目录
一、定义常变量
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
只是一个普通的对象,form
和row
是不同的引用 ,修改form.value
并不会直接影响row;
非要一起变,只能Object.assign(form, tableData[index]);
......待更新