Vue3源码系列——provide、inject

如果帮助到大佬,请给小弟一个赞哈!

provides的来源

每个组件在形成实例时:如果有父组件,则使用父组件的provides,没有则为{}

 const instance = {
    type: vnode.type,
    vnode,
    next: null,
    props: {},
    parent,
    provides: parent ? parent.provides : {},
    proxy: null,
    isMounted: false,
    attrs: {},
    slots: {},
    ctx: {},
    setupState: {},
    emit: () => { },
};
复制代码

provides源码

void 0同等于undefined,想知道为什么使用void 0,自行百度。通过上面代码已知实例如果有父组件,实例的provides等于parent.provides。

  1. 当parentProvides === provides,把当parentProvides放在provides的原型链中。如果某组件中访问key,会优先访问的父组件设置的key,找不到的话则继续向外找。
  2. provides[key] = value; 设置自己的provide。
function provide(key, value) {
    var _a;
    const currentInstance = getCurrentInstance();
    if (currentInstance) {
        let { provides } = currentInstance;
        const parentProvides = (_a = currentInstance.parent) === null || _a === void 0 ? void 0 : _a.provides;
        if (parentProvides === provides) {
            provides = currentInstance.provides = Object.create(parentProvides);
        }
        provides[key] = value;
    }
}
复制代码

上面的分析是否正确?我们验证一下,多层嵌套组件都设置了provide,然后打印最深的子组件的实例。

WechatIMG40.jpeg

provides确实是觉有多层原型链,大家可以去验证一下。

inject源码

  1. 现在原型链上找key,使用in遍历,会遍历到原形链。找到则return provides[key]。
  2. 没有找到,但传人了defaultValue,defaultValue是函数则return执行结果,不是函数直接return defaultValue。
  3. 原型链没找到,也没有设置默认值,则会不会return,也就会默认return undefined。
function inject(key, defaultValue) {
    var _a;
    const currentInstance = getCurrentInstance();
    if (currentInstance) {
        const provides = (_a = currentInstance.parent) === null || _a === void 0 ? void 0 : _a.provides;
        if (key in provides) {
            return provides[key];
        } else if (defaultValue) {
            if (typeof defaultValue === "function") {
                return defaultValue();
            }
            return defaultValue;
        }
    }
}
复制代码

总结

这部分源码是非常简单的,大家尽量去阅读一下。

猜你喜欢

转载自juejin.im/post/7041213129744711711