【mini-vue】- 解决this指向问题

58 阅读2分钟

前情回顾

在上一节中,我们可以看到instance.render()执行后的结果中,有些节点的值为undefined

image.png

因为他们引用的是instance身上的setup里的data

image.png

分析病情

那么归根结底就是instance.render()在执行的时候,instance身上没有对应的msg,data等属性,所以this.msg, this.data结果才会是undefined。

可是我们在对instance进行setupStateful的时候,已经把setup函数的执行结果,挂载到instance的setupState属性身上了呀,那么通过拿到instance.setupState属性是否就可以拿到我们想要的值了呢

image.png

答案是当然可以啦,但是怎么做到每次访问instance就可以拿到对应属性的返回值呢,总不可能把一个个属性写死吧?

解决办法

这时候就可以用到proxy代理对象啦,对instance.proxy做一层封装,每次访问的时候,返回setupSate里对应的属性值。

function setupStatefulComponent(instance) {
    // 这里的component为什么等于instance.type??=> createVnode的时候只传递了第一个参数
    const component = instance.type;
    const { setup } = component;
    if (setup) {
        const setupResult = setup();
        // setupResult可能是function 也可能是object
        // 如果是function, 那么将它作为组件的render函数
        // 如果是object,那么将它注入到组件的上下文中
        handleSetupResult(instance, setupResult);
    }
    
    //添加监听
    instance.proxy = new Proxy({}, {
        get(target, key) {
            const { setupState } = instance;
            console.log('get函数里---', setupState);
            if (key in setupState) {
                return setupState[key];
            }
        },
    });
}

添加一层proxy之后的instance image.png

然后在处理subTree的地方,我们执行instance.render的时候,需要修改一下this指向,

// 原来的
function setupRenderEffect(instance, container) {
  const subTree = instance.render()// 调用render函数生成组件的children的VNode
  patch(subTree, container)
}

// 现在的
function setupRenderEffect(instance, container) {
  const { proxy } = instance
  const subTree = instance.render.call(proxy)// 调用render函数生成组件的children的VNode
  patch(subTree, container)
}

解决this之前

image.png

解决this之后

image.png

可以看到subTree里的children的文本节点有值啦!