Vue 代码层优化
1. v-if 和 v-show区分使用的场景
v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。
2. compouted 和 watch props 区分使用场景
computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,
只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;
watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;
使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
注意:
-
如果子组件使用vuex,通过computed引入的数据,不能直接通过this.xxx=yyy修改,必须通过 commit 去修改vuex的数据。否则会报错
[图片上传失败...(image-7cc3bf-1604993476395)] -
如果一个需求,computed值发生改变,可以改变当前组件data的数据变化;data变化的值可以改变computed变化;双向绑定的。
getter/setter实现 -
vue 解决computed修改data数据的问题 https://www.jb51.net/article/173669.htm
当computed的数据依赖相关的数据是异步请求过来的数据,会报错的。
数据会先渲染初始值,然后再渲染异步请求回来的数据。渲染两次但是我只是需要最后一次变化的值。 -
子组件修改props时,如果是传来的值是
引用类型
vue不会报错,但是如果是基本类型
直接修改会报错。子组件修改props的方法:
- 子组件data中拷贝一份,注意引入类型需要深拷贝,根据需求可以watch监听
props: ["list"], data() { return { newList: this.list.slice() } }, watch: { list(newVal) { this.newList = newVal }
- 通过计算属性修改
computed: { nList() { return this.list.filter(item => { return item.isChecked }) } }
- 通过研究大佬们的写法又发现了一种修改方式: sync修饰符
父组件 穿进去的时候加上 .sync
子组件 通过this.$emit('update:xxx', params)
// 父组件 <todo-list :list.sync="list" /> // 子组件 methodName(index) { this.$emit('update:list', this.newList) }
3. v-for 和 v-if
- v-for 遍历必须为 item 添加 key
- v-for 遍历避免同时使用 v-if
v-for 比 v-if 优先级高,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候,必要情况下应该替换成 computed 属性。<ul> <li v-for="user in activeUsers" :key="user.id"> {{ user.name }} </li> </ul> computed: { activeUsers: function () { return this.users.filter(function (user) { return user.isActive }) } }
4. 长列表性能优化
Vue会通过Object.defineProperty对数据劫持,来实现视图响应数据的变化
然而有些时候长列表只是单纯的显示,不需要数据和视图绑定,所以我们禁止vue劫持我们的数据。
通过Object.freeze方法冻结对象就再也不能被修改了。
export default {
data: () => ({
users: {}
}),
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
}
};
5. 事件销毁
Vue 组件销毁时,会自动清理它与其它实例的连接,解绑它的全部指令及事件监听器,但是仅限于组件本身的事件。
如果在 js 内使用 addEventListene 等方式是不会自动销毁的,我们需要在组件销毁时手动移除这些事件的监听,以免造成内存泄露,
created() {
addEventListener('click', this.click, false)
},
beforeDestroy() {
removeEventListener('click', this.click, false)
}
6. 图片懒加载
对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。
这样对于页面加载性能上会有很大的提升,也提高了用户体验。
我们在项目中使用 Vue 的 vue-lazyload 插件:
安装插件
npm install vue-lazyload --save-dev
在入口文件 man.js 中引入并使用
import VueLazyload from 'vue-lazyload'
然后再 vue 中直接使用
Vue.use(VueLazyload)
或者添加自定义选项
Vue.use(VueLazyload, {
preLoad: 1.3,
error: 'dist/error.png',
loading: 'dist/loading.gif',
attempt: 1
})
在 vue 文件中将 img 标签的 src 属性直接改为 v-lazy ,从而将图片显示方式更改为懒加载显示:
<img v-lazy="/static/img/1.png">
以上为 vue-lazyload 插件的简单使用,如果要看插件的更多参数选项,可以查看 vue-lazyload 的 github 地址
7. 路由懒加载
const Foo = () => import('./Foo.vue')
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})
8. 优化无限列表性能
果你的应用存在非常长或者无限滚动的列表,那么需要采用 窗口化 的技术来优化性能,只需要渲染少部分区域的内容,减少重新渲染组件和创建 dom 节点的时间。
你可以参考以下开源项目 vue-virtual-scroll-list 和 vue-virtual-scroller 来优化这种无限列表的场景的。
网友评论