踩坑日记一(composition-api)
vue2 中使用 composition-api
# composition-api
# 安装依赖
npm i @vue/composition-api
# main 文件引入
import VueCompositionAPI from '@vue/composition-api';
Vue.use(VueCompositionAPI);
# 新建 .vue 文件
import { ref, watch } from '@vue/composition-api';
export default {
setup() {
const num = ref(1);
return {
num,
};
},
};
再引入了 composition-api 不使用 ts 总觉得不得劲,那我们就引入一下 ts
# 使用 ts
# 安装依赖
npm i typescript ts-loader -D
# webpack 配置
configureWebpack: {
module: {
rules: [
{
// 解析 ts 与 tsx 文件
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
transpileOnly: true,
appendTsSuffixTo: [/\.vue$/],
happyPackMode: false,
},
},
],
},
}
# 新建 tsconfig.json 文件
{
"compilerOptions": {
"baseUrl": ".",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"noEmitOnError": true,
// 与 Vue 的浏览器支持保持一致
"target": "es5",
// 如果使用 webpack 2+ 或 rollup,可以利用 tree-shake:
"module": "es2015",
"strict": true,
"allowJs": true,
"noEmit": false,
"noImplicitThis": true,
"esModuleInterop": true,
"moduleResolution": "node",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["**/*.vue", "**/*.ts"],
"exclude": ["node_modules", "dist"]
}
# shims 文件
在 src 目录下新建一个 shims-vue.d.ts 文件,申明 vue 模块,不然 ts 会报错
/* eslint-disable */
declare module '*.vue' {
import Vue from 'vue';
export default Vue;
}
# 可能遇到的问题
在 script 使用 ts 的时候会报错 Syntax Error: TypeError: loaderContext.getOptions is not a function 解决方案:
npm install ts-loader@~8.2.0
参考链接: 点这里 (opens new window)
# 踩坑
# 需要一个根节点
在 vue3 中 template 文件已经不需要有一个根节点,虽然引入了 '@vue/composition-api' 但是在 vue2 中任然需要有一个根节点包裹。
# 不能使用 setup 语法糖
# for 循环列表不更新的情况
问题:新增的时候视图不能更新但是数据更新了,删除和编辑都可以更新。
这个问题花费了大半天时间才解决这个问题,但是呢重新写个列子一模一样的例子,又复现不了,非常诡异哈,还没找到原因是啥。
解决方案:于是在循环的 dom 结构外加了一层 loading 的状态就解决了 dom 不更新的问题。
# 关于 input 输入一个字符就失去焦点
<div v-for="(item, idx) in spec.list" :key="item.giftNum + idx">
<el-input
@change="(event) => giftNumChangeHandler(event, index, idx)"
v-model="item.giftNum"
placeholder="输入数量"
size="mini"
clearable
style="width: 80px"
></el-input>
</div>
由于该数组里面没有唯一值 id, 因此使用了 giftNum + idx 的形式当做 key 值使用,每次输入的时候, dom 都会重新创建一个新的,所以才导致了输入一个字符之后就失去了焦点。
因此不建议使用子节点绑定的数据给父节点的属性赋值(key)。
解决方案:
:key="idx"
# [Vue warn]: The setup binding property "xxx" is already declared
解决方案1:
由于 vue 已经发布了 2.7.0 版本, 因此呢,直接升级版本,并且修改导入的包就可以了
import { reactive, ref } from '@vue/composition-api';
修改为
import { reactive, ref } from 'vue';
但是呢会遇到另外的报错: 关于深度选择器 ::v-deep 的,不能以这种形式去写,因为 vue3 已经弃用这种写法了,于是我就放弃了继续去修改。改用下面的方案。
解决方案2:
锁定版本:
"@vue/composition-api": "^1.6.2",
"vue": "2.6.14",
"vue-template-compiler": "2.6.14"
参考:https://github.com/vuejs/composition-api/issues/213 (opens new window)