Vue3踩坑记录

目录

一、定义常变量

1.1、ref和reactive到底用谁?

二、双向绑定

2.1、直接改变表格该行数据

2.1、在弹窗改变表格该行数据

一、定义常变量

1.1、ref和reactive到底用谁?

已知:使用ref定义基础类型数据;使用reactive定义复杂对象或数组;

javascript 复制代码
const items = reactive<string[]>([]);

const updateItems= () => {
  //以下都会报错 'items' is constant
  items = []
  items = res.data.items
};

报错原因:

reactive的常量不能直接重新赋值,可以通过修改数组内容来更新数据。

解决方法:

(1)、替换数组中的所有元素

javascript 复制代码
  items.length = 0; // 清空数组
  items.splice(0, items.length); // 清空数组
  Object.assign(items, []); //创建一个新的数组并赋值给 items

  items.push(...res.data.items)

(2)、ref 支持重新赋值

javascript 复制代码
const items = ref<string[]>([]);

const updateItems= () => {
  items.value = []; // 重新赋值整个数组
}

备注:

如果是对象:除非用ref,否则只能这样逐个赋值,且用 let 进行定义。

javascript 复制代码
     for (let key in res.data) {
        editForm[key] = res.data[key];
      }

二、双向绑定

2.1、直接改变表格该行数据

html 复制代码
<el-table height="100%" border class="mt20" size="large" v-loading="pager.loading" :data="tableData">
            <el-table-column label="工厂" prop="factoryCode" header-align="center" align="center" show-overflow-tooltip />
            <el-table-column label="设计记录sku" prop="sku" width="200" header-align="center" align="center"
              show-overflow-tooltip />
            <el-table-column label="格式" prop="sc_img_type" show-overflow-tooltip header-align="center" align="center">
              <template #default="{ row }">
                <el-tag v-if="row.sc_img_type == 1">JPG</el-tag>
                <el-tag v-if="row.sc_img_type == 2">SVG</el-tag>
                <el-tag v-if="row.sc_img_type == 3">TIFF</el-tag>
              </template>
            </el-table-column>
            <el-table-column label="创建时间" width="180" prop="create_time" show-overflow-tooltip header-align="center"
              align="center"></el-table-column>
            <el-table-column label="操作" show-overflow-tooltip header-align="center" align="center">
              <template #default="{ row }">
                <el-button type="primary" @click="updateRow(row)">编辑</el-button>
              </template>
            </el-table-column>
</el-table>
<script lang="ts" setup>
const updateRow = (row) => {
  row.factoryCode = "改变工厂名称";
};
</script>
javascript 复制代码
updateRow(row) {
      row.name = '改变后的名称'; // 修改传入的 row 对象
}

总结:

因为 tableData 是响应式的,Vue3 会把它内部的每一项(即 row)都变成响应式对象。当你修改其中的属性时,Vue3 会通过代理(Proxy)检测到这个属性的变化,并更新 DOM。

因为row 是响应式对象,访问/修改 row.name,Vue2 会触发getter或setter,从而通知视图更新。Vue 2 的响应式系统是基于 Object.defineProperty 实现的,它会使得对象的每个属性都变成 getter 和 setter,从而实现双向绑定。

2.1、在弹窗改变表格该行数据

表格数据显示在弹窗内时要注意:

javascript 复制代码
<script lang="ts" setup>
  // =======================用reactive定义
let form = reactive({
  factoryCode: "",
  sku: "",
});
const updateRow = (row) => {
  form= row;
  form = JSON.parse(JSON.stringify(row));
  // 逐个赋值【数据过多用for...in...】,上面两种都不对
  form.factoryCode = row.factoryCode;
  form.sku = row.sku;
  form.factoryCode ="改变它";//弹窗里会变,表格不会
  dialogFormVisible.value = true;
};
  // =======================用ref定义
let form = ref({
  factoryCode: "",
  sku: "",
});
const updateRow = (row) => {
  form.value= row;
  dialogFormVisible.value = true;
};
</script>

通过 form.factoryCode 修改数据时,它并没有直接修改 tableData中的对应数据项,而只是更新了 form 中的数据。如果你希望 tableData中的某个项随着 form 的改变而自动反映更新,需要做显式的修改【后端接口更新/自己改变tableData】。

但是在vue2里,却是可以直接改变的。

javascript 复制代码
  methods: {
    handleSelectionChange(val) {
      this.multipleSelection = val
      this.multipleSelection[0].name = '改变后的名称002' //这里一变,tableData也会变
    },
    updateRow(row) {
      this.form = row
      this.form.name = '改变后的名称' //这里一变,row就会变,tableData也会变
      this.dialogFormVisible = true
    }
  }

如果你不想修改 row 对象本身,而只想在 this.form 上进行修改:

this.form = { ...row } // 使用展开运算符创建 row 的浅拷贝

this.form = Object.assign({}, row) // 使用 Object.assign 创建 row 的浅拷贝
总结:

vue2:this.form = row 这样的赋值操作,让它俩指向的是同一个内存地址,所以一变全都变;

vue3:form.value = row这里的form 是一个响应式引用 ,而row只是一个普通的对象,formrow是不同的引用 ,修改form.value并不会直接影响 row;非要一起变,只能Object.assign(form, tableData[index]);

......待更新

相关推荐
腾讯TNTWeb前端团队26 分钟前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰4 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪4 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪4 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy5 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom5 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom5 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom5 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom6 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom6 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试