文章参考与 su1per
首屏渲染
老生常谈首屏渲染是单页面spa的通病。有些同学打包出来的dist高达60+M。首页加载20+S。这个体验真的是会让用户崩溃。
常见解决方案:
1. 路由懒加载
把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
{
path: '/index',
name: 'HelloWorld',
component: (resolve) => require(['../components/HelloWorld.vue'], resolve) // 直接定义引用
}
复制代码
或者
const HelloWorld = resolve => require(['@/components/HelloWorld.vue'], resolve) // 先定义
export default new Router({
routes: [
{ path: '/', name: 'HelloWorld', component: HelloWorld },// 再引用
]
})
复制代码
2. webpack优化
-
说到优化首提happypack, webpack默认是单线程进行的,而happypack则是启动node的多线程进行构建。可查看
-
webpack.prod.conf.js文件 devtool选择正确的 sourcemap 。生产环境直接去掉就好了。devtool官网
通过对比,生产环境:最好选择 (none)(省略 devtool 选项) - 不生成 source map。这是一个不错的选择。 开发环境: eval、cheap-eval-source-map
3. 数组检测
官网说的很明白。因为vue响应式是主要依赖Object.defineProperty的getter和setter,Vue 不能检测以下变动的数组:
-
当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
-
当你修改数组的长度时,例如:vm.items.length = newLengthd
// Vue.set
Vue.set(vm.items, indexOfItem, newValue);
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue);
复制代码
4. nextTick()
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。类似生命周期created和mounted的区别。
比如这么一个场景:你需要获取拿到数据后的某个文档的高度,请求结束后页面还没更新,获取的肯定不对。这个时候就需要在数据渲染结束后去获取。
updateList(){
this.itemList = ['super', 'tom', 'andy', 'nick'];
console.log(document.getElementById('demo').offsetHeight); //0 DOM 还没有更新
this.$nextTick(function () {
console.log(document.getElementById('demo').offsetHeight);// DOM 更新了
})
},
复制代码
5. this作用域指向问题
错误实例:
data () {
return {
msg: 'Welcome to Your Vue.js App',
itemList: [1, 2, 3, 4],
newList: []
}
},
methods:{
updateList(){
this.itemList.forEach(function (val) {
if(val >=2){
this.newList.push(val); // undefined
}
})
},
}
复制代码
正确写法:
1、_this赋值
updateList(){
let _this = this;
_this.itemList.forEach(function (val) {
if(val >=2){
_this.newList.push(val);
}
})
},
复制代码
2、箭头函数
updateList(){
this.itemList.forEach( (val) => {
if(val >=2){
this.newList.push(val);
}
});
},
复制代码