使用 Vue3 ref时踩到的小坑

2,621 阅读1分钟

记自己学习Vue3做项目时碰到的一个小坑

直接上简化后的代码

import Child from './components/Child.vue'
import { ref } from 'vue'
const config = [{
  filed: 'id',
  lable: 'id'
}, {
  filed: 'name',
  lable: '用户名'
},
]//配置
const defaultInfo = {}
config.forEach(item => {
  defaultInfo[item.filed] = ''
})//获取自己需要的字段
const formData = ref(defaultInfo)
const handleData = (data) => {
  Object.keys(data).forEach(key => {
    if (key in defaultInfo) {
      defaultInfo[key] = data[key]
    }
  })
  formData.value = defaultInfo //更新值
  //console.log(formData.value)
}

<template>
  <div style="background-color: aqua;">
    <h1>获得的数据:</h1>
    <h1 v-for="item in formData">{{ item }}</h1>
  </div>
  <Child @handle-post-data="handleData"></Child>
</template>

问题描述

子组件被点击后会给父组件传数据data(table中的一行数据),但是我们并不需要所有的数据,于是根据配置中数据初始化一个普通对象,包含着我们需要数据的key,然后监听数据时先判断key是否需要后再设置,但是点击的时候发现视图却没有更新,输出值发现formData的值也变了,但视图却没更新。

分析和解决

最后发现是因为 formData.value = defaultInfo 这一行赋值操作出了问题,按照官方文档来说ref返回一个响应式对象,改变value值会触发响应,但是我们这样赋值实际没有改变value的值,因为defaultInfo是对象,属于引用类型,我们改变它的key,value时并没有修改它的值,所以不会触发vue的响应式系统,明白是这个原因后我们只要修改为 formData.value = {...defaultInfo} 即可触发视图更新。