Vue1.x 迁移 Vue2.x 实战

本篇文章记录了完整的前端 Vue1.x 项目迁移至 Vue2.x 的步骤和遇到的问题。并且在迁移的过程也对Vue进行进一步学习。

1 为什么要迁移 Vue2.x

由于项目后面希望用到饿了么的 vue 组件,而且当前很多组件都是基于 Vue2.x 的,对于 Vue1.x 都已经不再维护。

Vue2.x 更加成熟,并且后面准备在移动端接入 weex ,而 weex 中也推荐使用 Vue2.x 进行开发。

综上所述,下定决心开始对 Vue1.x 的项目进行迁移。

2 前期准备

先介绍下原有项目的大致情况。

  1. 项目不是单纯的单页面应用,每个大模块是一个单页面应用,大模块中的子模块的跳转使用路由进行跳转。
  2. 原有项目 vue 版本号1.0.21,vue-router 版本号0.7.13,未使用 vuex ,网络请求用的就是 jquery

希望在迁移后,新功能的添加可以完全使用单页面应用,并且配合用上 vuex 和网络请求库( axios )还有一些其他的插件。

现附上在迁移过程中相关文档地址:

  1. Vue 官方迁移文档
    这也是迁移过程中主要的参考文档
  2. vue-migration-helper
    官方迁移的辅助工具,用以遍历查找出需要迁移的地方。识别出旧有的特性后,就会告知并给出建议,同时附上关于详细信息的链接。
  3. vue-router 2.x 官方文档
  4. 万能的 Google

3 开始迁移

3.1 检查出迁移的地方

先安装官方迁移工具vue-migration-helper

npm install --global vue-migration-helper

安装完成后进入项目目录,扫描项目中文件找出需要迁移的代码位置。(并不能完全找出,但是可以解决大部分的迁移)

我的迁移做法是扫描全局后,专注修改一类迁移问题,修改完后commit并且再次扫描确认该类问题已经解决。然后再解决下一类的问题。

第一次扫描并输出到文件中

vue-migration-helper >a.log

输出一看,WTF!!!500多个迁移点,网上人家迁移就几十个迁移点。呵呵哒了。

第一次扫描结果

3.2 package.json修改

首先提示的是修改 package.json 中的版本号,并重新 npm install

package.json 修改

这个没啥,我直接升到了最新的vue和vue-router版本

3.3 v-link 替换

第一个解决的是 v-link 提示信息如下

替换 v-link

找到相关文档 https://cn.vuejs.org/v2/guide/migration-vue-router.html#v-link-替换

文档描述是把

<a v-link="'/about'">About</a>

替换成

<router-link to="/about">About</router-link>

But,项目中是这么写的

 <button class="btn btn-default pull-right" v-link="{ path: '/'}">返回</button>

查询最新的 vue-router 文档,可以使用编程式导航,改成如下

<button class="btn btn-default pull-right" @click="$router.push({ path: '/'})">返回</button>

然后查找所有 v-link 类型问题一个个全部改过来,commit 提交。重新扫描一次。

3.4 $index 和 $key 的移除

$index$key 的移除问题的提示是这样的

$index 和 $key 的移除

文档见 https://cn.vuejs.org/v2/guide/migration.html#index-and-key-移除

主要是 Vue2.x 中移除了隐变量 $index$key,全部显示声明。修改例子如下

<tr v-for="clinic of clinicDatas">
    <td>{{ $index+1 }}</td>
</tr>

改为:

<tr v-for="(clinic, index) of clinicDatas">
    <td>{{ index+1 }}</td>
</tr>

回头重新看了下 v-for 的文档

默认命名 index 代表索引,key 代表遍历对象的键值。

比如遍历一个数组的时候,第二个参数是 index 索引

<ul id="example-2">
  <li v-for="(item, index) in items">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>

当遍历对象时,第二个参数是 key

<div v-for="(value, key) in object">
  {{ key }} : {{ value }}
</div>

同时如果遍历对象,还可以有第三个参数代表索引

<div v-for="(value, key, index) in object">
  {{ index }}. {{ key }} : {{ value }}
</div>

3.5 HTML 的计算插值移除 ({{{ }}})

HTML 的计算插值移除 提示是这样的

HTML 的计算插值移除

文档见 https://cn.vuejs.org/v2/guide/migration.html#HTML-计算插值-移除

这个替换比较简单,就是把 {{{}}} 全部替换为 v-html

3.6生命周期 ready 替换

生命周期 ready 替换 提示是这样的

生命周期 ready 替换

要把生命周期钩子函数 ready 替换为以下:

mounted: function () {
  this.$nextTick(function () {
    // 代码保证 this.$el 在 document 中
  })
}

在这里我回头看了下 nextTick 的具体概念:https://cn.vuejs.org/v2/guide/reactivity.html#异步更新队列

意思就是当数据发生变化后 DOM 不会立即更新,而是会在一个更新周期时统一更新(感觉就像 Android 的16ms 渲染刷新)。所以使用 nextTick,是一个异步执行,意思是方法里面的代码会在下次 DOM 更新后执行。

3.7 Array-prototype-$remove 移除

Array-prototype-$remove 移除问题的提示:

Array-prototype-$remove 移除

文档见 https://cn.vuejs.org/v2/guide/migration.html#Array-prototype-remove-移除

数组的一个 remove 方法移除了,换成了 splice 方法。

vm.articleList.$remove(vm.temArticle)

改成

var index = vm.articleList.indexOf(vm.temArticle);
vm.articleList.splice(index, 1)

3.8 v-el 和 v-ref 替换

v-elv-ref 替换问题的提示:

v-el 和 v-ref 替换

文档见:https://cn.vuejs.org/v2/guide/migration.html#v-el-和v-ref-替换

直接全局将 v-elv-ref 换成 ref

3.9 属性内部的计算插值移除 ({{ }})

属性内部的计算插值移除的提示:

属性内部的计算插值移除

文档见:https://cn.vuejs.org/v2/guide/migration.html#属性内部的计算插值-移除

属性内部的计算插值已经不能再使用了:

<button class="btn btn-{{ size }}"></button>

应该写成行内表达式:

<button v-bind:class="'btn btn-' + size"></button>

3.10 v-for 遍历数组/对象时的参数顺序变更

v-for 遍历数组/对象时的参数顺序变更问题的提示:

v-for 遍历数组/对象时的参数顺序变更

文档见:https://cn.vuejs.org/v2/guide/migration.html#v-for-遍历数组时的参数顺序-变更

当包含 index key 时,之前遍历数组时的参数顺序是 (index, value) 。现在是 (value, index) , 目的为了和 Javascript 原生中的顺序保持一致。

3.11 router-go 改变

router-go 改变 问题的提示是:

router-go 改变

文档见:https://cn.vuejs.org/v2/guide/migration-vue-router.html#router-go-改变

直接全局替换 router-gorouter-push

3.12 track-by 替换

track-by 替换问题的提示是:

track-by 替换

文档见:https://cn.vuejs.org/v2/guide/migration.html#track-by-替换

直接代码全局替换 track-by:key

3.13 router 路由定义的替换

router 替换的提示是:

router 路由定义的替换

文档见:https://cn.vuejs.org/v2/guide/migration-vue-router.html#router-map-替换

这个地方比较麻烦,要把所有路由定义都修改了。包括子路由的定义。原来的代码是:

import Vue from 'vue'
import Router from 'vue-router'
...

Vue.use(Router)
var router = new Router()
router.map({//定义路由映射
  '/': {
    name: 'main',
    component: Main,
    subRoutes: {
      '/': {
        name: 'list',
        component: List
      },
      '/list': {
        name: 'list',
        component: List
      }
    },
  },
  '/add/:assetId': {
    name: 'add',
    component: Add
  }
});
router.start(Assets, '#app')

修改为:

import Vue from 'vue'
import VueRouter from 'vue-router'
...

Vue.use(VueRouter)

var router = new VueRouter({
  routes: [
    {
      path: '/',
      name: 'main',
      component: Main,
      children: [
        {
          path: '/',
          name: 'list',
          component: List
        },
        {
          path: '/list',
          name: 'list',
          component: List
        }
      ]
    },
    {
      path: '/add/:assetId',
      name: 'add',
      component: Add
    }
  ]
})

const vm = new Vue({
  router,
  render: h => h(Assets)
}).$mount('#app')

3.14 v-bind 的 once 和 sync 修饰符移除

v-bindoncesync 修饰符移除问题提示是:

v-bind 的 once 和 sync 修饰符移除

文档见:https://cn.vuejs.org/v2/guide/migration.html#v-bind-的-once和-sync-修饰符-移除

这个问题将近 100 个地方,因为项目中定义了大量的组件。比如 翻页组件、日期组件、上传组件、地点组件等等。

在 Vue1.x 时可以增加 sync 修饰符实现父组件和子组件的双向绑定,但是到了 Vue2.x prop 只能单向传递,意思就是只能父组件以 prop 方式将数据传入子组件,但是子组件中不可以对 prop 中的值进行修改,即无法双向绑定。

如果想要通知父组件进行数据修改需要定义组件事件,然后子组件中使用 $emit(eventName) 触发事件,父组件中使用 $on(eventName) 监听事件。

这个问题改的比较多,消耗了很多的时间。首先我要把涉及的组件重新设计,改成反向事件触发修改父组件属性,然后父组件要监听修改函数。

4 编译项目

至此,基本上所有工具扫描出来的问题基本上改完了。但这还远远不够,当我 npm run dev 时又报出来很多错误。基本上总结以下几个问题。

4.1 template 下只能有一个根组件

问题报错:

template 下只能有一个根组件

原来是我的 vue 文件中的 template 节点下有多个 div 节点。不知道为什么 Vue1.x 没有报错。全部统一为一个 div 根节点。

4.2 delete 方法被占用

Paste_Image.png

我的一些方法定义是 delete ,这时报错 delete 是 JavaScript 的关键字。我需要所有修改为另一个名称。

<modal title="系统提示" text="确定删除吗?" id="deleteModal" :confirm-action="delete"></modal>

4.3 重复的 :class 和 :click

这个可能是我在迁移的时候一个标签里有了重复的 :class , :click 属性。自己删除或者整合一下就行

5 运行检查

编译通过后,终于可以跑起来了。这时候就需要每个页面进行测试,每个操作进行测试。发现了以下几个问题

  1. router.afterEach 方法有了修改,工具没有识别出来,手动查询做了修改
    文档可以参见 https://github.com/vuejs/vue-router/blob/1.0/docs/zh-cn/api/after-each.mdhttp://router.vuejs.org/zh-cn/advanced/navigation-guards.html 识别前后版本的区别。
  2. Vue.$set 方法已经废弃但是未被识别,手动查询做了修改
  3. 2.x 中增加了 HTML 保留关键字,之前我定义的 content address 组件都不能叫做这个名字了。要么首字母改成大写。要么换个名字。
    详细可见:https://jingsam.github.io/2016/10/30/vue-components-naming.html

所有页面跑过一遍,很多小细节慢慢调试修改,一定要细心再细心。(改的最多的还是组件的部分)

结尾

最后500多个问题总共耗时2天多的时间才完全跑通原有的项目。不过升级到 Vue2.x 后首先做的就是引入了饿了么组件,感觉方便很多,还有一些其他插件在升级后都可以方便的使用。

注:以上只是我升级迁移过程遇到的问题。每个项目不同会有不同的问题,建议以官方迁移文档为主。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容

  • 朱红色的庙宇在山顶的高处睥睨/幽深的大竹林卧憩在小径的身侧/行走在云雾里的人开始觉得听见了声音/不知道是自己的脚步...
    睡我家喵啊猫啊喵阅读 164评论 0 0
  • 有才又精明,但是太懒 好像什么都懂,甚至有了些作为 但他并不会满足于作为一名旁观者去享受生活 莫泊桑 我崇拜你 伙计
    愤怒的小汪阅读 191评论 0 0
  • 这本书,其实我之前好早就听说过,从来没有想过自己要去读一下。从题目看,无非又是一些神叨叨的内容或者又是一本心灵鸡汤...
    拆书家孟钢阅读 459评论 2 0