这篇文章主要介绍“Vue.$set失效如何解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Vue.$set失效如何解决”文章能帮助大家解决问题。
Vue.$set失效
有这样一个需求 添加数据过滤用 左边是控件选择 中间是条件 右边是值
因为会根据控件不同渲染不同的值选项控件
<el-form inline > <el-form-item style="margin-bottom: 20px;"> <el-select v-model="data[props.prop]" @change="data[props.value] = """> <el-option v-for="item in controls" :key="item.id" :value="item.id" :label="item.label"> </el-option> </el-select> </el-form-item> <el-form-item style="margin-bottom: 20px;"> <el-select v-model="data[props.type]"> <el-option v-for="item in condition" :key="item.code" :value="item.code" :label="item.name" ></el-option> </el-select> </el-form-item> <el-form-item style="margin-bottom: 20px;"> <FormControl v-if="control" :control="control" :value="data[props.value]" @input="onValueChange" ></FormControl> <el-input v-else :value="data[props.value]" @input="onValueChange"></el-input> </el-form-item> <el-form-item> <el-button type="primary" icon="el-icon-plus" @click="add"></el-button> </el-form-item> </el-form>
{
  props:{
    props: {
      type: Object,
      default: () => ({
        prop: "prop",
        value: "value",
        type: "type"
      })
    }
  },
  data(){
    return {
      data:{
        
      }
    }
  },
  methods:{
    onValueChange(val){
      this.$set(this.data, this.props.value, val)
    }
  }
  //...
}代码片段
由于控件ID的不确定性 所有 data并不能提前预设好key 自然无法响应 所以在onValueChange 使用了this.$set动态添加数据实现响应
复现可以发现 值输入框内的数据并不能实时响应
明明用了$set却不能响应 一番排查后发现只要切换控件后 value值就不能响应 但是只要在切换前随便输入点啥 再切换就没问题
又是一番排查后发现
<el-select v-model="data[props.prop]" @change="data[props.value] = """>
删除@change事件后故障解决
问题出现在 data[props.value] = ""
遂查看Vue源码
//vue/src/core/observer/index.js 源码片段 
 
/**
 * Set a property on an object. Adds the new property and
 * triggers change notification if the property doesn"t
 * already exist.
 */
export function set (target: Array<any> | Object, key: any, val: any): any {
  if (process.env.NODE_ENV !== "production" &&
    (isUndef(target) || isPrimitive(target))
  ) {
    warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`)
  }
  if (Array.isArray(target) && isValidArrayIndex(key)) {
    target.length = Math.max(target.length, key)
    target.splice(key, 1, val)
    return val
  }
  if (key in target && !(key in Object.prototype)) {
    target[key] = val
    return val
  }
  const ob = (target: any).__ob__
  if (target._isVue || (ob && ob.vmCount)) {
    process.env.NODE_ENV !== "production" && warn(
      "Avoid adding reactive properties to a Vue instance or its root $data " +
      "at runtime - declare it upfront in the data option."
    )
    return val
  }
  if (!ob) {
    target[key] = val
    return val
  }
  defineReactive(ob.value, key, val)
  ob.dep.notify()
  return val
}可以发现 在defineReactive之前 判断了key是否存在于对象之内 若存在就跳过了
坑就在这 多次翻阅Vue.$set文档并未发现$set不能为已存在的key添加监测对象
删除 data[props.value] = "" 改为 onValueChange("") 完美解决问题