经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
🖖少年,该升级 Vue3 了!
来源:cnblogs  作者:Kagol  时间:2023/9/19 8:41:15  对本文有异议

你好,我是 Kagol。

前言

根据 Vue 官网文档的说明,Vue2 的终止支持时间是 2023 年 12 月 31 日,这意味着从明年开始:

  • Vue2 将不再更新和升级新版本,不再增加新特性,不再修复缺陷

image.png

虽然 Vue3 正式版本已经发布快3年了,但据我了解,现在依然还有很多业务在使用 Vue2,迟迟没有升级 Vue3。

为什么要等到 Vue2 彻底停止维护,才考虑升级 Vue3 这个如此重要的问题呢???

本文是一篇 Vue2 升级 Vue3 的指南,主要包含以下部分:

  1. 使用 Vue CLI 搭建 Vue2 工程
  2. 使用 ElementUI 搭建表格、表单
  3. 使用 OpenTiny Vue 替换一个组件
  4. 使用 OpenTiny Vue 替换一个页面
  5. 使用 OpenTiny Vue 替换整个应用
  6. 使用 gogocode 升级到 Vue3,组件代码无需修改

1 创建 Vue2 项目

先用 Vue CLI 创建一个 Vue2 项目(也可以使用 Vite 配合 @vitejs/plugin-vue2vite-plugin-vue2 插件)。

  1. // 安装 Vue CLI
  2. npm install -g @vue/cli
  3. // 创建 Vue2 项目
  4. vue create vue2-demo

输出以下信息说明项目创建成功

  1. ??  Successfully created project vue2-demo.
  2. ??  Get started with the following commands:
  3. $ cd vue2-demo
  4. $ yarn serve

创建好之后可以执行以下命令启动项目

  1. yarn serve

输出以下命令说明启动成功

  1. App running at:
  2. - Local:   http://localhost:8080/ 
  3. - Network: http://192.168.1.102:8080/

效果如下

图片

2 使用 ElementUI 搭建表格、表单

安装 VueRouter

  1. npm i vue-router@3

main.js

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. import VueRouter from 'vue-router'
  4. const router = new VueRouter({
  5.   routes: [
  6.     {
  7.       path: '/',
  8.       component: () => import('./components/HomePage.vue')
  9.     },
  10.     {
  11.       path: '/form',
  12.       component: () => import('./components/FormPage.vue')
  13.     },
  14.     {
  15.       path: '/list',
  16.       component: () => import('./components/ListPage.vue')
  17.     }
  18.   ]
  19. })
  20. Vue.config.productionTip = false
  21. Vue.use(VueRouter)
  22. new Vue({
  23.   router,
  24.   render: h => h(App),
  25. }).$mount('#app')

App.vue

  1. <template>
  2.   <div id="app">
  3.     <img alt="Vue logo" src="./assets/logo.png">
  4.     <p>
  5.       <!-- use the router-link component for navigation. -->
  6.       <!-- specify the link by passing the `to` prop. -->
  7.       <!-- `<router-link>` will render an `<a>` tag with the correct `href` attribute -->
  8.       <router-link to="/">Home</router-link>
  9.       <router-link to="/form">Form</router-link>
  10.       <router-link to="/list">List</router-link>
  11.     </p>
  12.     <!-- route outlet -->
  13.     <!-- component matched by the route will render here -->
  14.     <router-view></router-view>
  15.   </div>
  16. </template>

安装 ElementUI

  1. npm i element-ui

在 src/views/FormPage.vue 中使用 ElementUI 组件,从 ElementUI 官网组件 demo 里面拷贝代码即可。

典型表单:https://element.eleme.io/#/zh-CN/component/form#dian-xing-biao-dan

  1. <template>
  2. <el-form ref="form" :model="form" label-width="80px">
  3. <el-form-item label="活动名称">
  4. <el-input v-model="form.name"></el-input>
  5. </el-form-item>
  6. <el-form-item label="活动区域">
  7. <el-select v-model="form.region" placeholder="请选择活动区域">
  8. <el-option label="区域一" value="shanghai"></el-option>
  9. <el-option label="区域二" value="beijing"></el-option>
  10. </el-select>
  11. </el-form-item>
  12. <el-form-item label="活动时间">
  13. <el-col :span="11">
  14. <el-date-picker type="date" placeholder="选择日期" v-model="form.date1" style="width: 100%;"></el-date-picker>
  15. </el-col>
  16. <el-col class="line" :span="2">-</el-col>
  17. <el-col :span="11">
  18. <el-time-picker placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker>
  19. </el-col>
  20. </el-form-item>
  21. <el-form-item label="即时配送">
  22. <el-switch v-model="form.delivery"></el-switch>
  23. </el-form-item>
  24. <el-form-item label="活动性质">
  25. <el-checkbox-group v-model="form.type">
  26. <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
  27. <el-checkbox label="地推活动" name="type"></el-checkbox>
  28. <el-checkbox label="线下主题活动" name="type"></el-checkbox>
  29. <el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
  30. </el-checkbox-group>
  31. </el-form-item>
  32. <el-form-item label="特殊资源">
  33. <el-radio-group v-model="form.resource">
  34. <el-radio label="线上品牌商赞助"></el-radio>
  35. <el-radio label="线下场地免费"></el-radio>
  36. </el-radio-group>
  37. </el-form-item>
  38. <el-form-item label="活动形式">
  39. <el-input type="textarea" v-model="form.desc"></el-input>
  40. </el-form-item>
  41. <el-form-item>
  42. <el-button type="primary" @click="onSubmit">立即创建</el-button>
  43. <el-button>取消</el-button>
  44. </el-form-item>
  45. </el-form>
  46. </template>
  47. <script>
  48. export default {
  49. data() {
  50. return {
  51. form: {
  52. name: '',
  53. region: '',
  54. date1: '',
  55. date2: '',
  56. delivery: false,
  57. type: [],
  58. resource: '',
  59. desc: ''
  60. }
  61. }
  62. },
  63. methods: {
  64. onSubmit() {
  65. console.log('submit!');
  66. }
  67. }
  68. }
  69. </script>

效果如下

image.png

表格页面也一样。

src/views/ListPage.vue

  1. <template>
  2. <div>
  3. <div class="filter-bar">
  4. <el-select v-model="value" placeholder="请选择">
  5. <el-option
  6. v-for="item in options"
  7. :key="item.value"
  8. :label="item.label"
  9. :value="item.value"
  10. >
  11. </el-option>
  12. </el-select>
  13. <el-date-picker v-model="value1" type="daterange"> </el-date-picker>
  14. <el-input
  15. v-model="search"
  16. placeholder="输入关键字搜索"
  17. style="width: 300px"
  18. />
  19. <el-button>搜索</el-button>
  20. </div>
  21. <el-table :data="tableData" style="width: 100%">
  22. <el-table-column prop="date" label="日期" width="180"> </el-table-column>
  23. <el-table-column prop="name" label="姓名" width="180"> </el-table-column>
  24. <el-table-column prop="address" label="地址"> </el-table-column>
  25. </el-table>
  26. </div>
  27. </template>
  28. <script>
  29. export default {
  30. data() {
  31. return {
  32. value1: '',
  33. options: [
  34. {
  35. value: '选项1',
  36. label: '王小虎'
  37. },
  38. {
  39. value: '选项2',
  40. label: '张三'
  41. },
  42. {
  43. value: '选项3',
  44. label: '李小萌'
  45. },
  46. {
  47. value: '选项4',
  48. label: '令狐冲'
  49. }
  50. ],
  51. value: '',
  52. search: '',
  53. tableData: [
  54. {
  55. date: '2016-05-02',
  56. name: '王小虎',
  57. address: '上海市普陀区金沙江路 1518 弄'
  58. },
  59. {
  60. date: '2016-05-04',
  61. name: '张三',
  62. address: '上海市普陀区金沙江路 1517 弄'
  63. },
  64. {
  65. date: '2016-05-01',
  66. name: '李小萌',
  67. address: '上海市普陀区金沙江路 1519 弄'
  68. },
  69. {
  70. date: '2016-05-03',
  71. name: '令狐冲',
  72. address: '上海市普陀区金沙江路 1516 弄'
  73. }
  74. ]
  75. }
  76. }
  77. }
  78. </script>
  79. <style lang="less" scoped>
  80. .filter-bar {
  81. display: flex;
  82. & > * {
  83. margin-right: 20px;
  84. }
  85. }
  86. </style>

效果如下

image.png

首页可以放一张轮播图。

src/views/HomePage.vue

  1. <template>
  2. <el-carousel>
  3. <el-carousel-item v-for="item in 4" :key="item">
  4. <img :src="`https://picsum.photos/1350/900?random=${item}`" style="width: 100%;">
  5. </el-carousel-item>
  6. </el-carousel>
  7. </template>
  8. <style>
  9. .el-carousel__item h3 {
  10. color: #475669;
  11. font-size: 14px;
  12. opacity: 0.75;
  13. line-height: 150px;
  14. margin: 0;
  15. }
  16. .el-carousel__item:nth-child(2n) {
  17. background-color: #99a9bf;
  18. }
  19. .el-carousel__item:nth-child(2n+1) {
  20. background-color: #d3dce6;
  21. }
  22. </style>

效果如下

image.png

参考:

3 使用 OpenTiny Vue 替换一个组件

OpenTiny Vue 的组件都是支持按需引入的,一开始我们步子不要迈得太大,先尝试替换一个 Button 组件。

安装 @opentiny/vue@2

  1. npm i @opentiny/vue@2

image.png

表单页面里面有两个按钮,我们尝试将其替换成 OpenTiny Vue 的 Button 组件。

替换的步骤很简单,不需要修改现有的代码,只需要增加4行代码即可。

src/views/FormPage.vue

  1. <template>
  2. <el-form ref="form" :model="form" label-width="80px">
  3. <el-form-item label="活动名称">
  4. <el-input v-model="form.name"></el-input>
  5. </el-form-item>
  6. ...
  7. <el-form-item>
  8. <el-button type="primary" @click="onSubmit">立即创建</el-button>
  9. <el-button>取消</el-button>
  10. </el-form-item>
  11. </el-form>
  12. </template>
  13. <script>
  14. + import { Button } from '@opentiny/vue'
  15. export default {
  16. + components: {
  17. + ElButton: Button
  18. + },
  19. data() {
  20. return {
  21. form: {
  22. name: '',
  23. ...
  24. }
  25. }
  26. },
  27. methods: {
  28. onSubmit() {
  29. console.log('submit!');
  30. }
  31. }
  32. }
  33. </script>

效果如下

image.png

4 使用 OpenTiny Vue 替换一个页面

接下来我们步子逐渐迈大一点,将整个 FormPage 页面的 ElementUI 组件全部替换成 OpenTiny Vue 的组件。

FormPage 页面一共有以下组件:

  • Button
  • Form
  • FormItem
  • Input
  • Select
  • Option
  • Col
  • DatePicker
  • TimePicker
  • Switch
  • CheckboxGroup
  • Checkbox
  • RadioGroup
  • Radio

替换的方式和前面替换 Button 组件一模一样,只需要多加一些组件。

  1. <template>
  2. <el-form ref="form" :model="form" label-width="80px">
  3. <el-form-item label="活动名称">
  4. <el-input v-model="form.name"></el-input>
  5. </el-form-item>
  6. ...
  7. <el-form-item>
  8. <el-button type="primary" @click="onSubmit">立即创建</el-button>
  9. <el-button>取消</el-button>
  10. </el-form-item>
  11. </el-form>
  12. </template>
  13. <script>
  14. import {
  15. Button,
  16. + Form,
  17. + FormItem,
  18. + Input,
  19. + Select,
  20. + Option,
  21. + Col,
  22. + DatePicker,
  23. + TimePicker,
  24. + Switch,
  25. + CheckboxGroup,
  26. + Checkbox,
  27. + RadioGroup,
  28. + Radio,
  29. } from '@opentiny/vue'
  30. export default {
  31. components: {
  32. ElButton: Button,
  33. + ElForm: Form,
  34. + ElFormItem: FormItem,
  35. + ElInput: Input,
  36. + ElSelect: Select,
  37. + ElOption: Option,
  38. + ElCol: Col,
  39. + ElDatePicker: DatePicker,
  40. + ElTimePicker: TimePicker,
  41. + ElSwitch: Switch,
  42. + ElCheckboxGroup: CheckboxGroup,
  43. + ElCheckbox: Checkbox,
  44. + ElRadioGroup: RadioGroup,
  45. + ElRadio: Radio,
  46. },
  47. data() {
  48. return {
  49. form: {
  50. name: '',
  51. ...
  52. }
  53. }
  54. },
  55. methods: {
  56. onSubmit() {
  57. console.log('submit!');
  58. }
  59. }
  60. }
  61. </script>

效果如下

image.png

5 使用 OpenTiny Vue 替换整体应用

最后一步就是使用 OpenTiny Vue 替换整个应用的 ElementUI。

我们可以用前面的方法进行替换,但考虑到整个应用的页面众多,我们采取另一种方式。

我们已经全局注册了 ElementUI 组件库,接下来我们全局注册 OpenTiny Vue 组件库。

  1. import Vue from 'vue'
  2. - import ElementUI from 'element-ui'
  3. - import 'element-ui/lib/theme-chalk/index.css'
  4. + import TinyVue from '@opentiny/vue'
  5. import App from './App.vue'
  6. import VueRouter from 'vue-router'
  7. - Vue.use(ElementUI)
  8. + Vue.use(TinyVue)
  9. const router = new VueRouter({
  10. routes: [
  11. ...
  12. ]
  13. })
  14. Vue.config.productionTip = false
  15. Vue.use(VueRouter)
  16. new Vue({
  17. router,
  18. render: (h) => h(App)
  19. }).$mount('#app')

然后全局替换 el-tiny-,一步到位!

image.png

效果如下

首页轮播

image.png

表单

image.png

表格

image.png

是不是非常丝滑,更丝滑的还在后面!

接下来我们将借助一款神器:gogocode,实现 Vue2 项目平滑升级 Vue3。

6 使用 gogocode 升级到 Vue3

安装 gogocode:

  1. npm install gogocode-cli -g

转换源码:

  1. gogocode -s ./src/ -t gogocode-plugin-vue -o ./src/

升级依赖:

  1. gogocode -s package.json -t gogocode-plugin-vue -o package.json

升级 TinyVue 组件库到 3.0 版本

  1. npm i @opentiny/vue@3

组件代码无需做任何修改,完成 Vue2 项目平滑升级到 Vue3 ??

执行 npm run dev 命令启动项目,除了 Vue 版本号变化之后,其他任何效果都没有变化。

首页轮播

image.png

表单

image.png

表格

image.png

遇到的问题

问题一:error 'v-model' directives require no argument vue/no-v-model-argument

解决方法:修改 FormPage.vue 中的 v-model:value 为 v-model 即可

问题二:Failed to resolve component: router-link

解决方案:修改 main.js 中 use(router) 代码顺序即可

  1. window.$vueApp = Vue.createApp(App)
  2. window.$vueApp.mount('#app')
  3. import * as Vue from 'vue'
  4. import TinyVue from '@opentiny/vue'
  5. import App from './App.vue'
  6. import * as VueRouter from 'vue-router'
  7. - window.$vueApp.use(TinyVue)
  8. const router = VueRouter.createRouter({
  9. history: VueRouter.createWebHashHistory(),
  10. routes: [
  11. ...
  12. ],
  13. })
  14. window.$vueApp = Vue.createApp(App)
  15. + window.$vueApp.use(TinyVue)
  16. + window.$vueApp.use(router) // 这一行代码需要放到 mount 之前
  17. window.$vueApp.mount('#app')
  18. window.$vueApp.config.globalProperties.routerAppend = (path, pathToAppend) => {
  19. return path + (path.endsWith('/') ? '' : '/') + pathToAppend
  20. }
  21. - window.$vueApp.use(router)

如果你在升级 Vue3 的过程中遇到任何问题,欢迎在评论区进行讨论,也欢迎添加 OpenTiny 小助手 opentiny-official 与我们交流!

本文涉及到的源码链接:

Element 升级 OpenTiny 的 demo 项目在 packages/element-to-opentiny 子包里。

  • vue2 项目在 vue2 分支
  • vue3 项目在 vue3 分支

关于 OpenTiny

OpenTiny 是一套华为云出品的企业级组件库解决方案,适配 PC 端 / 移动端等多端,涵盖 Vue2 / Vue3 / Angular 多技术栈,拥有主题配置系统 / 中后台模板 / CLI 命令行等效率提升工具,可帮助开发者高效开发 Web 应用。

image.png

核心亮点:

  1. 跨端跨框架:使用 Renderless 无渲染组件设计架构,实现了一套代码同时支持 Vue2 / Vue3,PC / Mobile 端,并支持函数级别的逻辑定制和全模板替换,灵活性好、二次开发能力强。
  2. 组件丰富:PC 端有80+组件,移动端有30+组件,包含高频组件 Table、Tree、Select 等,内置虚拟滚动,保证大数据场景下的流畅体验,除了业界常见组件之外,我们还提供了一些独有的特色组件,如:Split 面板分割器、IpAddress IP地址输入框、Calendar 日历、Crop 图片裁切等
  3. 配置式组件:组件支持模板式和配置式两种使用方式,适合低代码平台,目前团队已经将 OpenTiny 集成到内部的低代码平台,针对低码平台做了大量优化
  4. 周边生态齐全:提供了基于 Angular + TypeScript 的 TinyNG 组件库,提供包含 10+ 实用功能、20+ 典型页面的 TinyPro 中后台模板,提供覆盖前端开发全流程的 TinyCLI 工程化工具,提供强大的在线主题配置平台 TinyTheme

欢迎加入 OpenTiny 开源社区。

添加微信小助手:opentiny-official,一起参与共建!

OpenTiny 官网:https://opentiny.design/

Vue组件库https://opentiny.design/tiny-vue

Angular组件库https://opentiny.design/tiny-ng

OpenTiny 代码仓库:https://github.com/opentiny/ (欢迎 Star ?)

往期文章推荐

原文链接:https://www.cnblogs.com/kagol/p/17712132.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号