vue原理分析(八)研究new Vue()中的initProxy

在Vue.prototype._init 中有一些init函数,今天我们来研究这些init函数

Vue.prototype._init = function (options) {
  ......
  {
    initProxy(vm);
  }
  ......
  initLifecycle(vm);
  initEvents(vm);
  initRender(vm);
  callHook$1(vm, 'beforeCreate', undefined, false /* setContext */);
  initInjections(vm); // resolve injections before data/props
  initState(vm);
  initProvide(vm); // resolve provide after data/props
  callHook$1(vm, 'created');
  ......
}

接下来我们逐步分析,先分析initProxy(vm)

Vue.prototype._init = function (options) {
  ......
  {
    initProxy(vm);
  }
  ......
}

查看initProxy源码

initProxy = function initProxy(vm) {
  if (hasProxy) {
      // determine which proxy handler to use
      const options = vm.$options;
      const handlers = options.render && options.render._withStripped ? getHandler : hasHandler;
      vm._renderProxy = new Proxy(vm, handlers);
  }
  else {
      vm._renderProxy = vm;
  }
};

通过判断hasProxy,来执行不同的处理逻辑

我们看下hasProxy的源码

const hasProxy = typeof Proxy !== 'undefined' && isNative(Proxy);

它的作用就是判断当前环境中Proxy是否可用

// determine which proxy handler to use
const options = vm.$options;
const handlers = options.render && options.render._withStripped ? getHandler : hasHandler;

回到代码中,如果当前环境存在Proxy,则执行块内的语句

三元表达式,如果options上存在render属性,且render属性上存在_withStripped属性,则proxy的traps(traps其实也就是自定义方法)采用getHandler方法,否则采用hasHandler方法

接下来看看getHandler和hasHandler方法

const getHandler = {
    get(target, key) {
        if (typeof key === 'string' && !(key in target)) {
            if (key in target.$data)
                warnReservedPrefix(target, key);
            else
                warnNonPresent(target, key);
        }
        return target[key];
    }
};
const hasHandler = {
    has(target, key) {
        const has = key in target;
        const isAllowed = allowedGlobals(key) ||
            (typeof key === 'string' &&
                key.charAt(0) === '_' &&
                !(key in target.$data));
        if (!has && !isAllowed) {
            if (key in target.$data)
                warnReservedPrefix(target, key);
            else
                warnNonPresent(target, key);
        }
        return has || !isAllowed;
    }
};

getHandler方法主要是针对读取代理对象的某个属性时进行的操作。当访问的属性不是string类型或者属性值在被代理的对象上不存在,则抛出错误提示,否则就返回该属性值

hasHandler方法的应用场景在于查看vm实例是否拥有某个属性—比如调用for in循环遍历vm实例属性时,会触发hasHandler方法。

回到initProxy代码中

if (hasProxy) {
    ...
    vm._renderProxy = new Proxy(vm, handlers)
  } else {
    vm._renderProxy = vm
  }
}

如果Proxy属性存在,则把包装后的vm属性赋值给_renderProxy属性值,否则把vm是实例本身赋值给_renderProxy属性。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值