Vue.js升级小记

Posted 前端大学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue.js升级小记相关的知识,希望对你有一定的参考价值。

最近接手了一个 Vue 1.0 的陈年老项目,需要将其升级到Vue 2.0。下面记录一下升级过程:


安装迁移工具


首先需要安装 vue-migration-helper CLI 工具:


  1. 控制台运行命令:npm install --global vue-migration-helperCLI 工具来帮助项目从Vue 1.x 迁移到 2.x。 它扫描文件以查找特定于 Vue 的代码,并对需要升级的代码提供详细的警告。 vue-migration-helper的介绍说明告诉我们它大概能捕获 80% 的升级帮助信息,而不是全部。所以终端输出的帮助信息并不是完全正确的,在升级时不要盲目copy & paste,还是要根据实际情况去改写。

  2. 进入当前的项目:运行: vue-migration-helper


工具识别出了108 个需要升级的点:



由于这个古董项目不是用 Vue-CLI 构建的,为了避免在升级依赖上出错,我直接新起了一个Vue-CLI 项目,将老项目中的业务部分进行迁移,这个是最快最能避免踩坑的解决方案(当然,这么做是因为踩坑了,所以爬起来了=_=)与当前最新的Vue-CLI 的依赖版本做了对比:


  • "vue": "^1.0.24" to "vue": "^2.5.2"

  • "vue-router": "^0.7.13" to "vue-router": "^3.0.1"

  • "vuex": "^2.4.0" to "vuex": "^3.0.1"

  • "webpack": "^2.4.1" to "webpack": "^3.6.0"

  • "vue-loader": "^8.5.2" to "vue-loader": "^13.3.0"


升级代码


对于108 个需要升级的点来说,花费的时间远比想象的要多,除了根据官方文档进行迁移升级之外,运行项目还是会有很多报错,下面总结了一下改动比较多的地方。


1. 过滤器


移除内置过滤器


Vue 2.0 不再提供内置过滤器。可以创建自己的过滤器或者引入外部库如moment.js,accounting.js 来对时间和货币等进行格式化。之前项目中用到的 orderBy 方法已经被弃用了,根据升级指南的建议,直接引入了 lodash 工具库,并使用计算属性重构。


// Vue 1.x

<div v-for="tag in productTags | orderBy 'location'">

  {{ tag.tagTitle }}

</div>

// Vue 2.x

<div v-for="tag in productTags">

  {{ tag.tagTitle }}

</div>

 

import orderBy from 'lodash/orderBy'

...

...

...

computed{

  productTagsfunction () {

    return orderBy(this.tags, 'location')

  }

}

...


过滤器参数符号变更


// Vue 1.x

<div class="time">{{ item.appDate | date 'yyyy-MM-dd' }}</div>

 

// Vue 2.x

<div class="time">{{ item.appDate | date('yyyy-MM-dd') }}</div>


2. Vue Router


vue-router 的改动是相对来说非常大的,大部分都可以参考 官方文档 去修改,如:


  • router.go() 改成了router.push()

  • router.map() 被废弃,使用routes 选项数组

  • 使用 router-link 替换了 v-link

  • route.refresh 改成了 route.meta.refresh


对于beforeEach 来说现在是异步工作的,并且携带一个 next函数作为其第三个参数,beforeEach 经常用来设置页面的title,而 Vue 2.0 to 函数的使用也有一些改变,如下:


// Vue 1.x

router.beforeEach(({ to, next }) => {

  if (to.title) {

    ...

  }

  next()

})

// Vue 2.x

router.beforeEach((to, from, next) => {

  if (to.meta.title) {

   ...

  }

  next()

})


对于路由挂载根实例的改动,Vue 2.0 不再会有一个特殊的 API 用来初始化包含 Vue Router 的 app,而只需要传一个路由属性给 Vue 实例,如下:


// Vue 1.x

router.map(routes)

router.start(Vue.extend({

  store,

  components{

    apprequire('./app.vue')

  }

}), 'body')

// Vue 2.x

new Vue({

  el'#app',

  router,

  store,

  template'',

  components{ App }

})


3. 生命周期


生命周期钩子也是这次升级中比较大的改进点,对照 vue1.0文档 和 vue2.0 文档 ,异同如下表格:


Vue.js升级小记


因此主要的改动点是:使用mounted 钩子函数替换ready 钩子函数


4. transition


Vue 2.0 对动画做了非常大的更新,原来的transition属性已经被彻底废弃掉了,而使用 transition 或 来包裹元素去实现过渡效果,项目中关于动画的代码都要重新写,包括 CSS、 html ,还有 javascript 钩子函数的改变。


在要升级的这个项目中,关于transition 的升级差不多有10多个,其中大部分的改动都可以按照迁移工具去copy & paste, 但是还是要清楚其中的异同,再去做修改。不然就会出现,错误提示消失了,但是动画不生效的情况。


过渡CSS 变化


Vue.js升级小记


举个栗子:


// Vue 1.x :

div v-if="isShow" transition="info-fade">

spanhello world ! /span>

/div>

 

.info-fade-transition {

  transitionall .3s ease;

}

.info-fade-enter, info-fade-leave {

  opacity0;

}

// Vue 2.x

transition name="info-fade">

  span v-if="isShow"hello world ! /span>

/transition>

 

.info-fade-enter-active, info-fade-leave-active {

  transitionall .3s ease;

}

.info-fade-enter, info-fade-leave {

  opacity0;

}


Javascript 钩子


Vue 2.0 transitions能够通过组件应用,它们不再只是一种单独类型,因此全局的Vue.transition()方法和transition配置都被丢弃。现在可以通过组件的属性和方法配置内嵌的过渡:


// Vue 1.x

Vue.transition('expand', {

 

  beforeEnterfunction (el) {

    el.textContent = 'beforeEnter'

  },

  enterfunction (el) {

    el.textContent = 'enter'

  },

...

})

// Vue 2.x

methods{

  // 过渡进入

  // 设置过渡进入之前的组件状态

  beforeEnterfunction (el) {

    // ...

  },

  // 设置过渡进入完成时的组件状态

  enterfunction (el, done) {

    // ...

    done()

  },

  ...

}


5. Class 与 Style 绑定


// Vue 1.x

<div class="qa-item-question {{item.viewStatus === 1 ? 'isread' : ''}}"> </div>


如果使用 vue-migration-helper工具,它会提示你将老的代码替换成这样:


// Vue 2.x

<div v-bind:class="'qa-item-question ' + item.viewStatus === 1 ? 'isread' : ''"></div>


然而由于运算符优先级问题,最后的结果可能会是 :


<div class=""></div>


因此,应该注意的不能完全依赖升级工具的提醒去直接 copy & paste。


6. 双向数据绑定


Replace :visible.sync="xxx" with :visible="xxx", then $emit an event from the child component to trigger an update to xxx in the parent


Vue 2.x 中,为了规范数据流动,砍掉了 .sync,用来阻止子组件影响父组件所绑定的值,因为.sync 破坏了单向数据流。但是很多情况下还是会需要双向绑定的,比如 dialog 弹窗,当关闭时,将此状态返回给父组件。


而 Vue 2.x 中,子组件只能被动接收父组件传递过来的数据,并在子组件内不能修改由父组件传递过来的props数据。每次父组件更新时,子组件的所有prop都会更新为最新值,因此不应该在子组件内部改变 prop,如果我们尝试直接修改prop 属性的值,就会有警告提示:


[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: 

"xxx" (found in component ) 


Vue2.0 的官方文档也给出了解决方案:


定义一个局部变量,并用 prop 的值初始化它

定义一个计算属性,处理 prop 的值并返回


而对于 .sync ,Vue 2.3 + v-bind 指令中将其引进,成为一枚语法糖,它会被扩展为一个自动更新父组件属性的 v-on 监听器。


7. $loadingRouteData


Vue 2.0 移除了 $loadingRouteData 钩子。如果我们需要判断页面数据是否加载完成,需要自定义一个属性(例如: isLoading)


8. 其他简单的改动


  • v-for

    • track-by to :key

    • 废弃了$index

  • HTML 的计算插值{{{ foo }}}已经移除,取代的是v-html指令

  • v-el 和 v-ref 合并成 ref 属性

  • 在 Vue 的实例中不能使用Vue.set 和 Vue.delete

  • 使用@click.native 监听根元素的原生事件,@click传的只是一个方法

  • 废弃了 Array.prototype.$set/$remove,用Vue.set 或者 Array.prototype.splice取代


9. 其他报错


浏览器报错:


[Vue warn]: Do not use built-in or reserved HTML elements as component id: dialog


因为dialog在 HTML5 里面是个原生的标签解决方法:重命名components里面组件的名称


总结


上面只是简单梳理了一下该项目在升级时遇到的一些问题,但并不是所有。单单是升级webpack,其实要修改的点就有很多,但是对于陈年的经过 N 手的老项目来说,并不适合直接升级,可能会造成项目更加混乱,因此这里走了一点捷径,绕过了很多升级 webpack 会遇到的坑。升级遇到的大部分问题官方文档都有详细的描述,遇到问题,沉着冷静别惊慌,我们的目标是:远离 bug,不受伤。。。

原文:https://zhuanlan.zhihu.com/p/31436018

广告

Vue.js升级小记


  • 回复“面试题”“ajax”等关键词,可查看前端面试题

  • 其它功能正在完善,不定期更新....


觉得本文对你有帮助?请分享给更多人

关注「」,提升前端技能

以上是关于Vue.js升级小记的主要内容,如果未能解决你的问题,请参考以下文章

第1124期Vue.js 升级踩坑小记

Vue.js高仿饿了么外卖App 前端框架Vue.js 1.0升级2.0

[转]Vue.js特点

经典文摘:饿了么的 PWA 升级实践(结合Vue.js)

Vue.js 路线图和向后兼容性

vue.js是啥