您现在的位置是:首页 > 文章详情

🖖少年,该升级 Vue3 了!

日期:2023-09-18点击:83

你好,我是 Kagol。

前言

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

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

虽然 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 插件)。

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

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

🎉  Successfully created project vue2-demo. 👉  Get started with the following commands: $ cd vue2-demo $ yarn serve 

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

yarn serve 

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

App running at: - Local:   http://localhost:8080/  - Network: http://192.168.1.102:8080/ 

效果如下

2 使用 ElementUI 搭建表格、表单

安装 VueRouter

npm i vue-router@3 

main.js

import Vue from 'vue' import App from './App.vue' import VueRouter from 'vue-router' const router = new VueRouter({   routes: [     {       path: '/',       component: () => import('./components/HomePage.vue')     },     {       path: '/form',       component: () => import('./components/FormPage.vue')     },     {       path: '/list',       component: () => import('./components/ListPage.vue')     }   ] }) Vue.config.productionTip = false Vue.use(VueRouter) new Vue({   router,   render: h => h(App), }).$mount('#app') 

App.vue

<template>   <div id="app">     <img alt="Vue logo" src="./assets/logo.png">     <p>       <!-- use the router-link component for navigation. -->       <!-- specify the link by passing the `to` prop. -->       <!-- `<router-link>` will render an `<a>` tag with the correct `href` attribute -->       <router-link to="/">Home</router-link>       <router-link to="/form">Form</router-link>       <router-link to="/list">List</router-link>     </p>     <!-- route outlet -->     <!-- component matched by the route will render here -->     <router-view></router-view>   </div> </template> 

安装 ElementUI

npm i element-ui 

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

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

<template> <el-form ref="form" :model="form" label-width="80px"> <el-form-item label="活动名称"> <el-input v-model="form.name"></el-input> </el-form-item> <el-form-item label="活动区域"> <el-select v-model="form.region" placeholder="请选择活动区域"> <el-option label="区域一" value="shanghai"></el-option> <el-option label="区域二" value="beijing"></el-option> </el-select> </el-form-item> <el-form-item label="活动时间"> <el-col :span="11"> <el-date-picker type="date" placeholder="选择日期" v-model="form.date1" style="width: 100%;"></el-date-picker> </el-col> <el-col class="line" :span="2">-</el-col> <el-col :span="11"> <el-time-picker placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker> </el-col> </el-form-item> <el-form-item label="即时配送"> <el-switch v-model="form.delivery"></el-switch> </el-form-item> <el-form-item label="活动性质"> <el-checkbox-group v-model="form.type"> <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox> <el-checkbox label="地推活动" name="type"></el-checkbox> <el-checkbox label="线下主题活动" name="type"></el-checkbox> <el-checkbox label="单纯品牌曝光" name="type"></el-checkbox> </el-checkbox-group> </el-form-item> <el-form-item label="特殊资源"> <el-radio-group v-model="form.resource"> <el-radio label="线上品牌商赞助"></el-radio> <el-radio label="线下场地免费"></el-radio> </el-radio-group> </el-form-item> <el-form-item label="活动形式"> <el-input type="textarea" v-model="form.desc"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="onSubmit">立即创建</el-button> <el-button>取消</el-button> </el-form-item> </el-form> </template> <script> export default { data() { return { form: { name: '', region: '', date1: '', date2: '', delivery: false, type: [], resource: '', desc: '' } } }, methods: { onSubmit() { console.log('submit!'); } } } </script> 

效果如下

表格页面也一样。

src/views/ListPage.vue

<template> <div> <div class="filter-bar"> <el-select v-model="value" placeholder="请选择"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" > </el-option> </el-select> <el-date-picker v-model="value1" type="daterange"> </el-date-picker> <el-input v-model="search" placeholder="输入关键字搜索" style="width: 300px" /> <el-button>搜索</el-button> </div> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="日期" width="180"> </el-table-column> <el-table-column prop="name" label="姓名" width="180"> </el-table-column> <el-table-column prop="address" label="地址"> </el-table-column> </el-table> </div> </template> <script> export default { data() { return { value1: '', options: [ { value: '选项1', label: '王小虎' }, { value: '选项2', label: '张三' }, { value: '选项3', label: '李小萌' }, { value: '选项4', label: '令狐冲' } ], value: '', search: '', tableData: [ { date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄' }, { date: '2016-05-04', name: '张三', address: '上海市普陀区金沙江路 1517 弄' }, { date: '2016-05-01', name: '李小萌', address: '上海市普陀区金沙江路 1519 弄' }, { date: '2016-05-03', name: '令狐冲', address: '上海市普陀区金沙江路 1516 弄' } ] } } } </script> <style lang="less" scoped> .filter-bar { display: flex; & > * { margin-right: 20px; } } </style> 

效果如下

首页可以放一张轮播图。

src/views/HomePage.vue

<template> <el-carousel> <el-carousel-item v-for="item in 4" :key="item"> <img :src="`https://picsum.photos/1350/900?random=${item}`" style="width: 100%;"> </el-carousel-item> </el-carousel> </template> <style> .el-carousel__item h3 { color: #475669; font-size: 14px; opacity: 0.75; line-height: 150px; margin: 0; } .el-carousel__item:nth-child(2n) { background-color: #99a9bf; } .el-carousel__item:nth-child(2n+1) { background-color: #d3dce6; } </style> 

效果如下

参考:

3 使用 OpenTiny Vue 替换一个组件

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

安装 @opentiny/vue@2

npm i @opentiny/vue@2 

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

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

src/views/FormPage.vue

<template> <el-form ref="form" :model="form" label-width="80px"> <el-form-item label="活动名称"> <el-input v-model="form.name"></el-input> </el-form-item> ... <el-form-item> <el-button type="primary" @click="onSubmit">立即创建</el-button> <el-button>取消</el-button> </el-form-item> </el-form> </template> <script> + import { Button } from '@opentiny/vue' export default { + components: { + ElButton: Button + }, data() { return { form: { name: '', ... } } }, methods: { onSubmit() { console.log('submit!'); } } } </script> 

效果如下

4 使用 OpenTiny Vue 替换一个页面

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

FormPage 页面一共有以下组件:

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

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

<template> <el-form ref="form" :model="form" label-width="80px"> <el-form-item label="活动名称"> <el-input v-model="form.name"></el-input> </el-form-item> ... <el-form-item> <el-button type="primary" @click="onSubmit">立即创建</el-button> <el-button>取消</el-button> </el-form-item> </el-form> </template> <script> import { Button, + Form, + FormItem, + Input, + Select, + Option, + Col, + DatePicker, + TimePicker, + Switch, + CheckboxGroup, + Checkbox, + RadioGroup, + Radio, } from '@opentiny/vue' export default { components: { ElButton: Button, + ElForm: Form, + ElFormItem: FormItem, + ElInput: Input, + ElSelect: Select, + ElOption: Option, + ElCol: Col, + ElDatePicker: DatePicker, + ElTimePicker: TimePicker, + ElSwitch: Switch, + ElCheckboxGroup: CheckboxGroup, + ElCheckbox: Checkbox, + ElRadioGroup: RadioGroup, + ElRadio: Radio, }, data() { return { form: { name: '', ... } } }, methods: { onSubmit() { console.log('submit!'); } } } </script> 

效果如下

5 使用 OpenTiny Vue 替换整体应用

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

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

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

import Vue from 'vue' - import ElementUI from 'element-ui' - import 'element-ui/lib/theme-chalk/index.css' + import TinyVue from '@opentiny/vue' import App from './App.vue' import VueRouter from 'vue-router' - Vue.use(ElementUI) + Vue.use(TinyVue) const router = new VueRouter({ routes: [ ... ] }) Vue.config.productionTip = false Vue.use(VueRouter) new Vue({ router, render: (h) => h(App) }).$mount('#app') 

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

效果如下

首页轮播

表单

表格

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

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

6 使用 gogocode 升级到 Vue3

安装 gogocode:

npm install gogocode-cli -g 

转换源码:

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

升级依赖:

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

升级 TinyVue 组件库到 3.0 版本

npm i @opentiny/vue@3 

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

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

首页轮播

表单

表格

遇到的问题

问题一: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) 代码顺序即可

window.$vueApp = Vue.createApp(App) window.$vueApp.mount('#app') import * as Vue from 'vue' import TinyVue from '@opentiny/vue' import App from './App.vue' import * as VueRouter from 'vue-router' - window.$vueApp.use(TinyVue) const router = VueRouter.createRouter({ history: VueRouter.createWebHashHistory(), routes: [ ... ], }) window.$vueApp = Vue.createApp(App) + window.$vueApp.use(TinyVue) + window.$vueApp.use(router) // 这一行代码需要放到 mount 之前 window.$vueApp.mount('#app') window.$vueApp.config.globalProperties.routerAppend = (path, pathToAppend) => { return path + (path.endsWith('/') ? '' : '/') + pathToAppend } - 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 应用。

核心亮点:

  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://my.oschina.net/u/4863191/blog/10111409
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章