首页 > 语言 > JavaScript > 正文

ES6 Proxy实现Vue的变化检测问题

2024-05-06 15:38:07
字体:
来源:转载
供稿:网友

Vue变化检测Object使用DefineProperty、数组使用方法拦截实现。最近,Vue3.0将采用ES6 Proxy的形式重新实现Vue的变化检测,在官方还没给出新方法之前,我们先实现一个基于Proxy的变化检测。

模块划分

参照之前Vue变化检测的代码,将Vue 变化检测的功能分为以下几个部分。

Observer Dep Watcher Utils

首先,我们要确定的问题是,将Dep依赖搜集存在哪里。Vue 2.x里,Object的依赖收集放在defineRactive,Array的依收集存入到Observer中。ES6 Proxy里,考虑到让handler访问dep,我们将依赖放入到Observer中。

Observer

observer.js功能代码如下:

import Dep from './dep';import { isObject } from './utils';export default class Observer {  constructor (value) {    // 递归处理子元素    this.obeserve(value);    // 实现当前元素的代理    this.value = this.proxyTarget(value);  }  proxyTarget (targetBefore, keyBefore) {    const dep = new Dep();    targetBefore.__dep__ = dep;    let self = this;    const filtersAtrr = val => ['__dep__', '__parent__'].indexOf(val) > -1;    return new Proxy(targetBefore, {      get: function(target, key, receiver){        if (filtersAtrr(key)) return Reflect.get(target, key, receiver);        if (!Array.isArray(target)) {          dep.depend(key);        }        // sort/reverse等不改变数组长度的,在get里触发        if (Array.isArray(target)) {          if ((key === 'sort' || key === 'reverse') && target.__parent__) {            target.__parent__.__dep__.notify(keyBefore);          }        }         return Reflect.get(target, key, receiver);      },      set: function(target, key, value, receiver){        if (filtersAtrr(key)) return Reflect.set(target, key, value, receiver);        // 新增元素,需要proxy        const { newValue, isChanged } = self.addProxyTarget(value, target, key, self);        // 设置key为新元素        Reflect.set(target, key, newValue, receiver);        // notify        self.depNotify(target, key, keyBefore, dep, isChanged);        return true;      },    });  }  addProxyTarget(value, target, key, self) {    let newValue = value;    let isChanged = false;    if (isObject(value) && !value.__parent__) {      self.obeserve(newValue);      newValue = self.proxyTarget(newValue, key);      newValue.__parent__ = target;      isChanged = true;    }    return {      newValue,      isChanged,    }  }  depNotify(target, key, keyBefore, dep, isChanged) {    if (isChanged && target.__parent__) {      target.__parent__.__dep__.notify(keyBefore);      return;    }    if (Array.isArray(target)) {      if (key === 'length' && target.__parent__) {        target.__parent__.__dep__.notify(keyBefore);      }    } else {      dep.notify(key);    }  }  obeserve(target) {    // 只处理对象类型,包括数组、对象    if (!isObject(target)) return;    for (let key in target) {      if (isObject(target[key]) && target[key] !== null) {        this.obeserve(target[key]);        target[key] = this.proxyTarget(target[key], key);        // 设置__parent__,方便子元素调用        target[key].__parent__ = target;      }    }  }}            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选