Vue.js 2.0 最佳实践 & 踩坑记录

最近在团队的小组里做了一次关于Vue.js 2.0的一些 最佳实践 和常见的 采坑记录 的小分享,这里总结了一下分享给大家~ 如果哪里有问题欢迎大家diss ^_^

代码规范

关于代码规范,我的理解是不一定非要用什么特别严苛的标准或是特别权威的规范,只要项目团队遵循一套统一的约定就可以。当然,参考他人的经验沉淀从而制定自己的代码规范还是很有必要的。

1. 对齐

  • 静态属性 (static binding) 在前, 动态属性 (dynamic binding) 在后
  • 属性绑定 (:属性)在前, 事件绑定 (@事件) 在后
  • 如果有使用指令,则指令语句写在最前面

e.g:


  • {{ n.name }}
  • {{ n.name }}
  • 2. 简化的表达式(不要在模版里使用复杂的表达式)

    • 对于列表里的数据表达式,可以用 filter 来处理
    • 其他情况下,可以使用 computed property

    e.g:

    
    
    
    
    
    
    

    3. 组件编码规范

    • 导出一个清晰、组织有序的组件,使得代码易于阅读和理解。同时也便于标准化。
    • 能避免操作 dom 就尽量避免,实在要用的话最好使用 ref 来代替 querySelector 等选择器方法
    • 一个 .vue 的文件行数最好控制在 200 行左右
    • 善用 v-ifv-show。比如,涉及到权限的必须用 v-if 而非 v-show。例如,用户必须登录后才能查看的,请用 v-if
    • 请尽量保证数据流的可追踪性。尽量不要使用 $parent,而是通过 props 属性接收父组件的传入

    参考:Vue组件设计规范

    最佳实践

    1. 属性绑定

    1.1 绑定字符串不需要加冒号

    e.g:

    
    
    
    
    
    

    1.2 布尔属性省略值时默认为 true

    e.g :

    
    
    
    

    1.3 HTML原生属性可以不用 props 绑定 或者 组件特有的特性也不用 props 绑定

    e.g:

    
    
    
    

    2. 事件绑定

    2. 绑定无参函数不需要加 ()

    e.g:

    
    
    
    
    
    

    2.2 只有一行代码的事件函数,可以直接写在标签上

    e.g:

    
    

    2.3 在监听原生DOM事件时,方法以 事件 为唯一的参数。如果使用内联语句,语句可以访问一个 $event 属性:

    e.g:

    
    

    如果在父组件中想要给子组件抛出的事件添加自定义参数,可利用此属性:

    e.g: https://jsfiddle.net/hysunny/eywraw8t/228187/

    3. 修饰符

    Vue 内置了许多常用的 修饰符 ,可以让你少写几行代码,提高开发效率。

    e.g:

    
    
    
    
    
    ...
    ...

    4. 按需加载组件

    一般配合 Vue-Router 使用,适用于大型应用,将应用分割成小的代码块,只在需要的时候才从服务器加载。

    实现方式:

    • 异步组件实现
    • es6 import

    好处:

    • 按需加载,节省首次加载实践,提高速度,也算是一个性能优化;
    • 组件只会加载一次,加载完成后会缓存下来,使用一个组件多次使用的场景。

    e.g:

    // 异步组件实现
    export default new Router({
        routes: [
            {
                path: '/test',
                name: 'test',
                component: resolve => require(['../components/Test'], resolve)
            },
        ]
    })
    
    // ES6 import
    const Test1 = () => import('../components/Test1')
    const Test2 = () => import('../components/Test2')
    
    export default new Router({
        routes: [
            {
                path: '/test1',
                name: 'test1',
                component: Test1
            },
            {
                path: '/test2',
                name: 'test2',
                component: Test2
            }
        ]
    })
    

    5. 过滤器

    用于一些常见的文本格式化,如展示发布时间。

    e.g:

    
    
    
    

    6. 多个元素块可以用template包裹

    参考: Vue.js 在-lt-template-gt-元素上使用-v-if-条件渲染分组

    e.g:

    
    
    

    7. v-for 循环加 key

    Vue.jsv-for 正在更新已渲染过的元素列表时,它默认用 就地复用 策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。

    稍微深入一点,加 key 的原因是为了给 virtualDom中diff 做优化,结果就是提高 virtualDom 更新效率。

    patch参考: https://github.com/aooy/blog/issues/2

    8. 使用频率较高的方法挂载到Vue实例上

    这样做的好处是不需要每次使用都要 import,提高开发效率。

    e.g:

    Vue.prototype.$utils = {
        cookie,
        formatDate,
        ...vdom,
        getQueryString
    }
    
    new Vue();
    
    // 使用
    this.$utils.getQueryString('from_url');
    

    9. 多级组件传递数据使用 $attrs$listeners

    Vue 2.4 版本,配合 interitAttrs 选项,父组件中未被 props(v-on) 绑定的属性(事件) 可以在子组件中,通过 $attrs$listeners 获取。个人认为好处是不用再每个组件都显式绑定 props 或 事件,坏处是传递的属性或事件不够明确。一般情况下不需要使用,但是在创建更高层次的组件时非常有用。

    参考:

    $attrs: https://cn.vuejs.org/v2/api/#vm-attrs

    $listeners: https://cn.vuejs.org/v2/api/#vm-listeners

    常见的坑

    1. 对象和数组的更新检测

    由于 JavaScript 的限制,Vue 不能检测以下变动的数组

    • 当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
    • 当你修改数组的长度时,例如:vm.items.length = newLength

    还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除

    解决方法: 对于数组来说可以使用 vm.$set或改用可观察数组的变异方法,对于对象来说可以使用 vm.$setObject.assign

    e.g. https://jsfiddle.net/hysunny/eywraw8t/228152/

    2. mixins同名选项混合问题

    当我们想覆盖一个组件的一些东西或想扩展某个组件时,可以用 Vuemixins

    不过要注意:

    当组件和混合对象含有同名选项时,同名钩子函数将混合为一个数组,都会被调用;混合对象的钩子将在组件自身钩子之前调用。
    值为对象的选项,例如 methods, componentsdirectives,将被混合为同一个对象。两个对象键名冲突时,取组件对象的键值对。

    e.g: https://jsfiddle.net/hysunny/eywraw8t/228225/

    3. v-if 与 v-for 的优先级问题

    v-ifv-for 一起使用时,v-for 具有比 v-if 更高的优先级,因此如果想有条件的跳过循环的执行,则需将 v-if 置于外层元素(或 template)上。如:

    • {{ todo.name }}

    No todos left!

    4. 遍历对象顺序不一致

    使用 v-for 遍历对象时,是按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎 下是一致的。

    比如: 在 ios 下当对象的key为字母时,排序为降序,其他机型为升序。

    解决方法: 如果要保证顺序,可以加个排序的 filter 或者 改用数组。

    参考: https://github.com/vuejs/vue/issues/1827

    5. event bus 多次触发

    $on 的事件可在 createdmounted 注册

    需在 beforeDestroydestoryed 的时候使用用 $off 销毁

    否则在某些情况下会被被多次触发

    e.g. https://jsfiddle.net/hysunny/eywraw8t/232163/

    6. 变量命名

    变量名不要以_$开头,因为名字以 _$ 开始的属性不会被 Vue 实例代理,

    因为它们可能与 Vue 的内置属性与 API 方法冲突。

    需要用 vm.$data._property 访问它们。

    e.g: https://jsfiddle.net/hysunny/eywraw8t/224835/

    7. vue 2.0 给组件绑定事件无效

    对于一般的 html 元素,绑定自定义事件使用 v-on即可,但是在某个组件的 根元素 上监听一个 原生事件 ,比如:

    
    

    我们会发现这样是不起作用的,可以使用 .native 修饰符(某些情况) 或是 $listeners

    
    

    e.g. 用.native给自定义组件绑定事件

    哦啦~

    以上部分内容参考了: Vue最佳实践,非常感谢!O(∩_∩)O~

    你可能感兴趣的:(Vue.js 2.0 最佳实践 & 踩坑记录)