前段时间经历了多个rc版本,vue2.0正式发布了,随之而来的是vue-router 和vuex 的2.0 到来。

本文主要讲述笔者在升级的过程中遇到的问题,若你需要直接使用2.0,请直接移步Vue2.0官方教程,可能不会涉及到全部的升级内容。

##准备工作
官方提供了一个帮助工具,vue-migration-helper,全局安装。

1
2
3
>> npm install --global git://github.com/vuejs/vue-migration-helper.git
>> cd path/to/your-vue-project
>> vue-migration-helper

当下Shell会打印出你的项目中需要修改的地方。比如下面这一条:

  1. Replace this.\$dispatch(“SWITCH_TO_FOLLOW”) to use a global event bus or vuex (see link below for implementation details)
    Line 146: src/components/common/ScrollButton.vue
    Reason: \$dispatch and $broadcast have been deprecated because the pattern doesn’t scale well
    More info: http://vuejs.org/guide/migration.html#dispatch-and-broadcast-deprecated

上面的提示是由于2.0中 以前子组件给parents组件的通信方法$dispatch已被废弃,建议使用全局事件处理或者vuex来进行数据传递,后面我们将会说到全局事件处理中心是如何来处理组件之间的通信。

可能你的项目需要修改的地方比较多,建议你将命令结果写到文件方便查看需要修改的地方,下面列出一些笔者项目升级中约到的且重要的升级变动

##Vue升级

片段实例

之前的组件代码可能长这样:

<template>
  <div class="container-one"> </div>
  <div class="container-two"> </div>
</template>

升级后不允许出现这样的代码片段,一个组件必须只能有一个根元素,换言之,上面的代码必须修改为:

<template>
 <div>
   <div class="container-one"> </div>
   <div class="container-two"> </div>
 </div>
</template>

生命周期部分更新

2.0对生命周期的相关钩子函数进行了精简,移除的移除,替换的替换。

  • beforeCompile 移除, 用created替换
  • compiled 移除, 用mounted替换
  • attached 移除, 在其他钩子函数里面进行对dom的检查,
    在mounted函数里面:

    1
    2
    3
    4
    5
    mounted() {
    this.$nextTick(function () {
    doSomething()
    })
    }
  • detached 移除,在其他钩子函数里面禁用对用dom的检查.这里调用同样的this.$nextTick方法写到destroyed钩子函数里面表明当前组件已经完全从dom中被清除。

  • init 更名,现在使用beforeCreate

  • ready 现在使用mounted替换[请注意mounted并不能保证 component in-DOM,请调用方法$nextTick].

    注:
    全局和实例方法Vue.nextTick和this.$nextTick,表示回调会在DOM 更新循环之后执行,大白话,该回调函数内标识dom已经更新完毕,你可以肆意对dom进行操作;
    2.0还增加了一个重要的钩子函数,updated! 是它是它就是它,在我们各种生产环境中,肯定会遇到各种情况,data发生变化需要从新渲染组件,但是通常这一步由于双向绑定机制是vue自动帮我们做的,但是我们需要data更新之后在保证dom加载完成之后去做一些特定的操作。没错 updated 就是酱紫出现了。

官方解释: updated.笔者粗略翻译: 基于Dom的操作可以在这个钩子函数里面实现,但是请不要尝试改变data状态,因为它可能会导致死循环。

v-for 的变化

对于v-for,显著的变化是调整了参数的位置,以前的代码长这样

<div v-for="(index, item) in data"> </div>

现在为了和原生的js遍历方法统一,现在对于数组和对象都需要将item 和 index 对调,现在必须写成这样:

<div v-for="(item, index) in data"> </div>

1.0版本的track-by 由key 代替。$index 和 $key 被废弃,现在要求这两个值需要明确的在for循环内声明。

动态属性的变动

对于1.0 代码可能长这样,动态的给div添加一个class

<div class="content-container {{isActive? 'active': ''}}"> </div>

这样的属性动态绑定已经不再适用,现在需要使用行内表达式来实现,长这样:

<div v-bind:class="'content-container '+ (isActive ? 'active': '')  ">
或者这样
<div v-bind:class="['content-contaner', isActive? 'active': '']">

还有其他绑定方法这里不再详述,但是这里请注意,如果使用vue-migration-helper工具,它会提示你将老的代码替换成这样:

<div v-bind:class="'content-container '+ isActive ? 'active': ''  ">

然而由于运算符优先级问题 最后的结果会是
<div class=""></div>
不能直接根据帮助工具生成的直接copy&paste。现在动态属性绑定必须要用指令v-bind修饰。

\$brodcast和 \$dispatch移除

上一个版本他们没有很好的解决兄弟组件之间的通信问题,为了让组件通信更加简洁以及组件状态更加清晰,可以使用vuex。
但是在特定的情况下,例如组件间的ping-pong通信,这种及其简单的组件通信使用vuex就有点小题大做了。如果是父子组件,官方建议使用v-on 绑定到自定义组件上面,子组件调用$emit事件。这里关于v-on绑定事件可以绑定原生dom元素也可以绑定到自定义组件上,详情请查看官方文档v-on

但是对于跨多层的父子元素, $emit不能帮到你。官方的建议是用一个事件处理中心来处理这些事件,这个中心处理器可以直接由vue实例来做,因为vue实例实现了时间发射触发接口。

我们可以这样做,在root vue对象里面的data设置一个全局共享的数据,这个数据就是一个空的vue对象,我们所有的事件分发都由它来控制。
代码张这样:

new Vue({
    el: '#app',
    router,
    render: h => h(App),
    data: {
       eventHub: new Vue()
  }
})

这样每一个组件都能访问到eventHub.你可以通过这个vue对象来控制。

子组件里面可以通过 this.$root.eventHub来获取这个空的vue实例。
A组件里面发射事件:

this.$root.eventHub.$emit('event-name', data)

B组件里面,在created或者mounted钩子函数里面接收:

this.$root.eventHub.$on('event-name', (data)=> {dosomething()})

记得在beforeDestroy钩子函数里面 解除绑定。

官方相关文档看这里:
vm.\$on
vm.\$emit
vm.\$off

##vue-router 升级

关于vue-router的升级

vue-router的初始化,是现在router对象没有专门的方法去初始化App,而是现在讲router对象作为一个属性值传递给根Vue实例。其他变动请查看官方的 vue-router升级文档

个人认为有必要要提一下的是 vue-router的 canReuse 被废弃, 这也意味着组件的生命周期钩子不会再被调用。比如/user/1 跳转到/uers/2 如果获取数据的method 在mounted中调用,第一次进入/user/1 能够正常获取数据,在当前页面点击链接跳转到/user/2你会发现数据不会变化,因为生命周期钩子函数并没有被执行。这时候需要我们主动监听路由对象,代码长这样:

watch: {
    '$route' (to, from) {
      if(to.path !== from.path) {
        //todo
      }
    }

在todo代码块去获取数据,更新到store。但是对于有子组件的组件,并且该父组件有路由匹配,在这个父组件监听’$route’得慎重,如果你在父组件加载完成后还有路由的变动,这里监听函数会被调用两次,如果不注意会造成意想不到的后果。

##vuex 升级

vuex 暂时没有选择升级,请查看官方升级文档。

相关链接:
vue升级文档
vue-router升级文档
vuex升级文档

小小前端一名,若文中有描述不恰当或者有误的地方还请指出,我的邮箱:
kevinkaiqiang@gmail.com,希望本文对你有帮助