1. 问题场景
使用vue3进行开发时,对 reactive 定义的数组进行整个赋值操作,控制台打印数据,发现数组已正常重置,但页面并未生效。
let tableData = reactive([
{
ssh_ip: "",
ssh_port: "",
ssh_user: "",
ssh_password: "",
ssh_node_type: ""
}
]);
const resetTable = () => {
tableData = [{
ssh_ip: "",
ssh_port: "",
ssh_user: "",
ssh_password: "",
ssh_node_type: "",
}]
console.log(11, tableData);
}
2. 解决办法
const resetTable = () => {
tableData.length = 0;
tableData.push({
ssh_ip: "",
ssh_port: "",
ssh_user: "",
ssh_password: "",
ssh_node_type: ""
});
};
清除 reactive 定义的数组时必须将 length 设为0,直接赋值一个空数组是不生效的。对象也不能直接赋空对象,需要遍历删除。这里不生效指的是不能响应式的更新页面。即打印的数据结果正常,但页面没有发生变化。
3. reactive 赋值问题
场景原因分析:
const arr = reactive([]);
const reset = () => {
const newArr = [2, 3, 4, 5];
arr = newArr; // 方法1 失败,直接赋值丢失了响应性
arr.concat(newArr); // 方法2 这样也是失败
newArr.forEach(e => {
arr.push(e); // 方法3 可以,但是很麻烦
});
};
因为 arr = newArr 让 arr 失去了响应式。vue3 使用proxy,对于对象和数组都不能直接整个赋。具体原因:reactive声明的响应式对象被 arr 代理,操作代理对象需要有代理对象的前缀,直接覆盖会丢失响应式。
只有 push 或者根据索引遍历赋值才可以保留 reactive 数组的响应性?如何方便的将整个数组拼接到响应式数据上?看下解决方案:
// 方案1:创建一个响应式对象,对象的属性是数组
const state = reactive({
arr: []
});
state.arr = [1, 2, 3]
// 方案2: 使用 ref 函数
const state = ref([])
state.value = [1, 2, 3]
方案3: 使用数组的push方法
const arr = reactive([])
arr.push(...[1, 2, 3])
这几种办法都可以触发响应性,推荐第一种
4. 对象赋值
let obj = reactive({
name: 'zhangsan',
age: '18'
})
obj = {
name: 'lisi'
age: ''
}
// 直接赋值检测不到,因为响应式的是它的属性,而不是它自身
// 方法1: 单个赋值
obj['name'] = 'lisi';
obj['age'] = '';
// 方法2:创建响应式对象
let obj = reactive({
data: {
name: 'zhangsan',
age: '18'
}
})
obj.data = {
name: 'lisi'
age: ''
}