1、新建一个vue3项目
新建项目指南
2、将项目的配置文件复制过来
其中eslint配置需要修改成vue3相匹配的规则推荐
// .eslintrc.js
module.exports = {
// ESLint 一旦发现配置文件中有 "root": true,它就会停止在父级目录中寻找。
root: true,
// 指定脚本的运行环境。每种环境都有一组特定的预定义全局变量。
env: {
browser: true,
},
// 启用的规则
extends: [
'plugin:vue/vue3-recommended',
],
parserOptions: {
// js的版本
ecmaVersion: 13,
// 解析器
parser: '@typescript-eslint/parser',
// 模块化方案
sourceType: 'module',
// 支持jsx语法
ecmaFeatures: {
jsx: true
}
},
// 引用的插件 下载的插件去掉eslint-plugin-前缀引入
plugins: ['vue', '@typescript-eslint', 'import', 'node', 'promise'],
// 自定义规则
rules: {},
}
3、安装eslint中相关插件和模块
npm install typescript @typescript-eslint/parser eslint-plugin-@typescript-eslint
npm install eslint-plugin-import eslint-plugin-node eslint-plugin-promise
4、启动项目,解决报错
- Cannot find module 'compression-webpack-plugin'
npm install compression-webpack-plugin@6.1.1
- babel-polyfill in multi (webpack)-dev-server/client
npm install babel-polyfill
- 解决 NPM 安装应用出现 ERESOLVE 错误 版本不匹配
npm install xxx --legacy-peer-deps
5、移入index.html
修改vue.config.js中vue的cdn地址
6、移入main.js、app.vue
// 修改前
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import http from '@/assets/js/http';
import common from '@/assets/js/common';
import { JsEnum } from '@/assets/js/JsEnum';
import loader from '@/components/SlotLoader';
import asyncLoader from '@/components/AsyncLoader';
import "@/assets/icon/iconfont.css";
import rulePolicy from '@/assets/js/directives/rule-policy.js';
import model from '@/assets/js/model.js';
import draggable from 'vuedraggable';
Vue.directive(rulePolicy.name, rulePolicy.rule(store, bus, http));
Vue.use(http);
Vue.prototype.common = common;
Vue.prototype.JsEnum = JsEnum;
Vue.prototype.model = model;
Vue.prototype.$moment = moment;
Vue.prototype.$momenttz = momenttz;
Vue.component('loader', loader);
Vue.component('async-loader', asyncLoader);
Vue.component('svg-icon', svgIcon);
Vue.component('draggable', draggable);
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
});
// 修改后
import { createApp } from 'vue';
import App from './App.vue';
import http from '@/assets/js/http';
import common from '@/assets/js/common';
import { JsEnum } from '@/assets/js/JsEnum';
import bus from '@/assets/js/bus';
import loader from '@/components/SlotLoader';
import asyncLoader from '@/components/AsyncLoader';
import draggable from 'vuedraggable';
import rulePolicy from '@/assets/js/directives/rule-policy.js';
import model from '@/assets/js/model.js';
const app = createApp({
components: { App },
template: '<App/>'
})
app.directive(rulePolicy.name, rulePolicy.rule(store, bus));
app.use(store)
app.use(router)
app.use(http)
app.mount('#app');
app.component('Loader', loader);
app.component('AsyncLoader', asyncLoader);
app.component('Draggable', draggable);
app.config.globalProperties.common = common;
app.config.globalProperties.JsEnum = JsEnum;
app.config.globalProperties.model = model;
- less-loader版本太高报错 segmentfault.com/a/119000003…
- vue-router迁移
// 修改前
import Router from 'vue-router';
const router = new Router({
mode: 'history',
routes: routes,
base: common.getTS(),
fallback: false
});
// 修改后
import {createRouter} from 'vue-router';
const router = createRouter({
history: createWebHistory(common.getTS()),
routes: routes,
});
// 修改前
import Vuex from 'vuex';
const store = new Vuex.Store({
state,
getters,
mutations,
actions
});
// 修改后
import { createStore } from 'vuex';
const store = createStore({
state,
getters,
mutations,
actions
});
- 安装包
npm i svg-sprite-loader npm i -S vuedraggable@next
- [@vue/compiler-sfc] the >>> and /deep/ combinators have been deprecated. Use :deep() instead. vscode使用正则替换
// 匹配字段
/deep/(.*) \{
// 替换字段
:deep($1) {
// 匹配前
/deep/ thead {
// 匹配后
:deep(thead) {
// 修改前
import VueI18n from 'vue-i18n';
const i18n = new VueI18n({
...options
})
app.use(i18n)
// 修改后
import {createI18n} from 'vue-i18n';
const i18n = createI18n({
...options
})
app.use(i18n)
note!获取复杂数据类型需要更换api vue i18n v9的迁移后的$t()无法获取数组、对象
// 修改前
this.$t('navmenu');
// 修改后
this.$tm('navmenu');
- bus升级 Vue 3 中如何优雅的使用eventBus
- slot
slotattributes are deprecated
<!-- 修改前 -->
<a slot="other" href="javascript:;">{{$t('footer.department')}}</a>
<!-- 修改后 -->
<template #other>
<a href="javascript:;">{{ $t('footer.department') }}</a>
</template>
正则匹配(仅适用部分情况,换行情况不知道要怎么匹配,菜菜子😣)
<div slot="content">(.*)</div>
<template #content><div>$1</div></template>
- v-for的key值绑定
<template v-for>key should be placed on the<template>tag
<!-- 修改前 -->
<template v-for="(subItem, subIndex) in item.ChildrenNodes">
<div :key="subIndex"></div>
</template>
<!-- 修改后 -->
<template v-for="(subItem, subIndex) in item.ChildrenNodes" :key="subIndex">
<div></div>
</template>
- .native被弃用
'.native' modifier on 'v-on' directive is deprecated
<!-- 修改前 -->
<div @click.native="handleClick"></div>
<!-- 修改后 -->
<div @click="handleClick"></div>
- 改写axios全局挂载
// http.js
// 修改前
function install (app) {
Object.defineProperties(Vue.prototype, {
$http: {
get () {
if (!self) {
self = this;
}
return axios;
}
}
});
}
// 修改后
function install (app) {
app.config.globalProperties.$http = axios
}
- this.set](juejin.cn/post/706494…)
匹配字段
this\.\$set\((.*),\s?['|"](.*)['|"],\s?(.*)\)
this\.\$set\((.*),\s?['|"](.*)['|"],\s?(.*)\);
替换字段
$1.$2 = $3
- render方法改造
// 修改前
render(h){
return h()
}
// 修改后
import { h } from 'vue'
render(){
return h()
}
- 遇到一个很奇怪的问题;导入部分组件后没有更改文件webpack也会自动重新编译 调试发现是组件名称不规范导致的
// 修改前
export default {
name: "Achievement.PC.Setting",
};
// 修改后
export default {
name: "AchievementPCSetting",
};
- this._l替换
这是vue原型上渲染列表的方法,在vue3中可以直接从vue中导出renderList方法进行使用
// 修改前
const tabs = this._l(panes, (pane, index) => {
......
}
// 修改后
import { renderList } from 'vue'
const tabs = renderList(panes, (pane, index) => {
......
}
- 获取slots不兼容处理
// 修改前
this.$slots.default.filter(v => {
......
})
// 修改后
const slots = this.$slots.default && this.$slots.default()
slots.filter(v => {
......
})
- ts声明全局变量
新建global.d.ts文件
interface Window {
lang: string;
}
- ts声明索引类型 www.51cto.com/article/706…
🌰:定义以下数据结构可以动态声明索引类型
"Common": {
"dev": {
"a": "xxx",
"b": "xxx",
...
},
"prod": {
"a": "xxx",
"b": "xxx",
...
},
"yun": {
"a": "xxx",
"b": "xxx",
...
},
"API": {
"logOut": {
"Method": "POST",
"URL": "/api/Logout"
},
}
},
interface IApi {
[key: string]: {
Method: 'post' | 'POST' | 'get' | 'GET';
URL: string;
};
}
interface IUrl {
[key: string]: string;
}
interface ICommonItem {
[key: string]: IUrl | IApi;
API: IApi;
}