首页 > 其他分享 >vue 模拟set del 方法

vue 模拟set del 方法

时间:2023-03-01 18:33:47浏览次数:39  
标签:set 数组 val vue del key let data

上篇主要对数组格式数据进行响应式处理,vue 有set 和del 方法可以对数组和对象进行修改和删除。代码如下:

数组类型的数据修改和删除时候,只需要调用splice方法就可以,在上一篇数组响应是在get方法中属性为数组格式时进行依赖的注入,现在在每个属性都注入,这样调用set方法时候,才能在_ob_属性中去触发依赖函数的更新。

import Dep from "./dep";
import { hasProto, def,hasOwn } from "./utils/index";
import { arrayMethods } from "./array";
const arrayKeys = Object.getOwnPropertyNames(arrayMethods);
const NO_INIITIAL_VALUE = {};
function defineReactive(obj, key, val, shallow) {
	console.log(obj,key,val,'kkkkkddd')
  // 获取当前属性有没有自定义方法;
  let property = Object.getOwnPropertyDescriptor(obj, key);
  // 判断当前属性有没有自定义get set 方法
  let getter = property && property.get;
  let setter = property && property.set;
  // 没有val值,去obj里面的
  if (
    (!getter || setter) &&
    (val === NO_INIITIAL_VALUE || arguments.length == 2)
  ) {
    val = obj[key];
  }

  const dep = new Dep(); // 持有一个 Dep 对象,用来保存所有依赖于该变量的 Watcher

  // 如果有深度对象,则深度监听
  let childOb = !shallow && observe(val, false);

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function () {
      //添加依赖函数
      if (Dep.target) {
        // dep.addSub(Dep.target);
        dep.depend();

       
        if (childOb) {
          if (Array.isArray(val)) {
            // 如果当前值是数组,给数组生成的observer.dev添加依赖函数
            childOb.dep.depend();
			//循环数组,对嵌套数组进行依赖收集
			dependArray(val)
          }
		   /******新增 *************************/
	 //给每个属性都添加一个依赖函数,这样对象通过set新增一个属性后就可以去触发更新
		  childOb.dep.depend();
        }
        /************************************/
      }
	  
      //如果有自定义方法则调用
      let value = getter ? getter.call(obj) : val;
      return value;
    },
    set: function (newVal) {
		
      if (setter) {
        setter.call(obj, newVal);
      } else {
        val = newVal;
      }
      // 如果对一个对象整体赋值后,再修改对象属性也没有响应效果,在set也监听下

      childOb = !shallow && observe(newVal, false);
      //执行依赖当前属性的依赖函数
      dep.notify();
    },
  });
}

export class Observer {
  // shallow 属性判断是否需要深度监听
  constructor(data, shallow = false) {
    this.dep = new Dep(); // 新增dep
    def(data, "__ob__", this); // 每个数据都新增_ob_属性绑定当前Observer实例
    if (Array.isArray(data)) {
      // 判断当前值是否是数组类型,是否有__proto__属性,将重写的方法指向原型
      if (hasProto) {
        data.__proto__ = arrayMethods;
      } else {
        for (let i = 0, l = arrayKeys.length; i < l; i++) {
          const key = arrayKeys[i];
          def(data, key, arrayMethods[key]);
        }
      }
	  //添加对数组里面每一个值进行响应式监听
	    this.observeArray(data)
    } else {
      this.walk(data, shallow);
    }
  }
  walk(data, shallow) {
    let keys = Object.keys(data);

    for (let key of keys) {
      defineReactive(data, key, NO_INIITIAL_VALUE, shallow);
    }
  }
  // 循环数组,对数组里面值进行监听
  observeArray(data){
  	for(let i=0;i<data.length;i++){
  		observe(data[i])
  	}
  }
}
export function observe(data, shallow = false) {
  if (data !== null && typeof data === "object") {
    return new Observer(...arguments);
  } else {
    return false;
  }
}

//多层数组嵌套响应
function dependArray(value) {
    for (let e, i = 0, l = value.length; i < l; i++) {
        e = value[i];
        if (Array.isArray(e)) {
           	e && e.__ob__ && e.__ob__.dep.depend();
            dependArray(e); // 递归进行
        }
    }
} 


// set 方法
export function set(target,key,val){
	
	// 如果是数组类型
	if(Array.isArray(target)){
		target.length = Math.max(target.length,key)
		target.splice(key,1,val)
	  return val
	}
	//如果是对象类型 修改target自身的属性
	 if(target[key] && !(key in Object.prototype)){
		  Object.prototype = val;
		  return val
	 }
	
	let ob = target.__ob__;
	// 前面数据响应式每个属性都添加了_ob_属性,如果没有说明target不是响应式的数据
	if(!ob){
		target[key] = val;
		return val
	}
	
	// 如果是响应式数据,则将新增的值变为响应式
	defineReactive(target, key, val,false);
	// 让依赖的方法更新
	ob.dep.notify()
}

//delete 方法
export function del(target,key){
	// 如果是数组类型
	if(Array.isArray(target)){
		target.length = Math.max(target.length,key)
		target.splice(key,1)
	    return 
	}
	//如果target是对象类型
	 const ob = target.__ob__;
	    if (!hasOwn(target, key)) {
	        return;
	    }
	    delete target[key];
	    if (!ob) {
	        return;
	    }
	    ob.dep.notify();
}

  

import { observe,set,del } from "./reactive";
import { Watcher } from "./watcher";

const data = {
  test2: {
    dd: "aa",
  },
  arr: ["a",{test:'oo'},['a']],
};
const recursion = () => {
  console.log(data.test2.hh);
};
const updateArr = () => {
  data.arr.map((item) => console.log(item));
};

observe(data);


// 深度响应
 new Watcher(recursion);

// 数组方法响应
new Watcher(updateArr);

//数组set 方法
//set(data.arr,4,'add')
// 对象set 方法
//set(data.test2,'hh','ppp')
//数组删除
//del(data.arr,0)
//对象删除方法
del(data.test2,'dd')

  

标签:set,数组,val,vue,del,key,let,data
From: https://www.cnblogs.com/hardmeng/p/17169305.html

相关文章

  • VUE2 条件渲染
    条件渲染v-show特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉了。<divv-show="flag"></div><script>data(){return{flag:true......
  • error in ./src/components/NumberInfo/NumberInfo.vue?vue&type=style&index=0&id=
      删除NumberInfo中的scoped,因为使用了antdv的css变量,加了scoped导致获取不到......
  • vue刷新当前页面(App.vue)
    vue刷新当前页面有挺多种方法,比如window.location.reload()或者this.$router.go(0)但是这两种方法是会出现一瞬间的白屏,体验不好,所以这里给大家推荐第三种比较好用的......
  • HashSet 与 List 性能
    很明显,通用HashSet<T>类的搜索性能高于通用类List<T>。只需将基于散列的密钥与类中的线性方法进行比较即可List<T>。然而,计算哈希键本身可能需要一些CPU周期,因此对......
  • vue实现全部防抖
    //全局注册防抖Vue.component("ElButton").mixin({ data(){  return{   debounce:false  } }, methods:{  //覆盖el-button的点击......
  • vue3的ref、reactive、toRefs特性详解
    了解ref()、reactive()这两个特性之前,我们先回顾一下vue2中data和method方法。在vue2中我们定义一个响应式变量name,通过点击事件handle来改变name的值是通过如下方式写的。......
  • Vue3 reactive的理解
    1.什么是reactive?reactive是Vue3中提供实现响应式数据的方法.在Vue2中响应式数据是通过defineProperty来实现的.而在Vue3响应式数据是通过ES6的Proxy来实现的2.rea......
  • 踩坑小计-Flutter中引用其他module的asset资源
    最近开发了一个module,其中使用了asset设置了一个图片资源,在调试module时一切正常,当把module作为一个模块依赖到其他项目时,就出现了如下错误:查了一下解决方案,在使用asset时......
  • C. Maximum Set[数学] [*1300-*1500]
    C.MaximumSet[数学][*1300-*1500]题目链接点我题意:一个集合是漂亮的,如果他的每一个元素都是集合中其他元素的倍数或者因子给定你一个\(l\)和\(r\)让你找出在\(......
  • 前端框架vue中的v-on和v-bind的区别
    1.v-on指令监听DOM事件,并在触发时运行一些JavaScript代码"v-on:"的语法糖为"@",语法糖就是简写的意思。例如:<!--事件处理函数--><divid="app"> <!--语法:v-on:事......