Введение в Vue.set() и this.$set()

Vue.js

В процессе использования vue для разработки мы можем столкнуться с ситуацией: при генерации экземпляра vue, при повторном назначении данных, иногда не будет автоматически обновляться до вида, когда мы посмотрим на документ vue, вы найдите это предложение: если вы добавите новое свойство в экземпляр после создания экземпляра, это не вызовет обновление представления. Следующий код добавляет возрастной атрибут к объекту ученика.

data () {
  return {
    student: {
      name: '',
      sex: ''
    }
  }
}
mounted () { // ——钩子函数,实例挂载之后
  this.student.age = 24
}

Ограниченный ES5, Vue.js не может обнаруживать добавление или удаление свойств объекта. Поскольку Vue.js превращает свойства в геттеры/сеттеры при инициализации экземпляра, свойство должно находиться в объекте данных, чтобы Vue.js мог его преобразовать, чтобы он был отзывчивым.

Правильное написание: this.$set(this.data,"key",value')

mounted () {
  this.$set(this.student,"age", 24)
}

:: Vue не позволяет динамически добавлять реактивные свойства корневого уровня.

Например:

const app = new Vue({
  data: {
    a: 1
  }
  // render: h => h(Suduko)
}).$mount('#app1')

Vue.set(app.data, 'b', 2)

Вы можете добавлять реактивные свойства только к вложенным объектам, используя метод Vue.set(object, propertyName, value), например.

var vm=new Vue({
    el:'#test',
    data:{
        //data中已经存在info根属性
        info:{
            name:'小明';
        }
    }
});
//给info添加一个性别属性
Vue.set(vm.info,'sex','男');

Принцип реализации Vue.set() и this.$set()

Давайте сначала посмотрим на исходный код Vue.set():

import { set } from '../observer/index'

...
Vue.set = set
...

Давайте посмотрим на исходный код this.$set():

import { set } from '../observer/index'

...
Vue.prototype.$set = set
...
结果我们发现Vue.set()和this.$set()这两个api的实现原理基本一模一样,都是使用了set函数。set函数是从 ../observer/index 文件中导出的,区别在于Vue.set()是将set函数绑定在Vue构造函数上,this.$set()是将set函数绑定在Vue原型上。
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
}

Мы обнаружили, что функция set получает три параметра: target, key и val, где значением target является массив или объект, что соответствует параметрам, переданным при вызове метода Vue.set() с официального сайта. .

Ссылаться на:

Яма, обнаруженная в vue --- проблема обнаружения изменений (связанная с массивом)