3 / 31 vm.$set()实现原理是什么?

前面的话

前端日问,巩固基础,不打烊!!!

解答

搞懂set原理要先搞懂响应式原理,如果不动响应式原理,可以先看小柒前面的文章。

  • 受现代 JavaScript 的限制 (而且 Object.observe 也已经被废弃),Vue 无法检测到对象属性的添加或删除。
  • 由于 Vue 会在初始化实例时对属性执行 getter/setter 转化,所以属性必须在 data 对象上存在才能让 Vue 将它转换为响应式的。
  • 对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性。
  • 那么 Vue 内部是如何解决对象新增属性不能响应的问题的呢?
export function set(target: Array<any> | Object, key: any, val: any): any { 
 // target 为数组 
 if (Array.isArray(target) && isValidArrayIndex(key)) {   
  // 修改数组的长度, 避免索引>数组长度导致splice()执行有误   
   target.length = Math.max(target.length, key);   
  // 利用数组的splice变异方法触发响应式   
  target.splice(key, 1, val);  
   return val; 
  } 
  // target为对象, key在target或者target.prototype上 且必须不能在 Object.prototype 上,直接赋值 
 	if (key in target && !(key in Object.prototype)) {    
 	target[key] = val;   
  	return val; 
 }  
 // 以上都不成立, 即开始给target创建一个全新的属性 
  // 获取Observer实例 
  const ob = (target: any).__ob__;  
  // target 本身就不是响应式数据, 直接赋值 
   if (!ob) {  
     target[key] = val;  
     return val;
   }  
   // 进行响应式处理
     defineReactive(ob.value, key, val);
     ob.dep.notify(); 
      return val;
  } 
  • 如果目标是数组,使用 vue 实现的变异方法 splice 实现响应式
  • 如果目标是对象,判断属性存在,即为响应式,直接赋值
  • 如果 target 本身就不是响应式,直接赋值
  • 如果属性不是响应式,则调用 defineReactive 方法进行响应式处理

你可能感兴趣的:(#,Vue,vue)