为什么 B 站的弹幕可以不挡人物?
1 | div{ |
通过 mask-image 这个css 属性,通过AI 分析实时更新人物的虚拟图
MDN mask-image
Vue3 .native修饰符被弃除
1 | <child-component |
- 在编译的过程中 会给子组件添加对应的emit:[‘click’,close]
在使用npm安装软件是报异常 code EACCES , 其实就权限不足
1 | pm ERR! code EACCES |
解决办法
1 | sudo chown -R $USER /usr/local/lib/node_modules |
如何让input 重新聚焦
1 | <input |
需要让当前的 input 失去焦点一下再重新focus
Vue VSCode Snippets生成Vue模板代码使用大全
vbase 生成 template script style 三个模块基础模板
vdata 生成vue2 data 模块代码
v3mount 生成 vue3 mountd 模块代码
v3render 生成 vue3 render 模块代码
v3computed 生成 vue3 computed 模块代码
v3 会有其他vue3 相关指令提示
vbase-3-ts-setup
生成以下代码1
2
3
4
5
6
7
8
9
10
11
12
13<template>
<div>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped>
</style>importFromVue3 生成vue3 import代码
1
import { } from 'vue'
可以用 DevTools 的 queryObjects()函数测试是否有内存泄漏
1 | queryObjects(Promise) |
githooks 钩子没有被触发的原因
1 | [core] |
有可能之前安装了 .husky 后面又没用了把 hooksPath = .husky 这一行删除
.git hooks 里sample文件 的作用
pre-commit.sample文件看一下其中的内容,大致意思是说这是一个示例,做了一些格式方面的检测,这个脚本默认是不生效的,如果要生效,把文件名改为pre-commit即可
怎么写出优质的 JavaScript 代码?
指数幂
我们可以使用Math.pow()方法来得到一个数字的幂。有一种更短的语法来实现,即双星号 (**)。//Longhand
1 | const power = Math.pow(4, 3); // 64 |
数字分隔符
1 | // 旧语法 |
使用方法链(尤其是类)
播放器对象/类是这种情况,请使用方法链接。
需要做的就是从要链接的函数中返回对象的实例。
1 | class Player { |
代码可维护性、可复用性和可扩展性的区别
- 在《Java设计模式》一书中对
可维护性
的定义为:指软件能够被理解、改正、适应及扩展的难易程度。 - 对
可复用性
的定义为:指软件能够被重复使用的难易程度。
一般般说到可维护性指的是改正性维护,根据修复一个问题所花的平均时间和修复正确的百分比来衡量
广义上的可维护性也包括扩展可维护性,此时可扩展性是可维护性的一部分。(可以想见可理解性也是可维护性的一部分)
改正侧重改,扩展侧重增。
可维护性
可维护性表明了在软件中纠正一个缺陷或做一次更改的简易程度
。
可维护性取决于理解软件、更改软件和测试软件的简易程度,可维护性与灵活性密切相关。
高可维护性对于那些经历周期性更改的产品或快速开发的产品很重要。
你可以根据修复一个问题所花的平均时间和修复正确的百分比来衡量可维护性。
可扩展性
可扩展性反映软件适应“变化”的能力。
在软件开发过程中,“变化”是司空见惯的事情,如需求、设计的变化,算法的改进,程序的变化等等。
现代软件产品通常采用“增量开发模式”,不断推出新版本,获取增值利润。可扩展性越来越重要。
可扩展性是系统设计阶段重点考虑的质量属性。
谈到软件的可扩展性,开发人员首先想到的是怎样提高可扩展性,于是努力去设计很好的体系结构来提高可扩展性,却不考虑该不该做这件事。
从商业角度考虑,如果某个软件将不断地推出新版本,那么可扩展性很重要。
但是如果软件永远都不会有下个版本(一次性买卖),那么根本无需提高可扩展性。
一、变量
用有意义且常用的单词命名
对同一类型的变量使用相同的命名保持统一
每个常量都该命名(全大写)
避免无意义的命名
传参使用默认值
二、函数
函数参数( 最好 2 个或更少 )
如果参数超过两个,建议使用 ES6 的解构语法,不用考虑参数的顺序。1
2
3
4
5
6
7
8
9
10
11
12
13
14// Bad:
function createMenu( title, body, buttonText, cancellable ) {
// ...
}
// Good:
function createMenu( { title, body, buttonText, cancellable } ) {
// ...
}
createMenu({
title: 'Foo',
body: 'Bar',
buttonText: 'Baz',
cancellable: true
});一个方法只做一件事情
函数名上体现它的作用
删除重复代码,合并相似函数
使用 Object.assign 设置默认属性
1 | // Bad: |
用枚举来约定变量的使用与赋值
1 | enum Menu { |
every
every()方法的定义与用法:
every()方法用于检测数组中的所有元素是否都满足指定条件(该条件为一个函数)。
every()方法会遍历数组的每一项,如果有有一项不满足条件,则表达式返回false,剩余的项将不会再执行检测;如果遍历完数组后,每一项都符合条,则返回true。
1 | const a = [20,18,1,20,2] |
Husky钩子在SourceTree中报错:.husky/pre-commit: Line 4 npm: command not found
在命令行中可以正常commit,并正确触发钩子,但是,在SourceTree中,却报错了:
1 | .husky/pre-commit: Line 4 npm: command not found |
解决方法
找到所需命令所在路径,然后添加到~/.huskyrc文件中。
用以下命令自动创建文件并添加路径:
1 | echo 'export PATH="/usr/local/bin/:$PATH"' >> ~/.huskyrc |
参考文献
https://xmanyou.com/sourcetree-husky-npm-command-not-found/
TDD 驱动测试开发
- 测试驱动开发(Test-Driven Development,TDD)
T –> tasking
D –> tasking
D –> taskingmac 使用code命令打开VSCode
我们在mac的终端可以使用 open .打开文件夹
如果我们想用vs-code打开文件夹,用的命令是 code .,不过你得先按照code
安装code:打开VSCode –> command+shift+p –> 输入shell command –> 点击提示Shell Command: Install ‘code’ command in PATH运行
使用:打开终端,cd到要用VSCode打开的文件夹,然后输入命令code .即可打开
工程化方面
lerna:Lerna 是一个管理工具,用于管理包含多个软件包(package)的 JavaScript 项目。
prettier:Prettier 中文的意思是漂亮的、美丽的,是一个流行的代码格式化的工具。
tslint:TSLint 是可扩展的静态分析工具,用于检查 TypeScript 代码的可读性,可维护性和功能性错误。
commitizen & cz-conventional-changelog:用于帮助我们生成符合规范的 commit message。
husky:husky 能够防止不规范代码被 commit、push、merge 等等。
jest:Jest 是由 Facebook 维护的 JavaScript 测试框架。
coveralls:用于获取 Coveralls.io 的覆盖率报告,并在 README 文件中添加一个不错的覆盖率按钮。
vuepress:Vue 驱动的静态网站生成器,它用于生成 BetterScroll 2.0 的文档。
作者:阿宝哥
链接:https://juejin.cn/post/6876943860988772360
来源:稀土掘金
页面载入进度条
- 页面路由切换时,附带一个加载进度条会显得非常友好,不至于白屏时间过长,让用户以为页面假死。这时候我们可以用到nprogress,在路由切换时开启和关闭:import NProgress from ‘nprogress’;
1 | router.beforeEach(async (to, from, next) => { |
作者:codexu
链接:https://zhuanlan.zhihu.com/p/428497238
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
vite
如何加载依赖包?
在 ESModule 只会加载./
或者/
开头 的路径如何加载 SFC组件(.vue)?
第一步 vue文件 => template script (compiler-sfc))
是因为很多你想做的项目,要么在GitHub上已经有了,要么已经在文档中被人讨论过了,那为什么是你做?为什么你更有可能去做成?
玉伯说:这个问题的一个“政治正确”的答案是和你的业务有相关性,更实际的可能是和你这个人更有关系,是你内心想不想做,愿不愿意去长期的投入。
比如Ant Design、AntV,其实当时是集团更有机会去做的,因为集团有数据产品技术部,他们有很多业务,在这些业务土壤下是更有机会去长出这些项目的,但是他们缺人。所以对这个问题我的回答是,很多情况下,人的要素是比业务更重要的。只要你对事情是笃定想要去做的,大胆去做就好了。
可选链?.
,空值合并运算符??
- 空值合并操作符(
??
)是一个逻辑操作符,当左侧的操作数为null
或者undefined
时,返回其右侧操作数,否则返回左侧操作数。
1 | const foo = null ?? 'default string'; |
可选链式操作符(?.
) 与 ??
一样,可能为 undefined 与 null 的对象时,可选链式操作符非常有用。
1 | let foo = { someFooProp: "hi" }; |
动画卡顿分析
动画卡顿的原因
大多数设备的刷新频率是60次/秒,也就是1秒钟的动画是由60个画面连在一起生成的,所以要求浏览器对每一帧画面的渲染工作要在16ms内完成。当渲染时间超出16ms时,1秒钟内少于60个画面生成,就会有不连贯、卡顿的感觉,影响用户体验。
一个页面帧在客户端的渲染分为以下几步:
JavaScript:JavaScript实现动画效果,DOM操作等。
Style(样式计算):确认每个DOM元素应用的CSS样式规则。
Layout(布局):计算每个DOM元素最终在屏幕上的大小和位置。由于DOM元素的布局是相对的,所以当某个元素发生变化影响了布局时,其他元素也会随之变化,则需要回退重新渲染,这个过程称之为reflow。
Paint(绘制):在多个层上绘制DOM元素的文字、颜色、图像、边框和阴影等。
Composite(Render Layer合并):按照合理的顺序合并图层并显示到屏幕上。 浏览器在实际渲染页面的时候需要经过一系列的映射,由HTML页面构建出来的DOM树到最终的图层,映射过程如下图(来源:参考[3])所示(注意下图类名在后续有所更改,RenderObject->LayoutObject,RenderLayer->PaintLayer):
Node->RenderObject:DOM树的每个Node都有一个对应的RenderObject(一对一关系,RenderObject包含了Node的内容);
RenderObject -> RenderLayer:一个或多个RenderObject对应一个RenderLayer(多对一),RenderLayer用于保证元素之间的层级关系,一般来说位于同一位置的且层级相同的元素位于同一个Render Layer,只有某些特殊的RenderObject会专门创建一个新的渲染层,其他的RenderObject与第一个拥有RenderLayer的祖先元素共用一个。常见的生成RenderLayer的RenderObject拥有以下的一种特征
优化方法
结合页面渲染流程,这里将结合一些测试代码,分析动画的各种优化方案和效果:
JavaScript:优化JavaScript的执行效率
requestAnimationFrame代替setTimeout和setInterval
可并行的DOM元素更新划分为多个小任务
DOM无关的耗时操作放到Web Workers中
Style:降低样式计算复杂度和范围
降低样式选择器的复杂度
减少需要执行样式计算的元素个数
Layout:避免大规模、复杂的布局
避免频繁改变布局
用flexbox布局替代老的布局模型
避免强制同步布局事件
Paint/Composite:GPU加速
将移动或渐变元素由渲染层(RenderLayer)提升为合成层(Compositing Layer)
避免提升合成层的陷阱
JavaScript:优化JavaScript的执行效率
- requestAnimationFrame代替setTimeout和setInterval
为什么setTimeout和setInterval不好?
由于js是单线程执行,所以为了防止某个任务执行时间过长而导致进程阻塞,js中存在异步队列的概念,对于如setTimeout和ajax请求都是把进程放到了异步队列中,当主进程为空时才执行异步队列中的任务。所以 setTimeout和setInterval无法保证回调函数的执行时机,可能会在一帧之内执行多次导致多次页面渲染,浪费CPU资源甚至产生卡顿,或者是在一帧即将结束时执行导致重新渲染,出现掉帧的情况。
requestAnimationFrame是怎么优化的?
CPU节能,当页面被隐藏或最小化时,暂停渲染。
函数节流,其循环间隔是由屏幕刷新频率决定的,保证回调函数在屏幕的每一次刷新间隔中只执行一次。
优化效果具体如何?DEMO
通过chrome的performance面板查看具体表现的差别。
通过setTimeout进行了3次渲染,而且有长时间帧出现:
使用 requestAnimationFrameDOM操作部分合并,只进行了2次渲染,长时间帧也被优化:
requestAnimationFrame
1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。
2、在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。
作者:我是一个前端
链接:https://www.jianshu.com/p/fa5512dfb4f5
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
优化方法
querySelector和getElementById性能分析与使用选择
1 | console.time('querySelector'); |
querySelector的耗时明显多了好多
得到集合时间对比相差巨大。可是现在主流框架,比如jquery,手机上的框架jqmobi等内部实现查找元都是使用的querySelector,等方法,性能低的方法被使用唯一理由就是它用着方便。
- 得到的元素不是需要很麻烦的多次getElementBy..的话,尽量使用getElementBy..,因为他快些。
- 得到的元素需要很麻烦的多次getElementBy..组合才能得到的话使用querySelector,方便。
- 看实际情况,你决定方便优先还是性能优先,
URLSearchParams
1 | // Pass in a string literal |
vue-cli3 单独打包库
1 | vue-cli-service build --target lib --name port ['./src/_port/index.js'] |
1 | File Size Gzipped |
Node Sass could not find a binding for your current environment: OS X 64-bit with Node.js 6.x
进入project根目录,执行rebuild命令
1 | npm rebuild node-sass |
在 Mac 下安装 Node 与 NPM
安装 Node
1 | brew search node # 安装之前可以先看看 brew 支持的 node 版本 |
注意 安装 Node 的时候 NPM 会自动被安装,所以无需进行下一步。
安装 NPM
1 | brew search npm # 安装之前可以先看看 brew 支持的 npm 版本 |
安装 Node
1 | brew search node # 安装之前可以先看看 brew 支持的 node 版本 |
params动态路由传参
params动态路由传参一定要在路由中定义参数,然后在路由跳转的时候必须要加上参数,否则就是空白页面:
1 | { |
注意,params传参时,如果没有在路由中定义参数,也是可以传过去的,同时也能接收到,但是一旦刷新页面,这个参数就不存在了。这对于需要依赖参数进行某些操作的行为是行不通的,因为你总不可能要求用户不能刷新页面吧
在引用子组件里的 click 方法不生效
1 | <template> |
1 | <ion-button @click.native="primary()" color="primary">primary</ion-button> |
据Vue2.x
官方文档关于父子组件通讯的原则,父组件通过prop传递数据给子组件,子组件触发事件给父组件。但父组件想在子组件上监听自己的click的话,需要加上native修饰符
注意:Vue.3x 已经移除 v-on.native
commit-lint
可以帮助我们检查提交的 commit 信息,它强制约束我们的 commit 信息必须在开头附加指定类型,用于标示本次提交的大致意图,支持的类型关键字有:
- feat:表示添加一个新特性;
- chore:表示做了一些与特性和修复无关的「家务事」;
- fix:表示修复了一个 Bug;
- refactor:表示本次提交是因为重构了代码;
- style:表示代码美化或格式化;
CSS 变量教程
一、变量的声明
声明变量的时候,变量名前面要加两根连词线(–)。
1 | body { |
二、var() 函数
var()函数用于读取变量。
1 | body { |
三、作用域
1 | <html> |
1 | const isSupported = |
Proxy函数
Proxy 致代理最外层 对象
1 | var obj = { |
Proxy的优势如下
Proxy可以直接监听整个对象而非属性。
Proxy可以直接监听数组的变化。
Proxy有13中拦截方法,如ownKeys、deleteProperty、has 等是 Object.defineProperty 不具备的。
Proxy返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改;
Proxy做为新标准将受到浏览器产商重点持续的性能优化,也就是传说中的新标准的性能红利。
Object.defineProperty 的优势如下
兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 磨平。
Object.defineProperty 不足在于:
Object.defineProperty 只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。
Object.defineProperty不能监听数组。是通过重写数据的那7个可以改变数据的方法来对数组进行监听的。
Object.defineProperty 也不能对 es6 新产生的 Map,Set 这些数据结构做出监听。
Object.defineProperty也不能监听新增和删除操作,
vue3 源码大多是高阶函数, 做了类似柯里话函数
vue3 stup 为什么比mixin好用
- 如果组件内引用了多个mixin 后,无法知道 组件的数据属于哪个mixin,不好追踪到数据的来源
但是使用 setup 可以追踪到数据属于哪个 useFuntion - mixin 需要考虑到命名冲突,被其他mixin 里的方法或者data 替换
- setup 可以比较容易做类型推倒
vscode 代码片段
- 直接输入 ‘cl’ 就会直接生产 console.log(‘’)
- 直接输入 v3 会生成vue3 代码片段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<template>
<div>
</div>
</template>
<script>
export default {
setup () {
return {}
}
}
</script>
<style lang="scss" scoped>
</style>
CI/CD是什么?
- CI 持续集成(Continuous Integration)
- CD 持续交付(Continuous Delivery)
- CD 持续部署(Continuous Deployment)
CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法。CI/CD 的核心概念是持续集成、持续交付和持续部署。作为一个面向开发和运营团队的解决方案,CI/CD 主要针对在集成新代码时所引发的问题(亦称:“集成地狱”)。
具体而言,CI/CD 可让持续自动化和持续监控贯穿于应用的整个生命周期(从集成和测试阶段,到交付和部署)。这些关联的事务通常被统称为“CI/CD 管道”,由开发和运维团队以敏捷方式协同支持。
DevOps
DevOps是 Development和 Operations的组合,是一种思想、一组最佳实践、以及一种文化,用于促进应用开发、应用运维和质量保障(QA)部门之间的沟通、协作与整合。
React
1 | // in file /Users/chenxinxin/React/react/packages/react/src/ReactBaseClasses.js |
react的setState到底是同步还是异步?
setState本身并不是异步,只是因为react的性能优化机制体现为异步。在react的生命周期函数或者作用域下为异步,在原生的环境下为同步。
Rreact控制之外的事件中调用setState是同步更新的。比如原生js绑定的事件,setTimeout/setInterval等。
大部分开发中用到的都是React封装的事件,比如onChange、onClick、onTouchMove等,这些事件处理程序中的setState都是异步处理的。
Block formatting context(BFC)
(BFC MAN)[https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context]
BFC能解决什么问题
- 边距重叠问题 (父及添加
overflow:hideen
) - 盒子塌陷问题 (父及添加
overflow:hideen
) - float 没有高度,脱离文档流,清除浮动
- 浮动环绕文字问题
HMR(模块热替换)
我从 Vuejs 中学到了什么
- 参考链接-HcySunYang
框架要做到良好的 Tree-Shaking
那什么是 Tree-Shaking 呢?在前端领域这个概念因 rollup 而普及,简单的说所谓 Tree-Shaking 指的就是消除哪些永远不会执行的代码,也就是排除dead-code
,现在无论是 rollup 还是 webpack 都支持 Tree-Shaking。
想要实现 Tree-Shaking 必须满足一个条件,即模块必须是 ES Module,因为 Tree-Shaking 依赖 ESM 的静态结构。
vue 源码里用到以下等变量做 Tree-Shaking
1 | __VUE_OPTIONS_API__ |
VUE_OPTIONS_API 作用
- 在 Vue2 中我们编写的组件叫做组件选项 API:
1
2
3
4
5
6
7
8export default{
data(){},
// data 选项
computed:{},
// computed 选项
// 其他选项...
}
但是在 Vue3 中,更推荐使用 Composition API 来编写代码,例如:
1 | export default{ |
- 为了兼容 Vue2,在 Vue3 中仍然可以使用选项 API 的方式编写代码,但是对于明确知道自己不会使用选项 API 的用户来说,它们就可以选择使用 VUE_OPTIONS_API 开关来关闭该特性,这样在打包的时候 Vue 的这部分代码就不会包含在最终的资源中,从而减小资源体积。
使用 TS 的好处很多
如代码即文档、编辑器的自动提示、一定程度上能够避免低级 bug、让代码的可维护性更强等等。因此对 TS 类型支持的是否完善也成为评价一个框架的重要指标。
webpack
devtool
string false
- 选择一种 source map 格式来增强调试过程。不同的值会明显影响到构建(build)和重新构建(rebuild)的速度。
eval-source-map =>> 原始源代码
cheap-module-eval-source-map =>> 原始源代码(仅限行)
Warning: callback
is deprecated. Please return a promise instead.
1 | const handleCheckRePwd = (rules, value, callback) => { |
Observer(观察者模式)
Observer(观察者模式)属于行为型模式。
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
拿项目的 npm 依赖举例子:npm 包与项目是一对多的关系(一个 npm 包被多个项目使用),当 npm 包发布新版本时,如果所有依赖于它的项目都能得到通知,并自动更新这个包的版本号,那么就解决了包版本更新的问题,这就是观察者模式要解决的基本问题
举例子
对象与视图双向绑定
在 精读《设计模式 - Proxy 代理模式》 中我们也提到了双向绑定概念,只不过代理是实现双向绑定的一个具体方案,而观察者模式才是在描述双向绑定这个概念。
观察者模式在最初提出的时候,就举了数据与 UI 相互绑定的例子。即同一份数据可以同时渲染为表格与柱状图,那么当操作表格更新数据时,如何让柱状图的数据也刷新?从这个场景引出了对观察者模式的定义,即 “数据” 与 “UI” 是一对多的关系,我们需要一种设计模式实现当 “数据” 变化时,所有依赖于它的 “UI” 都得到通知并自动更新。
拍卖
拍卖由一个拍卖员与多为拍卖者组成。拍卖时,由 A 同学喊出的竞价(我出 100)就是观察者向目标发出的 setState 同时,此时拍卖员喊出(有人出价 100,还有更高的吗?)就是一个 notify 通知行为,拍卖员通知了现场竞价全员,刷新了他们对当前最高价的信息。
使用网页端 “vscode”阅读Github的源码
1s使用“vscode”阅读Github的源码
https://github.com/conwnet/github1s
在原有的github仓库地址中,对应的github后面加上1s,就可以使用,如https://github1s.com/microsoft/vscode。
source tree pull、push需要输入密码
打开Mac终端,以下命令:
1 | git config --global credential.helper osxkeychain |
Vue3 +ts
在Vue3+TS项目的script中用this访问变量报错Property ‘xxx(变量)’ does not exist on type ‘ …(vue的组件内容)’
解决方案:
在script中import { defineComponent } from ‘vue’
将 export default { … } 的形式改成 export default defineComponent({ … })的形式即可
TCP协议
因为在 TCP 通道里传输的数据只能是二进制形式的,所以我们必须将数据结构或对象转换成二进制串传递给对方,这个过程就叫「序列化」。而相反,我们收到对方的二进制串后把它转换成数据结构或对象的过程叫「反序列化」。而序列化和反序列化的规则就叫「协议」。
antd 自定义主题功能使用报错 .bezierEasingMixin(); ^ Inline JavaScript is not enabled. Is it set in your options
修改 less-loader 配置 : 增加 less-loader 配置子项 options.options.javascriptEnabled = true
1 | // vue cli 2 中定制主题 修改build/utils.js文件 |
css控制滚动条的样式,大小,颜色
1 | .my-scroll::-webkit-scrollbar { /滚动条整体样式/ |
Vue项目全局引用sass变量文件报错的解决办法
通常情况咱们的sass变量会以单独的文件存放。我们在使用这些变量的时候如果在每个组件中import引用的显得特别麻烦,而且感觉很蠢QAQ,但是全局引用的时候又会报错。这时就需要用到sass-resources-loader插件并进行相应的配置就可以解决问题
1 | module.exports = { |
vscode 快速跳转
在项目跟目录添加 jsconfig.json 文件
1 | { |
Visual studio Code 跳转定义返回快捷键
Windows
Alt + ← Navigate back
Alt + → Navigate forward
Mac
Ctrl + - Navigate back
Ctrl + Shift + - Navigate forward
vscode @ 路径提示
- 在vscode 扩展工具里安装Path Intellisense
- 选择edit in setting.json这个选项,进入下图,然后在右侧添加配置:“path-intellisense.mappings”: {
“@”: “${workspaceRoot}/src”
}
vue 2.x 使用 ts
导出枚举时不能使用 const?
1 | export enum ListDemo { |
特殊运算符 ~~
- 简单一点就是将一些变量转化为Number(数字)类型的;
- 数字类型的字符串可以转化为纯数字
- 字符串中带了其他字母,符号,或者其他除数字外的东西,一律输出 Number类型的0
- 任何boolen类型的,如果为TRUE则输出1,FALSE输出0;
- 特殊类型,转化为Boolean是true的输出1,转化为boolean是false的输出0;
1 |
|
这里还有一个需要注意的小知识点:不需要 px 转 rem 的情况,可以使用大写的 PX 作为单位。
编译时不会将其转化为 rem 单位,也可以通过 selectorBlackList 属性声明的 .norem 前缀的 class 类名,同样也不会被转化。
dependencies 与 devDependencies的区别
1 | yarn add lib-flexible -S // =>>> dependencies |
typescript
只是告诉大家为什么要用 Typescript,如果没有逻辑复用,没有面向抽象,Typescript 是没有任何使用价值的,只能用来恶心你的队友。
对象解构
1 | let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; |
vue debug 模式
1 | const isDebug_mode = process.env.NODE_ENV !== 'production'; |
提升效率的案例
认识的一个同事主要职责是负责工单域业务开发,我们能够想象到工单域没有那么的复杂,但是要面对接入N多个工单,这个工作量就很大,而且工单涉及到很多个性化的处理,每个工单状态和状态流转逻辑不一样,如何做到高效就是一个很有意思的话题,是否可以做到以低成本来支撑新业务的接入。
他的解法是用可视化配置的方式来实现不需要代码开发就可以完成一个新的工单的接入,把工单域的效率发挥的机制,价值也就显而易见的。
这是个提升效率的案例,我们也可以选择硬编码的方式来实现个性化的诉求,但不是一个优秀的解决方案,也没有留下技术资产。
在业务支撑中,忙的同时,也一定要给自己预留思考的时间,而且需要把自己的思考和总结去分享出来,再加工,刷新。
另外有些建议是:
- 找个适合的Mentor,寻求更多的人帮助,这个是在阿里特殊的优势,特有的资源,要用起来。
- 目标的实现路径往往还挺多的,找些合适的沟通,也给你点输入,来优化实现路径。
- 状态很重要,阶段性要奖励下自己,状态好了,做很多事情就很顺。
ES11 Promise.allSettled([]) 和 Promise.all([]) 的差别
- allSettled 返回的是成功的数组,包括每个promise 的执行状态和结果的对象 [{status: “fulfilled”, value: “p1”}1: {status: “fulfilled”, value: “p2”}]
- all 只要有一个promise为reject 则返回的都是reject,如果成功的话是,promise 执行的结果 [‘p1’,p2]
1
2
3
4
5
6
7
8
9
10
11
12
13
14const p1 = new Promise((res,rej)=>{setTimeout(()=>{res('p1')},2000)})
const p2 = new Promise((res,rej)=>{setTimeout(()=>{res('p2')},1000)})
Promise.allSettled([p1,p2])
Promise {<fulfilled>: Array(2)}__proto__: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: Array(2)0: {status: "fulfilled", value: "p1"}1: {status: "fulfilled", value: "p2"}length: 2__proto__: Array(0);
Promise.all([p,p2])
Promise {<fulfilled>: Array(2)}
__proto__: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: Array(2)
0: "p1"
1: "p222"
length: 2
异步(Promise)环境下错误处理方式
在 Promise 内部使用 reject 方法来处理错误,而不要直接调用 throw Error,这样你不会捕捉到任何的报错信息。
reject 如果使用 Error 对象,会导致捕获不到错误的情况,在我的博客中有讨论过这种情况:Callback Promise Generator Async-Await 和异常处理的演进,我们看以下代码:
1 | function thirdFunction() { |
AOP 模式
aop 是什么
aop又叫面向切面编程,主要作用是把一些和跟核心业务逻辑无关的功能包括日志统计、打点上报、异常处理等。把这些功能抽离出来后,再通过==动态织入==的方式掺入业务逻辑模块中。aop在js中是个被严重忽略的技术点。
aop有什么优势
aop的好处首先是可以保持我们业务逻辑模块的纯净和高内聚性,其次,可以很方便的复用日志统计等功能模块
1 | // 改造before函数 |
js调用轮询接口
1 | // polling-utils.js |
随手鸡汤
如果你待在原地过着安定平稳的生活,你的生活将是无趣,boring、
如果你可以避免 自我 和 盲点,。。。。。
performance :性能
memory: 内存
判断基本类型
1 | Object.prototype.toString.call(null); // "[object Null]" |
git 问题
error1: Updates were rejected because the tag already exists in the remote.
sourceTree , 把推送所有标签的打钩去掉
var x = 1, y = z = 0;
var add = (n) => {
return ++n+3
}
function add(n) {
return n++
}
y = add(x)
z=add(x)
Vue webpack-bundle-analyzer打包体积优化,详细分布查看插件
1 | // 1.npm 安装 |
ssh登录 The authenticity of host 192.168.0.xxx can’t be established. 的问题
用ssh登录一个机器(换过ip地址),提示输入yes后,屏幕不断出现y,只有按ctrl + c结束
错误是:The authenticity of host 192.168.0.xxx can’t be established.
以前和同事碰到过这个问题,解决了,没有记录,这次又碰到了不知道怎么处理,还好有QQ聊天记录,查找到一下,找到解决方案:
执行ssh -o StrictHostKeyChecking=no 192.168.0.xxx 就OK
网址是:
http://blog.ossxp.com/2010/04/1026/
记一下,防止又忘记了,又快到3点了,无数个不眠之夜啊。
2011/10/11
某天机器又改IP了,ssh后,报:
mmt@FS01:~$ ssh -o StrictHostKeyChecking=no 192.168.0.130
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
fe:d6:f8:59:03:a5:de:e8:29:ef:3b:26:6e:3d:1d:4b.
Please contact your system administrator.
Add correct host key in /home/mmt/.ssh/known_hosts to get rid of this message.
Offending key in /home/mmt/.ssh/known_hosts:38
Password authentication is disabled to avoid man-in-the-middle attacks.
Keyboard-interactive authentication is disabled to avoid man-in-the-middle attacks.
Permission denied (publickey,password).
注意这句
Add correct host key in /home/mmt/.ssh/known_hosts to get rid of this message.
执行:
mv /home/mmt/.ssh/known_hosts known_hosts.bak
再连:
ssh -o StrictHostKeyChecking=no 192.168.0.130
OK了!
你认为程序员从幼稚到成熟的过程是什么?
逐渐的认识到自己是真的菜,菜到你想转行,然后还不甘心的继续学习。– HcySunYang
element-ui的popover组件位置偏移
1、统一给popver固定的高度
2、boundariesElement真的很重要,记住一定要设置为viewport
1 | <el-popover |
boundariesElement真的很重要,记住一定要设置为viewport,默认的是body!
记住,获取到数据之后要this.$refs.dcPopover.updatePopper()一下(用来重新计算位置的)
el-table 设置 fixed=’right’
会导致hover 阴影出现位置错乱
运行vue报错There are multiple modules with names that only differ in casing.
There are multiple modules with names that only differ in casing.
This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.
Use equal casing. Compare these module identifiers:
如果遇到以上报错,请仔细检查/router/index.js中报错的vue组件文件路径的大小写是否正确
import Goods from ‘@/components/onekeyfollow/Goods’
数字数组转化为字符串数组或Number 数组
数字数组转化为字符串数组
1 | var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; |
字符串数组转化为数字数组
1 | var a = ['1', '2', '3', '4', '5', '6', '7', '8', '9'] |
文件预览或下载中,axios设置responseType:blob时对于后台报错信息的捕获兼容
当后台解析错误的时候,返回的就是正常的错误对象,包含错误码和错误信息,如果不做处理,那么错误状态和成功状态都是blob类型,无法捕获
因为返回分来 response 为
1 | { |
样式穿透
在开发中修改第三方组件样式是很常见,但由于 scoped 属性的样式隔离,可能需要去除 scoped 或是另起一个 style 。这些做法都会带来副作用(组件样式污染、不够优雅),样式穿透在css预处理器中使用才生效。
我们可以使用 >>> 或 /deep/ 解决这一问题:
1 | <style scoped> |
有些像 Sass 之类的预处理器无法正确解析 >>>。这种情况下你可以使用 /deep/ 或 ::v-deep 操作符取而代之——两者都是 >>> 的别名,同样可以正常工作。
[@vue/compiler-sfc] ::v-deep usage as a combinator has been deprecated. Use :deep(
1 | .a ::v-deep .b { |
百度地图
在安卓微信里获取经纬度不正确解决办法?
要用 域名 https ,因为受安全协议影响
es6提供了一个新的方法用于判断某个变量是否是整数
就是Number.isInteger()方法,用它就可以判断是否是整数了,注意ie是不支持的
函数防抖和节流的概念和真实项目中的应用场景
函数防抖(debounce):
在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时;典型的案例就是输入搜索:输入结束后n秒才进行搜索请求,n秒内又输入的内容,就重新计时。
立即执行版本
1 | function debounce (callback, wait) { |
举个例子–页面滚动
基于上述场景,首先提出第一种思路:在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms,然后:
• 如果在200ms内没有再次触发滚动事件,那么就执行函数
• 如果在200ms内再次触发滚动事件,那么当前的计时取消,重新开始计时
效果:如果短时间内大量触发同一事件,只会执行一次函数。
实现:既然前面都提到了计时,那实现的关键就在于setTimeOut这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现:
延时版
1 | /* |
- 对于短时间内连续触发的事件(上面的滚动事件),防抖的含义就是让某个时间期限(如上面的1000毫秒)内,事件处理函数只执行一次。
实际的应用
用户在输入搜索的时候不是每次输入都执行keyup的事件 而是用户输入1s后再执行请求的事件
1s之内用户再次输入的时候会从新计算时间
函数节流(throttle):
规定在一个单位时间内,只能触发一次函数,如果这个单位时间内触发多次函数,只有一次生效; 典型的案例就是鼠标不断点击触发,规定在n秒内多次点击只有一次生效。
立即执行版本
1 | function throttle (callback, wait) { |
延时版
1 |
|
实际的应用
滚动加载更多 在监听滚动条的位置的时候不是用户每次滚动都要去监听滚动条的位置的 而是例如2秒内不管你滚动多少次 我就监听一次滚动条的位置
其他应用场景举例
讲完了这两个技巧,下面介绍一下平时开发中常遇到的场景:
- 搜索框input事件,例如要支持输入实时搜索可以使用节流方案(间隔一段时间就必须查询相关内容),或者实现输入间隔大于某个值(如500ms),就当做用户输入完成,然后开始搜索,具体使用哪种方案要看业务需求。
- 页面resize事件,常见于需要做页面适配的时候。需要根据最终呈现的页面情况进行dom渲染(这种情形一般是使用防抖,因为只需要判断最后一次的变化情况)
图片懒加载
利用intersection observer 实现
class:用于在JavaScript中关联元素
src属性:指向了一张占位图片,图片在页面的第一次加载会显现
data-src和data-srcset属性:这是占位属性,里面放的是目标图片的ur
1 | <img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load-1x.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" alt="I'm an image!"> |
当DOMContentLoaded触发后,js会查询class为lazy的img元素。然后我们检测浏览器支不支持intersection observer,如果可以用,先创建一个observer,然后传入回调函数,回调函数将会在元素可见性变化时被调用。
或者用获取图片的可视高度 getBoundingClientRect
作者:Naeco
链接:https://www.jianshu.com/p/e86c61468285
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
vue 性能优化
vue 用的算法是找 最长递增子序列,而非 最长递增连续子序列,因为连续子序列不一定是最优解
(Leetcode 最长递增子序列)[https://leetcode-cn.com/problems/longest-increasing-subsequence/]
数组求最大值
1 | Math.max(1,2,3) |
v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
(1)v-for 遍历必须为 item 添加 key
在列表数据进行遍历渲染时,需要为每一项 item 设置唯一 key 值,方便 Vue.js 内部机制精准找到该条列表数据。当 state 更新时,新的状态值和旧的状态值对比,较快地定位到 diff 。
(2)v-for 遍历避免同时使用 v-if
v-for 比 v-if 优先级高,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候,必要情况下应该替换成 computed 属性。
它也可以用于强制替换元素/组件而不是重复使用它。当你遇到如下场景时它可能会很有用:
完整地触发组件的生命周期钩子
触发过渡
例如:
1 | <transition> |
当 text 发生改变时, 总是会被替换而不是被修改,因此会触发过渡。
(3)如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
事件的销毁
Vue 组件销毁时,会自动清理它与其它实例的连接,解绑它的全部指令及事件监听器,但是仅限于组件本身的事件。 如果在 js 内使用 addEventListene 等方式是不会自动销毁的,我们需要在组件销毁时手动移除这些事件的监听,以免造成内存泄露,如:
1 | created() { addEventListener('click',this.click,false)},beforeDestroy() { removeEventListener('click',this.click,false)}复制代码 |
第三方插件的按需引入
Webpack 对图片进行压缩
在 vue 项目中除了可以在webpack.base.conf.js中 url-loader 中设置 limit 大小来对图片处理,对小于 limit 的图片转化为 base64 格式,其余的不做操作。所以对有些较大的图片资源,在请求资源的时候,加载会很慢,我们可以用image-webpack-loader来压缩图片:
(1)首先,安装 image-webpack-loader
npm install image-webpack-loader –save-dev复制代码
(2)然后,在 webpack.base.conf.js 中进行配置:
1 | {test:/\.(png|jpe?g|gif|svg)(\?.*)?$/,use:[ {loader:'url-loader',options: {limit:10000,name: utils.assetsPath('img/[name].[hash:7].[ext]') } }, {loader:'image-webpack-loader',options: {bypassOnDebug:true, } } ]}复制代码 |
####提取公共代码
关于vue项目在build出现的问题
找到config文件夹下的index.js文件修改一下build中的
assetsPublicPath: ‘/‘,
改为assetsPublicPath: ‘./‘,(在/前加.)
2、背景图片路径不对
在css中写的background-img的路径出错 需要找到build文件夹下的utils.js,修改一下
1 | if (options.extract) { |
在这一段代码中添加:publicPath: ‘../../‘,改后如下:
1 | if (options.extract) { |
keep-alive的正确使用
组件按需加载
使用 CDN 外部加载资源
次优化主要是针对echarts,在其文档里也有提到按需加载,但是这次我们不用按需加载了,我想把echarts彻底干掉!我们这次要使用webpack的externals,参考这里
在webpack.base.config.js中,做如下改动
//webpack.base.config.js module.exports中增加externals对象
1 | module.exports = { |
作者:AllenN
链接:https://juejin.im/post/5b0033c9518825056508075f
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
尤大大聊 vue3.0-BETA
- 去 RFC 上了解
vue3.0
,可以更了解比较全面
- 性能提高 -performance
速度 比 vue2.0快2-3倍
Vue 3 Template Explorer 可以测代码被编译的东西
Vue composition api
2. 无用的不进入打包
3.
重排和重绘
理论上,每一次的dom更改或者css几何属性更改,都会引起一次浏览器的重排/重绘过程,而如果是css的非几何属性更改,则只会引起重绘过程。所以说重排一定会引起重绘,而重绘不一定会引起重排。
重排(Relayout/Reflow)
在弄明白什么是重排之前,我们要知道:浏览器渲染页面默认采用的是流式布局模型(Flow Based Layout),这一点很重要。
页面首次渲染。
浏览器窗口大小发生改变。
元素尺寸或位置发生改变。
元素内容变化(文字数量或图片大小等等)。
元素字体大小变化。
添加或者删除可见的DOM元素。
激活CSS伪类(例如::hover)。
设置style属性
查询某些属性或调用某些方法。
减少重排
避免设置大量的style属性,因为通过设置style属性改变结点样式的话,每一次设置都会触发一次reflow,所以最好是使用class属性
实现元素的动画,它的position属性,最好是设为absoulte或fixed,这样不会影响其他元素的布局
动画实现的速度的选择。比如实现一个动画,以1个像素为单位移动这样最平滑,但是reflow就会过于频繁,大量消耗CPU资源,如果以3个像素为单位移动则会好很多。
不要使用table布局,因为table中某个元素旦触发了reflow,那么整个table的元素都会触发reflow。那么在不得已使用table的场合,可以设置table-layout:auto;或者是table-layout:fixed这样可以让table一行一行的渲染,这种做法也是为了限制reflow的影响范围
css及动画处理
少用css表达式
减少通过JavaScript代码修改元素样式,尽量使用修改class名方式操作样式或动画;
动画尽量使用在绝对定位或固定定位的元素上;
隐藏在屏幕外,或在页面滚动时,尽量停止动画
作者:小白师兄
链接:http://www.imooc.com/article/45936
来源:慕课网
本文原创发布于慕课网 ,转载请注明出处,谢谢合作
为什么在foreach要抛异常才能停止
localStorage 是长效存储的,但是有的场景希望用它来实现数据缓存功能,并且像 cookie 一样可以设置时间,这该如何处理。比如:
1 | /** |
null和undefined的区别
- 在 if 语句中 null 和 undefined 都会转为false两者用相等运算符比较也是相等
1
2
3
4console.log(null==undefined); //true 因为两者都默认转换成了false
console.log(typeof undefined); //"undefined"
console.log(typeof null); //"object"
console.log(null===undefined); //false "==="表示绝对相等,null和undefined类型是不一样的,所以输出“false”
null
表示没有对象,即该处不应该有值
作为函数的参数,表示该函数的参数不是对象
作为对象原型链的终点
undefined表示缺少值,即此处应该有值,但没有定义
定义了形参,没有传实参,显示
undefined
对象属性名不存在时,显示
undefined
函数没有写返回值,即没有写return,拿到的是
undefined
写了return,但没有赋值,拿到的是undefined
null和undefined转换成number数据类型
null
默认转成 0undefined
默认转成NaN
链接:https://www.jianshu.com/p/7514e2d56661
对接扫码抢或者类似pos机出现拿到付款码没有支付的解决办法
- 很大的可能是因为你的付款码被取到后没有回车功能,所以碰到没法支付时一般会在付款码后缀加上
\n
\n
代表enter
或者 换行符1
2let faceCode='12334444'
faceCode=faceCode+'\n'
面向对象编程和面向接口编程
1.什么是面向接口编程?
面向接口英文名是 Interface Oriented Design 面向接口编程是开发程序的功能先定义接口,接口中定义约定好的功能方法声明,通过实现该接口进行功能的实现,完成软件或项目的要求.软件或项目随着时间的不断变化,软件的功能要进行升级或完善,开发人员只需要创建不同的新类重新实现该接口中所有方法,就可以达到系统升级和扩展的目的.
2.什么是面向对象编程
面向对象,英文名字叫Object Oriented,是一种软件开发方法。是和面向过程相对应的。特性就是封装、继承、多态、
什么是封装?
我们把「数据」和「能力」组合成一个对象的过程就叫做「封装」。
封装的结果就是可以有一个类,通过这个类我们可以获得一个对象。然后我们就可以通过给这个对象下命令,让他执行自己的「能力」。
除了把「数据」和「能力」封装成一个「对象」更加方便使用以外,还有啥其他的特点么?
封装只是面向对象的第一步,目的是把现实世界的东西抽象成对象。面向对象真正有威力的地方是「继承」和「多态」。
举一个不是很恰当,但是女朋友比较容易理解的例子。
我们使用外卖软件点餐,当我们第二次去某一家店时,外卖软件会提示你上一次你在这家点了什么,你可以点击<再来一单>把上次的菜品直接加到购物车中,这就是「继承」。而在购物车中的物品你可以直接付款下单,也可以把增删和修改菜品。这就是「多态」。
什么是继承?
在面向对象编程中,当两个类具有相同的特征(属性)和行为(方法)时,可以将相同的部分抽取出来放到一个类中作为父类,其它两个类「继承」这个父类。继承后子类自动拥有了父类的部分属性和方法。
通过继承创建的新类称为“子类”或“派生类”。
被继承的类称为“基类”、“父类”或“超类”。
比如:
狗{吠;}牧羊犬 继承 狗{放羊;}
上面的例子中,狗类是父类,牧羊犬类是子类。牧羊犬类通过继承获得狗类的吠的能力,同时增加了自己独有的放羊的能力。
什么是多态?
同一操作,作用于不同的对象,可以产生不同的结果,这就是「多态」。通常说的多态都是指运行期的多态,也叫动态绑定。
要实现多态,需要满足三个条件:
有类继承或接口实现、子类重写父类的方法、父类引用指向子类的对象。比如:
犬科动物{吠;}狗 继承 犬科动物{吠{旺旺旺}}狼 继承 犬科动物{吠{嗷嗷嗷}}
狗和狼都是犬科动物,拉来一直犬科动物,如果它你叫的话,你可能没办法直接分辨出他到底是狼还是狗。只要他真正的叫出来的时候,你才知道。这就是运行时多态。
有人说,你自己定义的对象,定义的时候不就知道到底是什么类的对象了么,这个其实并不决定的,很多时候我们可能不知道,原因是,对象可能并不是我们自己创建出来的。
3.面向接口编程与面向对象开发的区别:
面向对象开发:
UserDao dao = new UserDao();
假设项目开发中dao层的技术要升级改造,那么面向对象开发有两种实现方式
将UserDao中的代码删除,全部重写,但是方法名称不允许改变,为了不影响其他层,如service层调用dao的方法
创建一个新的类,如:UserDaoTwo 所有的方法名称照搬,用新技术重写方法体中的内容,但是需要调用dao层的位置,要全部更换为新的类,new UserDaoTwo();
面向接口编程:
UserDao dao = new UserDaoImpl();
1.项目需要升级改造时:
- 不需要修改原来的类,只要创建一个新的类,实现这个接口,以前的方法全部都有,只要重写方法体即可,不会漏写
- 为了不在调用dao处,修改多次,可以写为UserDao dao = 工具类.getImpl(); 这时如果我们项目升级过程中更改了实现类,只需要在工具类中修改一次,项目中就全部修改了
这时我们又发现,工具类中如果给多个接口返回实现类,就有如下代码冗余的问题:
1 | function getBean(){ |
4.面向接口编程的好处
降低了程序的耦合性.其能够最大限度的解耦,所谓解耦既是解耦合的意思,它和耦合相对。耦合就是联系,耦合越强,联系越紧密。在程序中紧密的联系并不是一件好的事情,因为两种事物之间联系越紧密,你更换其中之一的难度就越大,扩展功能和debug的难度也就越大。
易扩展. 我们知道程序设计的原则是对修改关闭,对新增开放.面向接口编程扩展功能只需要创建新实现类重写接口方法进行升级扩展就可以,达到了在不修改源码的基础上扩展的目的.
易维护
将对象的属性值保存为局部变量
对象成员嵌套越深,读取速度也就越慢。所以好的经验法则是:如果在函数中需要多次读取一个对象属性,最佳做法是将该属性值保存在局部变量中,避免多次查找带来的性能开销。
推荐:
1 | let person = { |
H5直接唤起照相机
- 使用input:file标签, 去调用系统默认相机,摄像,录音功能,其实是有个capture属性,直接说明需要调用什么功能
[参考链接](https://www.cnblogs.com/LisenH/p/11635919.html)
iOS最遵守遵守HTML5规范,其次是X5内核,安卓的webview基本忽略了capture。
理想情况下应该按照如下开发webview:
- 当accept=”image/*”时,capture=”user”调用前置照相机,capture=”其他值”,调用后置照相机
- 当accept=”video/*”时,capture=”user”调用前置录像机,capture=”其他值”,调用后置录像机
- 当accept=”image/,video/”,capture=”user”调用前置摄像头,capture=”其他值”,调用后置摄像头,默认照相,可切换录像
- 当accept=”audio/*”时,capture=”放空或者任意值”,调用录音机
- 当input没有capture时,根据accppt类型给出文件夹选项以及摄像头或者录音机选项
- input含有multiple时访问文件夹可勾选多文件,调用系统摄像头或者录音机都只是单文件
- 无multiple时都只能单文件
1
2
3
4
5
6
7
8
9
10
<input type="file" accept="image/*" capture="camera">
<input type="file" accept="video/*" capture="camcorder">
<input type="file" accept="audio/*" capture="microphone">
<!-- capture表示,可以捕获到系统默认的设备,比如:camera--照相机;camcorder--摄像机;microphone--录音。
accept表示,直接打开系统文件目录。 -->
ES6
super
- 作为函数时,super()只能用在子类的构造函数之中,用在其他地方就会报错。
1 | class A {} |
addEventListener()与removeEventListener()
通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除;移除时传入的参数与添加处理程序时使用的参数相同。通过addEventListener()添加的匿名函数无法移除,如下面的例子所示:
1 | var btn = document.getElementById("myBtn"); |
让video标签铺满div
1 | .video{ |
- 在VUE监听键盘事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43data() {
return {
orderNumber: '',
isEnter: false,
eventFn: null
}
},
mounted() {
this.eventFn = (event) => {
console.log(event)
var e = event || window.event || arguments.calle.caller.arguments[0]
if (this.isEnter) {
this.orderNumber = ''
this.isEnter = false
}
if (e && e.key === 'Enter') { // enter 键
// 要做的事情
this.isEnter = true
this.checkOrderNumber(this.orderNumber)
return console.log('enter', this.orderNumber)
} else if (e && e.key !== 'Enter') { // enter 键
// 要做的事情
this.orderNumber += event.key
}
}
window.addEventListener('keydown', this.eventFn)
},
methods: {
checkOrderNumber(val) {
indexApi.orderDestroy({ destroy: 1, orderNumbers: [val] }).then(res => {
if (res.code === 200) {
this.$toast.success('验票成功')
this.$emit('success')
} else {
this.$toast.fail(res.msg)
}
})
}
},
beforeDestroy() {
window.removeEventListener('keydown', this.eventFn)
}
}
缓存
设置浏览器缓存有下面几种方法
设置浏览器缓存有下面几种方法
Last-Modified:服务器上文件的最后修改时间
Etag:文件标识
Expires:本地缓存目录中,文件过期的时间(由服务器指定具体的时间)
Cache-control:本地缓存目录中,文件过期的时间(由服务器指定过期的间隔时间,由于浏览器根据间隔生成具体的时间)
刷新浏览器的方法
- reload 方法,该方法强迫浏览器刷新当前页面。
语法:location.reload([bForceGet])
参数: bForceGet, 可选参数, 默认为 false,从客户端缓存里取当前页。true, 则以 GET 方式,从服务端取最新的页面, 相当于客户端点击 F5(“刷新”)
reload() 方法用于重新加载当前文档。
如果该方法没有规定参数,或者参数是 false,它就会用 HTTP 头 If-Modified-Since 来检测服务器上的文档是否已改变。如果文档已改变,reload() 会再次下载该文档。如果文档未改变,则该方法将从缓存中装载文档。这与用户单击浏览器的刷新按钮的效果是完全一样的。
- replace 方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,你不能通过“前进”和“后退”来访问已经被替换的URL。
语法: location.replace(URL)
通常使用: location.reload() 或者是 history.go(0) 来做。
此方法类似客户端点F5刷新页面,所以页面method=”post”时,会出现”网页过期”的提示。
因为Session的安全保护机制。
当调用 location.reload() 方法时, aspx页面此时在服务端内存里已经存在, 因此必定是 IsPostback 的。
如果有这种应用: 需要重新加载该页面,也就是说期望页面能够在服务端重新被创建,期望是 Not IsPostback 的。
这里,location.replace() 就可以完成此任务。被replace的页面每次都在服务端重新生成。
代码: location.replace(location.href);
返回并刷新页面:
location.replace(document.referrer);
document.referrer //前一个页面的URL
不要用 history.go(-1),或 history.back();来返回并刷新页面,这两种方法不会刷新页面。
3. Javascript刷新页面的几种方法:
1,history.go(0)
2,location.reload()
3,location=location
4,location.assign(location)
5,document.execCommand(‘Refresh’)
6,window.navigate(location)
7,location.replace(location)
8,document.URL=location.href
number不能设置为属性
1 | Uncaught (in promise) TypeError: Cannot create property '__' on number '154' |
iview Table默认选中方法
1 | this.$refs.table.$refs.tbody.objData[index]._isChecked = true; |
封装findIndex
1 | Array.prototype.findIndex(array, callback) { |
VUE v-model
- v-model虽然很像使用了双向数据绑定的 Angular 的 ng-model,但是 Vue 是单项数据流,v-model 只是语法糖而已:↓
1 | <input v-model="sth" /> |
这是 HTML5 新增加的,类似 onchange ,每当输入框内容发生变化,就会触发 oninput ,把最新的value传递给 sth
如果你不知道 $event 是从哪来的,那你需要点击它再复习一下文档。
1 | <div id="demo"> |
1 | <currency-input v-model="price"></currentcy-input> |
- 在 Vue 2.2 版本,你可以在定义组件时通过 model 选项的方式来定制 prop/event:↓
1 | <my-checkbox v-model="foo"></my-checkbox> |
scoped样式穿透
scoped虽然避免了组件间样式污染,但是很多时候我们需要修改组件中的某个样式,但是又不想去除scoped属性。
- 使用/deep/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19//Parent
<template>
<div class="wrap">
<Child />
</div>
</template>
<style lang="scss" scoped>
.wrap /deep/ .box{
background: red;
}
</style>
//Child
<template>
<div class="box"></div>
</template>
`
对象的复制
浅复制
- 浅拷贝时,改变属性的属性值,改变原对象
1 | let target = {a: 123}; |
深复制
1 | let obj = { |
对数组深拷贝之后,改变原数组不会影响到拷贝之后的数组。
但是该方法有以下几个问题:
(1)会忽略 undefined
(2)会忽略 symbol
(3)不能序列化函数
(4)不能解决循环引用的对象
(5)不能正确处理new Date()
(6)不能处理正则
其中(1)(2)(3) undefined
、symbol
和函数这三种情况,会直接忽略。
1 |
|
css总结
解决移动端1px的问题
由于分辨率 DPI 的差异,高清手机屏上的 1px 实际上是由 2×2 个像素点来渲染,有的屏幕甚至用到了 3×3 个像素点
所以 border: 1px 在移动端会渲染为 2px 的边框
虽然用户在实际使用的时候,很难发现这 1px 的差异,但是设计师往往会在这 1px 上较劲,这就产生了经典的 “一像素问题”
最简单的解决办法,就是用图片做边框,只是修改颜色不太方便。除此之外,还有两种常用的办法
一、transform:scale
1 | .border-bottom{ |
二、viewport
网页的内容都渲染在 viewport 上,所以设备像素比的差异,直接影响的也是 viewport 的大小
通过 js 获取到设备像素比,然后动态添加 标签
1 | <script type="text/javascript"> |
使用display:inline-block,出现元素高度错位
- ‘inline-block’的baseline是其在normal flow中的最后一个line box的baseline,除非它没有in-flow line boxes,或者其‘overflow’属性不等于‘visible’,这种情况下,其baseline位于bottom margin边上。
解释如下:
i) 如果inline-block的overflow设为visible(默认属性),则其baseline是当前行的containing block的baseline。
ii) 如果overflow设为其他,则其bottom margin位于前行的containing block的baseline;
我们这种情况下,inline-block元素的overlow:hidden,所以元素的底部边框在父元素的baseline。
因此高度才会看起来增加了。
- 调整方法,就是为他们指定基准线,加’vertical-align:top’
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<style>
.left{
display:inline-block;
height:110px;
width:110px;
}
.right{
display:inline-block;
height:110px;
width:110px;
vertical-align:top
}
</style>
<div class='container'>
<div class="left"></div>
<div class="right"></div>
css调用系统调试盘
1 | <html lang="en"><head> |
句子
You are the owner of your career.
你是你职业发展的责任人。这句话潜台词是,你(不是你老板,也不是你爸妈,也不是你女朋友)是你职业发展的责任人。
vue的虚拟DOM
Vue的核心是双向绑定和虚拟DOM(下文我们简称为vdom),vdom是树状结构,
其节点为vnode,vnode和浏览器DOM中的Node一一对应,通过vnode的elm属性可以访问到对应的Node。
Vue 所有改变的元素都是vdom上操作,然后vue会把所有要改变的元素放到一个队列,然后通过diff算法,最终一次append到Dom
1 | document.getElementById('myId').appendChild(myNewNode); |
更新DOM是非常昂贵的操作
为什么需要虚拟DOM?
DOM是很慢的,其元素非常庞大,页面的性能问题鲜有由JS引起的,大部分都是由DOM操作引起的。如果对前端工作进行抽象的话,主要就是维护状态和更新视图;而更新视图和维护状态都需要DOM操作。其实近年来,前端的框架主要发展方向就是解放DOM操作的复杂性
理解虚拟DOM
虚拟的DOM的核心思想是:对复杂的文档DOM结构,提供一种方便的工具,进行最小化地DOM操作。这句话,也许过于抽象,却基本概况了虚拟DOM的设计思想
参考资料
vue v-if
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
父组件在子组件使用v-if时,向子组件传值时,要使用异步传值,
1 | <add-card-slot v-if="addCardSlot.show" |
1 |
|
vue data里使用对象时的响应式原理
-受现代 JavaScript 的限制 (而且 Object.observe 也已经被废弃),Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它
,这样才能让它是响应的。例如:
1 | var vm = new Vue({ |
-Vue 不允许在已经创建的实例上动态添加新的根级响应式属性 (root-level reactive property)。然而它可以使用 Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上:
- 有时你想向一个已有对象添加多个属性,例如使用 Object.assign() 或 _.extend() 方法来添加属性。但是,这样添加到对象上的新属性不会触发更新。在这种情况下可以创建一个新的对象,让它包含原对象的属性和新的属性:
1 | // 代替 `Object.assign(this.someObject, { a: 1, b: 2 })` |
Vue-watch问题
1.出现数组监听不到问题时的解决办法
- 因为 Vue 不能侦测的是直接对著数组的某个索引赋值,例如 replys[1] = {},但是你这边是对数组里面的某个元素赋值, Vue 是可以侦测到的,Vue是通过监测 get, set 来得知数据是否更新,而数组的索引是没有 get、set。
1
2
3
4
5
6// 先通过Object.assign()方法负值给新数组
let goodsArr = Object.assign([], this.goodList)
let localData = goodsArr[index].childList[j]
goodsArr[index].childList[j].addNum += 1
// 改变新数组的对象,然后再负值给旧数组 。z这样vue就可以监听到当前数组的变化
this.goodList = goodsArr
声明响应式属性
注意:
-由于 Vue 不允许动态添加根级响应式属性,所以你必须在初始化实例前声明根级响应式属性,哪怕只是一个空值:
1 | var vm = new Vue({ |
如果你未在 data 选项中声明 message,Vue 将警告你渲染函数正在试图访问的属性不存在。
这样的限制在背后是有其技术原因的,它消除了在依赖项跟踪系统中的一类边界情况,也使 Vue 实例在类型检查系统的帮助下运行的更高效。而且在代码可维护性方面也有一点重要的考虑
:data 对象就像组件状态的概要,提前声明所有的响应式属性,可以让组件代码在以后重新阅读或其他开发人员阅读时更易于被理解
。
iview 复选框单当单选框用,且可以取消当前的勾选
1 | <CheckboxGroup @on-change='doLevelGroup' |
Why review code?(为什么需要代码评审)
A friend asked me recently why it s valuable to do code review. Most Silicon Valley tech companies, at least, do code review on every change to get at least two sets of eyes on it. At one of my earlier jobs we did opt-in code review (rarely) for a while, then a new employee coming from Google joined us and encouraged us to review all our code which we did. It was a great decision. If you do it right, code review shouldn t feel onerous. You and your reviewer aren t adversaries; you re working together to build the best software you can together. (It s important to not take feedback personall
最近一个朋友问我,为什么做代码评审很有价值。至少,大多数硅谷的科技公司都会对每一个变更进行代码审查,以获得至少两组关注。在我早期的一个工作中,我们做了一段时间的代码评审(很少),然后一个来自谷歌的新员工加入了我们,并鼓励我们评审我们所做的所有代码。这是一个伟大的决定。如果你做得对,代码评审就不会觉得繁重。你和你的审稿人不是对手;你们在一起工作,共同构建最好的软件。不要把反馈当成针对个人的,这一点很重要## 缓存
设置浏览器缓存有下面几种方法
设eload 方法,该方法强迫浏res:本地缓存目录中,文件过期的时间(由服务器指定具体的时间)
置浏览器缓存有下面几种方法
Last-Modified:服务器上文件的最后修改时间
Etag:文件标识
Expires:本地缓存目录中,文件过期的时间(由服务器指定具体的时间)
Cache-control:本地缓存目录中,文件过期的时间(由服务器指定过期的间隔时间,由于浏览器根据间隔生成具体的时间)
刷新浏览器的方法
- r
酷 壳 – COOLSHELL -陈皓
“在你40岁,在父亲病重,孩子上学问题、房贷并未还清、你是全家唯一收入来源之类的中年危机的情况下,辞去你现在的工作,不加入任何一家公司,不用自己的任何一分钱积蓄,不要任何人的投资和帮助。只通过自己的技术能力,为别人解决相应的技术难题(不做任何无技术含量的外包项目),来生存养家,并除了能照顾好自己的家人没有降低自己的生活水平之外,还能再养活3个每人年薪36万元的工程师”作者博客
1)软件工程师分工分得越细这个团队就越没效率,团队间的服务化是关键的关键。不管是从语言上还是从软件模块上的人员分工,越细越糟糕。服务化不是我要帮你做事,而是我让你做起事来更容易。
2)你总需要在一个环节上认真,这个环节越往前就越有效率,越往后你就越没效率。要么你设计和编码认真点,不然,你就得在测试上认真点。要是你设计、编码、测试都不认真,那你就得在运维上认真,就得在处理故障上认真。你总需要在一个地方认真。另外一篇文章你可以看一下——《多些时间少写些代码》
3)“小而精的团队”+“条件和资源受限”是效率的根本。只有团队小,内耗才会小,只有条件或资源受限,才会逼着你去用最经济的手段做最有价值的事,才会逼着你喜欢简单和简化。
4)技术债是不能欠的,要残酷无情地还债。很多事情,一开始不会有,那么就永远不会有。一旦一个事情烂了,后面只能跟着一起烂,烂得越多,就越没有人敢去还债。
5)软件架构上要松耦合,团队组织上要紧耦合。
6)工程师文化是关键,重视过程就是重视结果。只重视结果的KPI等同于“竭泽而渔”和“饮鸩止渴”。
iview form表单提交的问题
prop 的值要和 form里的key相对应
控制光标位置
1 |
|
点击按钮让;input获取焦点
1 |
|
移动端的知识
1、apple-mobile-web-app-capable
apple-mobile-web-app-capable是设置Web应用是否以全屏模式运行。
1 | <meta name="apple-mobile-web-app-capable" content="yes"> |
- 如果content设置为yes,Web应用会以全屏模式运行,反之,则不会。content的默认值是no,表示正常显示。你可以通过只读属性window.navigator.standalone来确定网页是否以全屏模式显示。
2、顶部状态栏背景色
1 | <meta name="apple-mobile-web-app-status-bar-style" content="black" /> |
- 除非你先使用apple-mobile-web-app-capable指定全屏模式,否则这个meta标签不会起任何作用。
如果content设置为default,则状态栏正常显示。如果设置为blank,则状态栏会有一个黑色的背景。如果设置为blank-translucent,则状态栏显示为黑色半透明。如果设置为default或blank,则页面显示在状态栏的下方,即状态栏占据上方部分,页面占据下方部分,二者没有遮挡对方或被遮挡。如果设置为blank-translucent,则页面会充满屏幕,其中页面顶部会被状态栏遮盖住(会覆盖页面20px高度,而iphone4和itouch4的Retina屏幕为40px)。默认值是default。
3、桌面图标
1 | <link rel="apple-touch-icon" href="touch-icon-iphone.png" /> |
- 图片尺寸可以设定为5757(px)或者Retina可以定为114114(px),ipad尺寸为72*72(px)
4、启动画面
1 | <link rel="apple-touch-startup-image" href="start.png"/> |
- iOS下页面启动加载时显示的画面图片,避免加载时的白屏。
可以通过madia来指定不同的大小
1 | <!--iPhone--> |
移动端 HTML5 audio autoplay 失效问题
- 这个不是 BUG,由于自动播放网页中的音频或视频,会给用户带来一些困扰或者不必要的流量消耗,所以苹果系统和安卓系统通常都会禁止自动播放和使用 JS 的触发播放,必须由用户来触发才可以播放。
解决方法思路:先通过用户 touchstart 触碰,触发播放并暂停(音频开始加载,后面用 JS 再操作就没问题了)。
解决代码:
1 | document.addEventListener('touchstart', function () { |
H5 苹果手机滚动卡顿问题
1 | * { |
iview Modal用loading解决点击确定时关闭modal
1 | <template> |
VUE中的name
- 当项目使用keep-alive时,可搭配组件name进行缓存过滤
1 | export default { |
- 当你用vue-tools时
vue-devtools调试工具里显示的组见名称是由vue中组件name决定的
$attrs
1 | <input |
Vue点击子元素方法影响父元素方法
1 | <label class="ml5" |
Vue 父组件和子组件的生命周期
一、没有任何任何显示与隐藏限制条件的情况下:
1.运行的顺序依次是:
父组件created→父组件beforeMounted→子组件created→子组件beforeMounted→子组件mounted→父组件mounted;
二、当用v-show来控制子组件显示与隐藏的时候:
1.当用v-show=’show’,当show的默认值为true,执行顺序同上;
2.当用v-if=’show’,当show的默认值为true,执行顺序依然同上;
3.当用v-show=’show’,当show的默认值为false,无论在父组的生命周期(created,beforeMount)将show 变为true,执行的顺序依然如上;
5.当用v-show=’show’,当show的默认值为false,当在父组件的(mounted)生命周期将show变为true,执行顺序将会变为:父组件created→父组件beforeMounted→子组件created→子组件beforeMounted→子组件mounted→→父组件mounted→父组件beforeUpdated→父组件updated;;
4.当用v-if=’show’,当show的默认值为false,当在父组件的(created,beforeMount)生命周期将show变为true,执行顺序依然如上;
5.当用v-if=’show’,当show的默认值为false,当在父组件的(mounted)生命周期将show变为true,执行顺序将会变为:父组件created→父组件beforeMounted→父组件mounted→父组件beforeUpdated→子组件created→子组件beforeMounted→子组件mounted→父组件updated;
综上:1.vue项目里面在mounted以前的周期内的变化是不会触发updated的,只有在mounted才可以;
2.希望当触发某个条件的时候再进行子组件渲染的时候,那就采用v-if吧,这也是v-if,v-show的区别之一吧;
mounted
注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted:
Vue.js2.0中子组件修改父组件传递过来的props,并不影响父组件的原始数据
vue2.0中,子组件中不能修改父组件的状态,否则在控制台中会报错。
但是经我测试发现,这仅限于props为非数组及对象等引用类型数据,譬如字符串,数字等
如果props是对象或数组的话,在子组件内修改props的话,父组件是不会报错的。
那么要怎么解决修改props传的值而不污染父组件的值:
1,可以使用ES6提供的Object.assign({}, prop)的返回值就是一个全新的对象,操作这个新对象不会影响旧对象。如果不用ES6就自己递归实现拷贝器
2,可以给对象重新赋值:(给对象里的每一项重新赋值)
关于npm安装包几个问题
npm install X:
会把X包安装到node_modules目录中
不会修改package.json
之后运行npm install命令时,不会自动安装X
npm install X –save:
会把X包安装到node_modules目录中
会在package.json的dependencies属性下添加X
之后运行npm install命令时,会自动安装X到node_modules目录中
之后运行npm install –production或者注明NODE_ENV变量值为production时,会自动安装msbuild到node_modules目录中
npm install X –save-dev:
会把X包安装到node_modules目录中
会在package.json的devDependencies属性下添加X
之后运行npm install命令时,会自动安装X到node_modules目录中
之后运行npm install –production或者注明NODE_ENV变量值为production时,不会自动安装X到node_modules目录中
const
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。
const 无法改变指针的指向。
在let和const之间,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。
const优于let有几个原因。一个是const可以提醒阅读程序的人,这个变量不应该改变;另一个是const比较符合函数式编程思想,运算不改变值,只是新建值,而且这样也有利于将来的分布式运算;最后一个原因是 JavaScript 编译器会对const进行优化,所以多使用const,有利于提高程序的运行效率,也就是说let和const的本质区别,其实是编译器内部的处理不同
我们在javascript中有3种声明变量的方式:var,let,const;
其中var和let声明的是变量,而const声明的叫做常量,那我们想一个问题,我们声明一个变量后,我们不去管它,不去修改它,那它不就也是所谓意义上的常量了吗,为什么还要存在const呢?
解答:首先,const它有一个独特的存放值的空间,而var和let就没有,我们用const声明的常量都会放到它独有的空间里面,当我们跑代码的时候,如果我们用的是var或let声明的变量,我们电脑找一个变量的时候,就会一个一个的去找,因为javascript是单线程的,代码会从上往下依次执行,所以找起来就会很慢,但当我们用const的时候,电脑就会默认从它独有的空间里去找,就快了很多,没有去跑那些不必要跑的路。
如何编写高性能的 JavaScript?
- 遵循严格模式:”use strict”;
- 将 js 脚本放在页面底部,加快渲染页面
- 将 js 脚本将脚本成组打包,减少请求
- 使用非阻塞方式下载 js 脚本
- 尽量使用局部变量来保存全局变量
- 尽量减少使用闭包
- 使用 window 对象属性方法时,省略 window
- 尽量减少对象成员嵌套
- 缓存 DOM 节点的访问
- 通过避免使用 eval() 和 Function() 构造器
- 给 setTimeout() 和 setInterval() 传递函数而不是字符串作为参数
- 只要有可能尽量使用直接量创建对象和数组的字变量表达方式来消除不必要的语句
- 最小化重绘(repaint)和回流(reflow)
JavaScript parseInt() 函数
parseInt() 函数可解析一个字符串,并返回一个整数。
当参数 radix(若为数值,就是当前值的进制,比如为2,那就是按二进制解析) 的值为 0,或没有设置该参数时,parseInt() 会根据 string 来判断数字的基数。
当忽略参数 radix , JavaScript 默认数字的基数如下:
如果 string 以 “0x” 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数。
如果 string 以 0 开头,那么 ECMAScript v3 允许 parseInt() 的一个实现把其后的字符解析为八进制或十六进制的数字。
如果 string 以 1 ~ 9 的数字开头,parseInt() 将把它解析为十进制的整数。
parseInt(string, radix)
1 | document.write(parseInt("10") + "<br>"); |
快速排序
1 |
|
使用BEM命名规范来组织CSS代码
- BEM 是 Block(块) Element(元素) Modifier(修饰器)的简称
使用BEM规范来命名CSS,组织HTML中选择器的结构,利于CSS代码的维护,使得代码结构更清晰(弊端主要是名字会稍长
js命名关于大小写规范
1.常量:全部大写 NUM
2.变量:(1)小写+下划线
(2)驼峰式
3.方法:小写+下划线 compare_two_num
4.对象:驼峰式 Activity
5.数据库表名:小写+下划线,表名始终是复数形式的 users
面试
一行代码实现数组去重?
new Set();
1 |
|
JavaScript – forEach不改变原数组但是改变对象属性的问题
- forEach(item, index, arr),三个参数,如果直接用item=xxx是无法改变原数组的,但是如果用arr[index]就可以改变原数组。
1 |
|
- 数组里面的子元素是对象,那么是可以改变对应属性的
1 |
|
阿里的故事
阿里 P 的英文单词 是 profession ;
(需要专门技能,尤指需要较高教育水平的某一) 行业,职业; (某) 职业界; 业内人士; 同业; 同行; 同人; (统称,指需要较高教育水平的) 职业;
阿里面试要求
1、阿里云大数据前端团队(DTUX)主要负责阿里云大数据开发平台(数加)
1、关注用户体验,不断改进服务的易用性;
2、不需要关注陈旧的浏览器的兼容性
3、用最前沿的前端技术与算法团队一起探索未来多种平台的前端交互方式
4、参与前端框架建设,并不断优化前端工具链
5、改进协作流程,创建技术标准和规范;
6、参与新人培训和前端技术布道。
职位要求:
1、2年以上开发经验,能熟练使用常见类库或框架,编写高质量的前端代码;
2、熟练掌握 React 、Angular 、Vue 及相关框架和技术;
3、熟练掌握 CSS3 、HTML5 、ES6 、Gulp 、Webpack 等规范和技术;
4、熟悉 Node.JS ,有 Node.JS 开发经验,熟悉 Express\Koa 等框架优先;
5、熟练使用 Canvas 、 SVG 、 D3.js 等可视化技术者优先;
6、有 WebVR 、WebGL 、Three.js 经验者优先;
7、有浏览器端音频、视频、图像处理经验者优先;
8、有前端深度优化或者大型网站开发经验者优先;
9、有广泛使用的开源项目优先
2、iHome业务
职位要求:
- 前端技术扎实,技术专研能力强,对新事物和技术热情高,熟悉主流的思想。
- 在工程领域,前端框架(react,vue),全栈,移动,动画等领域有一项或是多项有深入研究(不仅仅只是使用)。
- 执行力强,有良好的分析,总结能力。能够有效识别痛点,并找到有效的解决方案。
- 具备良好的团队协作精神,能利用自身技术能力提升团队整体研发效率,提高团队影响力。
- 在理解产品业务的基础上,提升产品的用户体验,技术驱动业务的发展。
3、前端开发专家
岗位描述:
1、负责阿里巴巴集团内客户端系统的研发。
2、参与阿里巴巴集团内客户端框架及应用组件的规划与设计。
3、提升集团信息系统的整体用户体验和前端技术实力。
4、进行基于html5及移动互联网技术的技术论证和发展规划。
岗位要求:
1、至少3年前端开发的工作经验,有大型网站的前端架构部署和实践经验
2、精通至少一门非Web前端语言,对前后端合作模式有深入了解并有项目经验
3、善于沟通,有良好的文档写作能力,口头沟通能力,良好的团队合作精神,良好的抽象思维,理性地做出技术决策,具有风险控制意识
4、熟悉多种JavaScript框架及对它们适用的范围及优劣有独到见解
4、职位描述
杭州1-3年本科
职位描述
• 方向一:全栈售卖中台,参与抽象售卖的核心层、场景层、开放api层的建设
• 方向二:自动化营销中台,参与可视化配置营销体系、底层营销自动化配置体系建设
• 方向三:生态体系,参与社区、云市场、云栖大会等建设
• 方向四:平台架构组,参与工程化工具、框架、数据平台等建设
岗位要求
• 两年以上互联网行业前端工作经验;
• 基础编程知识牢靠,熟悉面向对象编程、熟悉函数式编程;
• 前端技术扎实,关注对新事物和技术,熟悉主流前端开发思想;
• 擅长 JavaScript,熟悉 ES2015,擅长 CSS,了解相关的前端生态;
• 擅长 React,了解 React 的核心思想,熟悉 Redux/MobX 理解它们解决的问题;
• 了解前端模块化,能够编写出易于维护的前端代码;
• 熟悉 Node.js,能够用 Node.js 编写工程工具或 Restful API
• 会使用 Webpack 或 Gulp 等前端构建工具实现开发流程自动化;
• 了解测试的重要性,熟悉测试驱动开发,熟练编写单元测试、E2E 测试;
• 熟练使用常用的 Git 操作,熟悉基于 Git 的常见协作规范及流程;
• 执行力强,有良好的分析、总结能力,能够有效识别痛点、并找到的解决方案;
• 良好的团队协作精神、利用自身技术能力提升团队整体研发效率;
5、
杭州1-3年本科
岗位要求 :
- 大学本科学历,2年以上开发经验,能熟练使用常见类库或框架,编写高质量的前端代码;
- 熟练掌握React、Redux及相关框架和技术,有单页面应用开发经验;
- 精通ES6,gulp,webpack等规范和技术;
- 熟悉NodeJS,有NodeJS开发经验,熟悉Express\koa等框架;
- 善于 Web 性能优化与前端效果的实现;
- 良好的团队合作精神和积极主动的沟通意识,具有很强的学习能力和对新技术的追求精神,乐于分享;
- 有大型网站开发经验者优先。
- 较强的自我管理能力,抱有积极的学习心态,乐于分享知识,喜欢沟通。
团队介绍
我们是一支极具活力、怀揣梦想的UED团队,涵盖视觉/交互设计、PC/无线/服务端开发、前端架构、用户体验等领域于一体的阿里巴巴UED团队
我们专注企业级应用的UI框架研发,建设领先的前端基础设施,丰富的可视化经验积累,服务于阿里巴巴双十一大型活动的数据大屏研发
6、
杭州3-5年本科
职位描述
阿里巴巴计算平台事业部数加前端团队岗位描述:
阿里巴巴计算平台事业部 IDE 前端团队主要负责阿里巴巴 WebIDE(https://app.data.aliyun.com),在这里你将接触到复杂前端应用架构,这里也给你提供了一个充分发挥技术能力的试验田;如果你有相关 WebIDE 开发经验、或者你对 VsCode 源码有深入的理解,欢迎您加入我们的团队!
1、关注用户体验,不断改进服务的易用性;
2、不需要关注陈旧的浏览器的兼容性;
3、用最前沿的前端技术与算法团队一起探索未来多种平台的前端交互方式;
4、参与前端框架建设,并不断优化前端工具链;
5、改进协作流程,创建技术标准和规范;
6、参与新人培训和前端技术布道;
岗位要求:
1、3年以上开发经验,能熟练使用常见类库或框架,编写高质量的前端代码;
2、熟练掌握 React 、Angular 、Vue 及相关框架和技术;
3、熟练掌握 CSS3 、HTML5 、ES6 、Gulp、Webpack 等规范和技术;
4、熟悉 Node.JS ,有 Node.JS 开发经验,熟悉 Express\Koa 等框架优先;
5、熟练使用 Canvas 、 SVG 、 D3.js 等可视化技术者优先;
6、有 WebVR 、WebGL 、Three.js 经验者优先;
7、有浏览器端音频、视频、图像处理经验者优先;
8、有前端深度优化或者大型网站开发经验者优先;
9、有广泛使用的开源项目优先;
10、有 WebIDE 相关工作经验优先;
11、了解 VsCode 源码优先;
- 本文作者: Littleki
- 本文链接: https:/littleki.gitee.io/2019/04/25/随手笔记/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!