The render function uses this to get the property returned by setup and get $el

export const App = {
  render() {
    return h(
      "div",
      {
        id: "root",
        class: ["red", "blue"],
      },
      "hi, " + this.msg
    )
  },
  
  setup() {
    return {
      msg: 'mini-vue'
    }
  }
}
Copy the code

SetupState access

In the previous implementation of the Component initialization main process, we assigned the return value of setup to the Component instance property setupState. So we just need to

  1. Passes when initializing a stateful componentproxythegetOperation to broker.
  2. When calling the component instance objectrenderFunction will bethisPoint to theproxy.
// component.ts function setupStatefulComponent(instance) {const component = instance.type // Use Proxy for component instance object Instance. proxy = new proxy ({}, {get(target, key) { const { setupState } = instance if (key in setupState) { return setupState[key] } } } ) ... }Copy the code
Renderer. ts function setupRenderEffect(instance, container) {const {proxy} = instance, Const subTree = instance.render. Call (proxy) patch(subTree, container); }Copy the code

$el retrieve

First add an EL attribute when creating a VNode to hold the root element of the component

// vnode.ts export function createVNode(type, props? , children?) { const vnode = { type, props, children, el: null }; return vnode; }Copy the code

Assignment at Element initialization assigns the DOM Element created from vnode.type to vnode.el

// renderder.ts function mountElement(vnode, container) { const el = (vnode.el = document.createElement(vnode.type)); . }Copy the code

After obtaining the VNode tree and recursively patch, the EL of the VNode tree is assigned to VNode

// renderder.ts
function setupRenderEffect(instance, vnode, container) {
  const { proxy } = instance;
  const subTree = instance.render.call(proxy);
  patch(subTree, container);
  vnode.el = subTree.el;
}
Copy the code

Where instance.proxy is handled, determine $el

// component.ts function setupStatefulComponent(instance) {const component = instance.type // Use Proxy for component instance object Instance. proxy = new proxy ({}, {get(target, key) { const { setupState } = instance if (key in setupState) { return setupState[key] } if (key === '$el') { return instance.vnode.el } } } ) ... }Copy the code

Code refactoring

/ / componentPublicInstance. Ts / / save the instance on the property of the corresponding getter const publicPropertiesMap = {$el: i => i.vnode.el } export const PublicInstanceHandlers = { get({_:instance}, key) { const { setupState } = instance; if (key in setupState) { return setupState[key]; } const publicGetter = publicPropertiesMap[key]; if (publicGtter) { return publicGetter() } } }Copy the code
// component.ts function setupStatefulComponent(instance) { const component = instance.type; instance.proxy = new Proxy({ _: instance }, PublicInstanceProxyhandlers); . }Copy the code