记一次vue2项目迁移至vue3经历

5 篇文章 0 订阅
2 篇文章 0 订阅

升级之前建议阅读下面这篇文章,会对升级有帮助

vue官方文档:vue3迁移指南

注:vue3是支持vue2的选项式API风格的

下面就进入升级的流程了

  1. 环境准备,如果node和npm的版本过低需要升级,我的环境如下:

  1. 依赖升级以及错误修复

升级之前项目采用的是vue2.6+ant-design-of-vue1.7+less+axios+webpack,因为项目采用的是vue-cli搭建的,所以第一步是升级vue-cli,通过 vue upgrade 命令升级到最新的 @vue/cli-service

在终端执行npm view vue versions --json.查看vue的历史版本,选择合适的vue3版本后更改package.json,删除node-module,执行yarn重新安装node-module包,安装完成之后安装与vue版本相同的@vue/compact,如果项目中存在vue-template-compiler的话,将其替换为@vue/compiler-sfc

启动项目,根据终端的报错信息来修改项目

2.1

ERROR  ValidationError: Invalid options object. Ignore Plugin has been initialized using an options object that does not match the API schema.
 - options should be one of these:
   object { resourceRegExp, contextRegExp? } | object { checkResource }
   Details:
    * options misses the property 'resourceRegExp'. Should be:
      RegExp
      -> A RegExp to test the request against.
    * options misses the property 'checkResource'. Should be:
      function
      -> A filter function for resource and context.

如果出现以上错误,修改vue.config.js中configureWebpack中 plugin的写法。

报错的写法:

plugins: [
      // Ignore all locale files of moment.js
      new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
    ],

正确的写法:

plugins: [ 
onew webpack.IgnorePlugin(
        {
          resourceRegExp:/^\.\/locale$/,
          contextRegExp:  /moment$/,
        }
)
]

2.2

Invalid options object. PostCSS Loader has been initialized using an options object that does not match the API schema.    
options has an unknown property ‘plugins’. These properties are valid:  
object { postcssOptions?, execute?, sourceMap?, implementation? } 

如果出现以上错误,是因为项目中采用了postcss-pxtorem 或者postcss-px2rem插件导致的运行报错,只需在vue.config.js中更改loaderOptions的写法就可以了

错误的写法:

loaderOptions: {
      postcss: {
        plugins: [
          require('postcss-px2rem')({
            remUnit: 100,
          }),
        ],
      },
    },

正确的写法:

loaderOptions: {
        postcss: {
          postcssOptions:{
            plugins: [
              require('postcss-px2rem')({
                remUnit:100
              }),
            ]
          }
        }
    }

2.3

Uncaught Error: Module build failed (from ./node_modules/css-loader/dist/cjs.js): 
TypeError: node.getIterator is not a function

如果出现上述错误,是因为用了postcss-px2rem插件,该插件与vue3不兼容,可以卸载该插件,安装postcss-pxtorem, vue.config.js修改如下:

css: {  
  loaderOptions: {  
    postcss: {  
      postcssOptions: {  
        plugins: [  
          require('postcss-pxtorem')({  
            // remUnit: 100,  
            rootValue: 100,  
            // unitPrecision: 5,  
            propList: ['*'],  
          }),  
        ],  
      },  
    },  
  },  
},

2.4

Component name “xxx“ should always be multi-word vue/multi-word-component-names

升级为vue3后,文件的命名不符合规范,有2种解决方式:

一是修改组件文件的命名

另一种是更改eslint验证规则,内容如下

module.exports = {  
  root: true,  
  env: {  
    node: true  
  },  
  'extends': [  
    'plugin:vue/essential',  
    'eslint:recommended'  
  ],  
  parserOptions: {  
    parser: '@babel/eslint-parser'  
  },  
  rules: {  
    // 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',  
    // 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',  
     //在rules中添加自定义规则  
     //关闭组件命名规则  
     "vue/multi-word-component-names":"off",  
     "vue/no-v-model-argument":"off"  
  },  
  // overrides: [  
  //   {  
  //     files: [  
  //       '**/__tests__/*.{j,t}s?(x)',  
  //       '**/tests/unit/**/*.spec.{j,t}s?(x)'  
  //     ],  
  //     env: {  
  //       jest: true  
  //     }  
  //   }  
  // ]  
}  

到这里运行项目基本就不会报错了

3.接下来就是修改main.js

原来的写法:

new Vue({  
  router,  
  store,  
  render: (h) => h(App),  
}).$mount('#app') 

新的写法:

import {createApp} from 'vue'  
  
const app = createApp(App)  
  
app.use(store)  
app.use(router)  
app.use(Antd)  
app.use(Plugins)  
  
app.config.productionTip = false;  
app.config.globalProperties.$message = message;  
app.config.globalProperties.$filters = filters  
  
app.mount('#app') 

需要注意的是app.use()的使用顺序

更改完之后升级vue-router,vuex到最新的版本,然后升级UIant-design,综合所有原因,UI框架最终选择了版本2的,ant-design升级建议了解下这篇文章

原来vue-router的写法:

import Vue from 'vue'  
import Router from 'vue-router'  
Vue.use(Router)  
  
function initRouter(isAsync) {  
  const options = isAsync  
    ? require('./async/config.async').default  
    : require('./config').default  
  formatRoutes(options.routes)  
  // 路由默认模式  
  options.mode = 'history'  
  return new Router(options)  
}

升级后的写法:

import { createRouter, createWebHistory  } from "vue-router";  
function initRouter(isAsync) {  
  const options = isAsync  
    ? require('./async/config.async').default  
    : require('./config').default  
  formatRoutes(options.routes)  
  options.history = createWebHistory()  
  return createRouter(options)  
}  

原来vuex的写法:

import Vue from 'vue'  
import Vuex from 'vuex'  
import modules from './modules'  
  
Vue.use(Vuex)  
const store = new Vuex.Store({ modules })

升级后的写法:

import { createStore } from 'vuex'  
import modules from './modules'  
  
const store = createStore({ modules })  
  
export default store 

4.更改之后运行项目,可以看到控制台有非常多的警告

之后就是根据警告来修改代码

4.1

Vue.extend is not a function

如果出现上述错误,有可能是插件不兼容,可以根据提示找到相应的文档暂时注释该插件的使用,后续再放开,升级插件或者是找到可更换的插件

4.2

Non-function value encountered for default slot. Prefer function slots for better performance.

vue3 更改了h函数的语法。原来的h函数可以从render 函数中获取,但是vue3当中获取h函数的方法改成了 import { h } from ‘vue’.并且语法改成了h(节点的标签名,节点的属性(如果没有属性,可以用{}代替),节点标签的内容(注意这块改成了对象)),详情可以参考这篇文章

4.3

Extraneous non-props attributes (style) were passed to component but could not be automatically inherited because component renders fragment or text root nodes.

原因:在组件的节点上添加了样式

解决办法:在组件的外面套一层标签,把组件的样式放到这个标签上

4.4 Invalid VNode type: undefined (undefined)

原因:某个节点获取不到,我这边是动态引入组件,()=>import(‘@/components/tag/index.vue’) 报的警告

解决方式:vue3 增加了一个动态注册组件的方法defineAsyncComponent,用这个方法包裹一下就可以啦

4.5

Vue received a Component which was made a reactive object. This can lead to unnecessary performance overhead, and should be avoided by marking the component with `markRaw` or using `shallowRef` instead of `ref`.

原因:组件是一个响应对象,将会进一步引入性能开销,也是解决警告5后出现的

解决方法:用markRaw包裹一下,写法如下:

markRaw(defineAsyncComponent(()=> import (‘组件路径’)))

解决完上面的问题,项目基本上就可以正常的运行啦

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值