vue3 中关于对象和数组整个赋值但页面不生效

7,377 阅读2分钟

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);
}

image.png

image.png

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: ''
}

参考链接:
blog.csdn.net/qq_26705343… www.jb51.net/article/249…