背景
在很多情况下,我们的项目没有办法直接升级到vue3
但是我们又想体验vue3
的一些用法,这种情况下,我们就需要对项目进行改造,这是我们在使用若依框架的时候的一个升级方案,希望能给大家带来一些灵感。
支持vue3的响应式api
通过 vue-demi
和 @vue/composition-api
来实现vue3的api的使用。
最简单的使用方法。
在首页的 index.vue
中进行测试。
<template>
<div>
{{ counter }}
<el-button @click="add">增加</el-button>
</div>
</template>
<script>
import { ref } from "vue-demi"
export default {
setup(){
const counter = ref(1);
const add = () => {
counter.value ++
}
}
}
</script>
支持setup的语法模式
这里需要使用到的是github.com/unplugin/un…
安装插件
npm i -D unplugin-vue2-script-setup
使用插件
在 vue.config.js
中导入插件
const ScriptSetup = require('unplugin-vue2-script-setup/webpack').default
module.exports = {
// ... 忽略前面的配置
plugins:[
// ... 忽略前面的配置
ScriptSetup({})
]
// ... 忽略后面的配置
}
实现volar的提示
若要实现volar的提示,需要安装一下 @vue/runtime-dom
npm i -D @vue/runtime-dom
为了避免错误,所以需要配置一下tsconfig.json 因为若依中不存在这个配置文件,需要我们重新创建一个新的配置文件。
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
"jsxImportSource": "vue",
"types": [
"unplugin-vue2-script-setup/types"
],
/* Linting */
"allowJs":true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
// paths
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"vueCompilerOptions": {
"target": 2
},
"include": [
"src/**/*.ts",
"src/**/*.js",
"src/**/*.vue"
]
}
对工程功能进行测试,将原来的写法改成setup的写法
<template>
<div>
{{ counter }}
<el-button @click="add">增加</el-button>
</div>
</template>
<script setup>
import { ref } from "vue-demi"
const counter = ref(1);
const add = () => {
counter.value ++
}
</script>
测试是否可以正常运行。
实现自动导入
这里使用到的插件是unplugin-auto-import 需要先安装一下这个插件
npm i -D unplugin-auto-import
安装完成后在 vue.config.js
中进行配置
module.exports = {
/* ... */
plugins: [
require('unplugin-auto-import/webpack').default({ /* options */
imports:["vue-demi"],
dirs:["src/composable"],
}),
],
}
然后再对demo进行改造删除导入再进行测试
<template>
<div>
{{ counter }}
<el-button @click="add">增加</el-button>
</div>
</template>
<script setup>
const counter = ref(1);
const add = () => {
counter.value ++
}
</script>
若依中在setup中使用字典
创建一个composable的文件夹,用于存放组合式api的代码,创建一个dict.js的文件
将一下代码拷贝到 dict.js
文件中。
import { getCurrentInstance, ref, nextTick} from "vue-demi"
import Dict from "@/utils/dict/Dict.js"
export const useDict = (dicts,$options = {}) =>{
const dict = ref()
const instance = getCurrentInstance()
const options = instance?.proxy?._dictOptions ?? {};
if(dicts.length > 0){
dict.value = new Dict();
dict.value.owner = instance
options.onCreated && options.onCreated(dict.value)
dict.value.init({
...options,
types:dicts
}).then(() => {
options.onReady && options.onReady(dict.value)
nextTick(() => {
instance.emit('dictReady', dict.value)
if ($options.methods && $options.methods.onDictReady instanceof Function) {
$options.methods.onDictReady?.(dict.value)
}
})
})
}
return {
dict
}
}
接下来需要在 src/utils/dict/index.js
中,加入如下的一行代码
export default function(Vue, options) {
mergeOptions(options)
+ // 数据挂载到原型上
+ Vue.prototype._dictOptions = options;
}
这样我们就完成了dict字典的支持改造。 我们进行相应的测试:
<template>
<div>
{{ a }}
<el-button @click="handleClick">按钮
</el-button>
<el-select v-model="data" placeholder="请选择任务分组">
<el-option
v-for="dict in dict.type.sys_job_group"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
{{ data }}
</div>
</template>
<script setup>
import { useDict } from "@/composable/dict"
const { dict } = useDict(['sys_job_group', 'sys_job_status'])
const a = ref(1)
const data = ref()
const handleClick = () => {
a.value ++
}
</script>