vue
v-show 和 v-if的区别
v-show通过css display控制显示和隐藏
v-if组件真正的渲染和销毁
频繁切换用v-show否则v-if
为何 v-for 中要用key
必须用key不能使用index和random
diff算法中通过tag和key来判断是不是sameNode
减少渲染次数,提高渲染性能
vue生命周期(有父子组件的情况)
父beforeCreate > 父created > 父beforeMount > 子beforeCreate > 子created > 子beforeMount > 子mounted > 父mounted
props、$emit
EvenetBus自定义事件
Vue.prototype.$bus = new Vue();
this.$bus.$on("test", (data) => {});
this.$bus.$emit("test", "go");
Vuex
$parent、$children,$attrs、$listenners,Provide、Inject,ref,observable
computed 和 watch
相同:
computed
和watch
都起到监听/依赖一个数据,并进行处理的作用。computed
缓存,依赖的data、props 等属性数据发生变化的时候调用,可以提高性能;
在computed中的,属性都有一个 get 和一个 set 方法,当数据变化时,调用 set 方法。
watch
监听引用类型取不到oldValue
可以监听的数据来源:data,props,computed内的数据;可以看作是 computed 和 methods 的结合体。
watch支持异步;
不支持缓存;
自定义v-model、$nextTick、slot、动态组件 异步组件、keep-alive、mixin
双向数据绑定v-model实现原理
绑定input value=this.name
通过监听input的onInput事件
更改this.name = $event.target.value;
数据改变重新触发render函数
Object,defineProperty的缺点
不能监听数组,监听数组的变化需要重写数组的原型方法,为了保留数组原型的原始方法避免被污染,利用object.create(Array.prototype)创建新对象。
深度监听,需要递归到底,一次性计算量大,可能会导致卡死。
无法监听属性的新增和删除但是有替代方案(Vue.set,Vue.delete)
为解决以上问题,vue3.0使用proxy,proxy的缺点无法使用polify浏览器兼容性差
虚拟DOM(Virtual DOM )
用js模拟DOM结构(vnode)
新旧vnode对比,得出最小的更新范围,最后更新DOM
数据驱动视图的模式下,有效控制dom操作
diff算法
diff算法是比较两个vnode,计算出最小的变更,以便减少DOM操作次数,提高性能。
其原理有:
只比较同级,不跨域比较;
如果tag不相同,直接删除重建,不再深度比较
如果tag和key都相同,默认是一样的节点,也不再深度比较
它的流程是:
首先,它会判断是否是首次渲染,因为如果是首次渲染,没有旧的vnode,不需要比较,直接渲染就可以了。
在非首次渲染,首先比较两个节点是否一样。如果不一样,直接删除重建;如果一样,就需要进行vnode比较、就是比较children。
如果新节点没有文本节点,删除旧节点的文本节点;如果有文本节点,替换掉旧的文本节点。
如果只有新节点有子节点,直接插入;如果只有旧节点有子节点,直接删除。
最后就是,新旧节点都有子节点的情况。
这时候会遍历新节点的children,每个新的子节点都需要在旧的children里面进行寻找,找一个一样的节点。
如果没有找到,新的子节点直接插入;如果找到了,这两个节点再进行vnode比较。
也可以简单的理解为,如果没有是重新渲染,如果有的话,直接把旧的子节点挪过来用就可以了。
组件渲染更新流程
整体编译流程 http://coding.imooc.com/learn/questiondetail/172128.html
模板编译
使用vue-template-compiler,with语法
将模板编译为render函数,执行函数返回vnode
基于vnode再执行渲染和更新(patch和diff)
如果有需要可以用render函数代替template,react就是使用的render
如果是在webpack环境下则vue-loader会在开发环境下预编译模板
为何使用异步渲染
$nextTick(()=>{});
汇总data修改,一次性更新视图
减少dom操作次数,提高性能
MVVM数据驱动视图
使开发人员不再关注具体dom,将精力放到对数据的处理上
vue常见性能优化
data层级避免过深
v-show v-if
computed
v-for时加key,以及避免同时使用v-if
beforedestory 及时销毁自定义事件、DOM事件、定时器等
使用异步组件import(),和路由import()
keep-alive
使用vue-loader在开发环境下做模板预编译
服务端渲染
const renderer = require('vue-server-renderer')
renderer.renderToString()
vue 如何解析模板?
模板就是一段字符串,非结构化的数据,没法分析。因此,第一步是将非结构化的模板字符串,转变成结构化的 JS 对象,抽象语法树,即 AST 。其实就是一个 JS 对象,这样就结构化了。
第二步,将 AST 转换成一个 render 函数,步骤是先转换为一段函数体的字符串,然后再用
new Function(...)
生成函数。第三部,渲染时执行 render 函数,返回虚拟 DOM 对象,然后执行虚拟 DOM 的
patch
方法,渲染成真正的 html 。
webpack
前端为何要进行构建和打包
代码层面
体积更小(tree-shaking、压缩、合并),加载更快
编译高级语言或语法(ts、es6+、模块化、less/scss)
兼容性和错误检查(polyfill、postcss、eslint)
研发流程方面
统一、高效的开发环境
统一构建流程和产出标准
继承公司构建规范(提测、上线等)
module chunk bundle 分别什么意思,有何区别
mudule: 各个源码文件(如src文件下的文件),webpack中一切皆模块
chunk:
多模块合并成的,如entry import() splitChunk
webpack分析过程中,通过entry import等文件的依赖分析,分析出模块的多个集合
bundle:最终输出的文件,,chunk构建完成最终输出文件一般叫bundle,一个chunk对应一个bundle
webpack中易混淆的名词https://www.cnblogs.com/skychx/tag/Webpack/
loader 和plugin的区别
loader:翻译官,将文件翻译成webpack能识别的js语言,模块转换器,如less转换为css
plugin:扩展插件,如 htmlwebpackplugin,是用来增强功能的
常见loader和plugin都有哪些
webpack如何实现懒加载
import()语法,结合vue react异步组件,结合vue-router react-router 异步加载路由
webpack常见性能优化 — 优化构建速度
可用于生产环境:优化babel-loader、IgnorePlugin忽略无用文件、noParse避免重复打包、happyPack多进程打包、ParallelUglifyPlugin 多进程压缩 JS
不可用于生产环境:自动刷新、热更新、DllPlugin 动态链接库插件
优化babel-loader
{ tets:"/.js$/", use:['babel-loader?cacheDirectory'],//?cacheDirectory开启缓存 include:path.resolve(__dirname,'src'),//明确编译范围 exculde:path.resolve(__dirname,'node_modules')//排除编译范围 }
IgnorePlugin忽略无用文件
直接忽略相关文件不进行引入,减小文件体积
//webpack.prod.js配置 忽略 moment 下的 /local 目录 plugins:[ new webpack.IgnorePlugin(/\.\/locale/,/moment/) ] //main.js使用 全部忽略之后需要手动引入所需文件 import moment from 'moment' import‘moment/locale/zh-cn’;
noParse避免重复打包
引入相关文件,但不再进行打包
已经模块化处理过的文件不需要再进行打包所以需要配置,比如jQuery.min.js等
module:{ noParse:[/jQuery\.min\.js$/] }
大文件按需使用 happyPack多进程打包
因为js是单线程的,使用happyPack可以多进程打包,提高构建速度(特别是多核CPU)
const HappyPack = require('happypack') module:{rules:{ tets:"/.js$/", use:['happypack/loader?id=babel']//把对 .js 文件的处理转交给 id 为 babel的 HappyPack 市里 }} plugins:[ new HappyPack({ id:"babel", loaders:['babel-loader?cacheDirectory'] }) ]
大文件按需使用 ParallelUglifyPlugin 多进程压缩 JS
webpack有内置的Uglify JS压缩工具,但是单线程没办法多进程压缩,使用 ParallelUglify 可以使压缩更快
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin') plugins:[ new ParallelUglifyPlugin({ uglifyJS:{//依然是使用UglifyJS,只不过开启了多进程 output:{ beautify:false,//是否压缩为一行 comments:False,//删除所有的注释 }, compress:{ drop_console:true,//删除所有的console语句,可以兼容ie collapse_vars:true,//内嵌定义了但是只用到一次的变量 reduce_vars:true//提取出现多次但是没有定义成变量去引用的静态值 } } }) ]
自动刷新
每当检测到文件改变浏览器会刷新当前页面,页面状态会丢失
module.export = {//不常用,一般使用 devServer替代 watch:true, watchOptions:{ ignored:/node_modules/,忽略文件下的监听 aggregateTimeout:300,//监听到稳健变化等待默认300ms,防止文件更改过快编译频率太高 poll:1000,//默认每隔100ms询问一次 } } devServer:{ port:8080, progress:true, contentBase:'dist', open:true, compress:true,//启用gzip压缩 hot:true, proxy:{} }
热更新
检测到文件发生改变,不刷新页面更新数据。
const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin') entry:{ index:[ 'webpack-dev-server/client?http://localhost:8080/', 'webpack/hot/dev-server', path.join('src','index.') ] } plugins:[ new HotModuleReplacementPlugin() ] devServer:{ hot:true, } //index.js 文件开启 if(module.hot){ module.hot.accept(listenner,fn)//listenner 可以是字符串也可以是数组'src'||['/src'] }
DllPlugin 动态链接库插件
开发环境使用
前端框架如vue体积大,构建慢,较稳定,不常升级版本,同一版本只构建一次即可,考虑使用 DllPlugin
首先使用DllPlugin打包出dll文件 plugins:[new webpack,DllPlugin({})]
DllReferencePlugin使用dll文件 ‘webpack/lib/DllReferencePlugin’
webpack常见性能优化 — 优化产出代码
体积更小,合理分包不重复加载,速度更快 内存使用更小
小图片base64编码、bundle使用contenthash、懒加载 import()、提取公共代码、IgnorePlugin忽略无用文件、使用CDN加速、使用production、Scope Hoisting
小图片base64编码
rules:{ test:/\.(png|jpg|jpeg|gif)$/, use:{ loader:'url-loader', options:{ limit:5 * 1024,//小于 5kb 输出位base64 outputPath:'/img/' } } }
bundle使用contenthash
根据文件内容生成hash,文件不变则生成的文件名不变,请求页面可以命中缓存文件、
懒加载 import()
提取公共代码
optimization:{ splitChunks:{ chunk:'all',//initial async all cacheGroup:{//缓存分组 vendor:{//第三方模块 name:'vendor',//chunk名称 priority:1,//数字越大权限越高,优先提取 test:/node_modules/, minSize:0,//大小限制 minChunks:1//最少复用过几次 }, common:{//公共模块 name:'vendor',//chunk名称 priority:0,//数字越大权限越高 minSize:0,//大小限制 minChunks:1//最少复用过几次 } } } }
IgnorePlugin忽略无用文件
可以使打包出来的代码更少
使用CDN加速
output:{ publicPath:‘cndurl’//修改所有静态文件 url 的前缀为改cdn地址 } rules:use:options:{ publicPath:'cndurl'//针对图片设置cdn加速 }
使用production
自动压缩代码,减小代码体积
vue react 等会自动删掉调试代码(如开发环境的warning)
自动启用Tree-Shaking(删除没有用到的js代码),以下分析ES6 module和commonjs的区别
1). 必须ES6 Module 才能让其生效,commonjs 不行
2).es6 module 静态引入,编译时引入。commonjs 动态引入,执行时引入。
3).只有es6 module才能静态分析,实现Tree-Shaking
可以使代码体积更小
创建函数作用域更少
代码可读性更好
babel 和 webpack的区别
babel:js新语法编译工具,不关心模块化
webpack:打包构建工具,十多个loader plugin的集合
babel
babel-runtime 和 babel-polyfill有什么区别
https://blog.csdn.net/m0_37613019/article/details/108226550
https://www.cnblogs.com/L-xmin/p/12493824.html
babel-polyfill会污染全局对象
Proxy为何不能被pplyfill
共同学习,写下你的评论
评论加载中...
作者其他优质文章