众所周知,Vue项目采用了数据双向绑定和虚拟DOM基础,在数据驱动代替DOM频繁渲染已经算是非常高效了,对开发者而言已经非常优化了,那为什么还会有Vue性能优化这一说呢?
因为目前Vue 2.x使用了webpack等第三方打包构建工具,并且支持其他第三方的插件,我们在项目中使用这些工具时可能不同的操作在运行或打包效率上会有不同的效果,下面就来详细说明优化的方向。
v-if
为false
的时候不会渲染DOM
到视图,为true
的时候才会渲染到视图;v-show
不管初始条件是什么,元素总是会渲染到视图,只是简单地基于 CSS 的 display 属性进行切换。最佳实践:频繁切换显示隐藏的元素采用
v-show
,很少改变使用v-if
computed
: 是计算属性,依赖其它属性值,并且 computed
的值有缓存
,只有它依赖的属性值发生改变,下一次获取 computed
的值时才会重新计算 computed
的值;watch
: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;最佳实践:当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
现在不加key
一般会报错的,添加key
可以方便 Vue内部机制精准找到该条列表数据。当更新时,新的状态值和旧的状态值对比,较快地定位到 diff
v-for
比 v-if
优先级高,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候,必要情况下应该替换成 computed
属性。
<ul>
<li v-for="user in adminUsers" :key="user.id">
{{ user.name }}
li>
ul>
<script>
export default {
data () {
return { users: [] }
},
computed: {
adminUsers: function(){
return this.users.filter(()=>user.isAdmin)
}
}
}
script>
对于只用来展示用的数据,不需要做vue做数据劫持,只需要冻结这个对象即可:
export default {
data () {
return {
users: []
}
},
created () {
axios.get('/api/users').then((res)=>{
this.users = Object.freeze(res.data.users)
})
}
}
Vue 组件销毁时,会自动清理它与其它实例的连接,解绑它的全部指令及事件监听器,但是仅限于组件本身的事件。 如果在 js 内使用 addEventListene
等方式是不会自动销毁的,我们需要在组件销毁时手动移除这些事件的监听,以免造成内存泄露,如:
created() {
addEventListener('click', this.click, false)
},
beforeDestroy() {
removeEventListener('click', this.click, false)
}
使用vue-lazyload
插件:
安装
npm install vue-lazyload --save-dev
man.js 引用
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload)
// 或自定义
Vue.use(VueLazyload, {
preLoad: 1.3,
error: 'dist/error.png',
loading: 'dist/loading.gif',
attempt: 1
})
修改img标签
<img v-lazy="/static/img/1.png">
Vue 是单页面应用,可能会有很多的路由引入 ,这样使用 webpcak 打包后的文件很大,当进入首页时,加载的资源过多,页面会出现白屏的情况,不利于用户体验。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应的组件,这样就更加高效了。这样会大大提高首屏显示的速度,但是可能其他的页面的速度就会降下来。
const Foo = () => import('./Foo.vue')
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})
我们在使用第三方库的时候,最好是按需引入而不是全局引入,因为第三方库的插件比较多全部引入会打包比较慢,如Element UI
、Ant Design of Vue
等UI库:
按需引入
import Vue from 'vue';
import { DatePicker } from 'ant-design-vue';
Vue.use(DatePicker);
全局引入
import Antd from 'ant-design-vue';
Vue.use(Antd);
如果你是在渲染带无限滚动加载的列表时,那么需要采用 窗口化
的技术来优化性能,只需要渲染少部分区域的内容,减少重新渲染组件和创建 dom 节点的时间。 你可以参考以下开源项目 vue-virtual-scroll-list 和 vue-virtual-scroller来优化这种无限列表的场景的。
大家自己去Github
看使用说明吧。
一般单页应用是在浏览器端完成页面渲染的,数据是发请求从后台拿过来的;而服务器端渲染SSR是页面元素的结构(HTML)是在服务器端就已经构建好的,直接把整个页面返回到客户端的。
那SSR有什么优缺点呢:
SEO
:网络爬虫可以直接爬取页面信息利于被搜索引擎收录,而ajax异步请求的内容不会被收录,所以通过SSR渲染的完整的页面信息更利于SEO;beforCreate
和 created
,服务器需要处于Node Server环境;如果对首屏加载速度要求比较高或对SEO有要求的可以采用SSR渲染。
PS:优化只是建议,需要考虑是否适合自己的项目,包括优化难度、影响范围、适用场景、是否影响别的模块、优化效果是否明显等等。适合自己的才是最好的!