踩坑日记一(composition-api)

2022/6/30 踩坑日记vue3

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)

# 踩坑

# 需要一个根节点

vue3template 文件已经不需要有一个根节点,虽然引入了 '@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)

Last Updated: 2026/06/09/ 06:29:26