Vue.js 源码(14)—— 最佳实践

277 阅读2分钟

这是我参与更文挑战的第14天,活动详情查看: 更文挑战

前言

本文,我们聊一聊日常工作中使用 Vue.js 开发项目时的最佳实践以及风格规范

最佳实践

为列表渲染设置属性key

key 这个特殊属性主要用在 Vue.js 的虚拟DOM算法中,在对比新旧虚拟节点时辨识虚拟节点。

我们在介绍虚拟DOM时提到,在更新子节点时,需要从旧虚拟节点列表中查找与新虚拟节点相同的节点进行更新。如果这个查找过程设置了属性key,那么查找速度会快很多。所以无论何时,建议大家尽可能地在使用 v-for 时提供key,除非遍历输出的DOM内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

在v-if/v-if-else/v-else中使用key

v-if指令在编译后是下面的样子:

(has) ? _c('li', [_v('if')]) : _c("li", [_v('else')])

所以当状态发生变化时,生成的虚拟节点既有可能是v-if上的虚拟节点,也有可能是v-else上的虚拟节点。

默认情况下,Vue.js 会尽可能高效地更新 DOM。这意味着,当它在相同类型的元素之间切换时,会修补已存在的元素,而不是将旧的元素移除,然后在同一位置添加一个新元素。如果本不相同的元素被识别为相同,则会出现意料之外的副作用

如果添加了属性key,那么在比对虚拟 DOM 时,则会认为它们是两个不同的节点,于是会将旧元素移除并在相同的位置添加一个新元素,从而避免意料之外的副作用。

路由切换组件不变

在使用Vue.js开发项目时,最常遇到的一个典型问题就是,当页面切换到同一个路由但不同参数的地址时,组件的生命周期钩子并不会重新触发。

下面总结了3个方法来解决这个问题:

1. 路由导航守卫 beforeRouteUpdate

组件的生命周期钩子虽然不会重新触发,但是路由提供的 beforeRouteUpdate守卫可以被触发。因此,只需要把每次切换路由时需要执行的逻辑放到 beforeRouteUpdate守卫中即可。

2. 观察 $route对象的变化

const User = {
    template: '...',
    watch: {
        '$route': function(to, from) {
            // 对路由变化作出响应
        }
    }
}

3. 为router-view组件添加属性key

<router-view :key="$route.fullPath"></router-view>

为所有路由统一添加query

1. 使用全局守卫 beforeEach

2. 使用函数劫持

这种方式的原理是:通过拦截 router.history.transitionTo 方法,在 vue-router 内部在切换路由之前将参数添加到 query 中。