# v-if 和 v-show
- v-if 是 真正 的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;也是惰性的: 如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
- v-show 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 display 属性进行切换。
总结: v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。
# computed 和 watch
- computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值
- watch: 是监听属性,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作
总结:当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算; 当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率, 并在我们得到最终结果前,设置中间状态;这些都是计算属性无法做到的。
# v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
- v-for 遍历必须为 item 添加 key
在列表数据进行遍历渲染时,需要为每一项 item 设置唯一 key 值,方便 Vue.js 内部机制精准找到该条列表数据。当 state 更新时,新的状态值和旧的状态值对比,较快地定位到 diff 。
- v-for 遍历避免同时使用 v-if
v-for 比 v-if 优先级高,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候,必要情况下应该替换成 computed 属性。
# 长列表性能优化
Vue 会通过 Object.defineProperty 对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变, 我们就不需要 Vue 来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,那如何禁止 Vue 劫持我们的数据呢? 可以通过 Object.freeze 方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。
代码语言:javascript复制export default {
data: () => ({
users: {}
}),
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
}
};
# 事件的销毁
Vue 组件销毁时,会自动清理它与其它实例的连接,解绑它的全部指令及事件监听器,但是仅限于组件本身的事件。 如果在 js 内使用 addEventListene 等方式是不会自动销毁的,我们需要在组件销毁时手动移除这些事件的监听,以免造成内存泄露。
例子:
代码语言:javascript复制created() {
addEventListener('click', this.click, false)
},
beforeDestroy() {
removeEventListener('click', this.click, false)
}
# 图片资源懒加载
对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。这样对于页面加载性能上会有很大的提升,也提高了用户体验。
vue实现图片懒加载最简单的方法是使用插件,如下:
1、安装插件
代码语言:javascript复制npm install vue-lazyload --save-dev
2、在入口文件 man.js 中引入并使用
代码语言:javascript复制import VueLazyload from 'vue-lazyload'
3、在 vue 中使用
代码语言:javascript复制Vue.use(VueLazyload)
4、在 vue 文件中将 img 标签的 src 属性直接改为 v-lazy ,从而将图片显示方式更改为懒加载显示:
代码语言:javascript复制<img v-lazy="/img/1.png">
# 路由懒加载
Vue 是单页面应用,可能会有很多的路由引入 , 这样使用 webpcak 打包后的文件很大,当进入首页时,加载的资源过多, 页面会出现白屏的情况,不利于用户体验。如果我们能把不同路由对应的组件分割成不同的代码块, 然后当路由被访问的时候才加载对应的组件,这样就更加高效了。这样会大大提高首屏显示的速度。
例子:
代码语言:javascript复制const Foo = () => import('./Test.vue')
const router = new VueRouter({
routes: [
{ path: '/test', component: Test }
]
})
# 第三方插件的按需引入
我们在项目中经常会需要引入第三方插件,如果我们直接引入整个插件,会导致项目的体积太大 , 我们可以只引入需要的组件,以达到减小项目体积的目的。
以 element-ui (opens new window) 组件库为例:
1、安装 babel-plugin-component
代码语言:javascript复制npm install babel-plugin-component -D
2、将 .babelrc 修改为:
代码语言:javascript复制{
"presets": [["es2015", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
3、在 main.js 中引入部分组件:
代码语言:javascript复制import Vue from 'vue';
import { Button, Select } from 'element-ui';
import App from './App.vue';
Vue.component(Button.name, Button);
Vue.component(Select.name, Select);
/* 或写为
* Vue.use(Button)
* Vue.use(Select)
*/
new Vue({
el: '#app',
render: h => h(App)
});
# 优化无限列表
如果你的应用存在非常长或者无限滚动的列表, 我们可以采取scroll滑动刷新分页加载,通过滑动多次请求数据,再把数据通过concat来拼接在数组里来优化性能; 或者通过后端协助直接进行传参分页数据。