“This is my 36th day of participating in the First Challenge 2022. For details: First Challenge 2022.”

Previously on & Background

A small essay introduces the Vue ahead at compile time for < slot > this placeholder tag a processing, compile slot label finally got a called _t rendering function runtime help function invocation: _t (slotName, children, attrs, bind);

SlotName is the name attribute value on the slot tag of a named slot. For an anonymous slot, slotName is default.

Children are children of the slot tag; Although the slot is not shown when it is eventually used, the slot’s child elements are still rendered for placeholder cues when the component is referenced without passing the slot’s contents.

We have described rendering functions in the following cases:

  1. Static root node rendering function, promoted tostaticRenderFnsThe array;
  2. withv-model ηš„ inputRender functions that deal with different elements,inputDynamic bindingtypeIs the type of the different event handling types and binding values;
  3. withv-if/v-else-if/v-elseCondition rendering, according toel.ifConditonsDeal with the ternary expression of the set of children;
  4. withv-forList rendering, according toel.for ε’Œ el.aliasProcessing into_l(el.for, function (it1,it2) {return _c(...) })The call;
  5. Handle tag rendering ifel.tagTo obtain theslotNameProcessing into_t(slotName,children...)



Second, the processing of custom components

In our test.html we have a
custom component. Let’s use it as an example to look at the rendering function of the custom component.

2.1 example test. HTML

<div id="app">
 <some-com :some-key="forProp">
    <div>SomeCom slot contents</div>
 </some-com>
</div>
Copy the code

2.2 genElement handles custom components

There is not much difference between handling custom components and native HTML elements in the render function of the root instance. It is handled in the else of the genElement, including dynamic components.

export function genElement (el: ASTElement, state: CodegenState) :string {
  if (el.parent) {
  } else {
    // This else handles: dynamic components, normal elements, custom components

    let code
    if (el.component) {
      
       
      code = genComponent(el.component, el, state)
    } else {
      let data
      if(! el.plain || (el.pre && state.maybeComponent(el))) {// Non-ordinary elements or components with v-pre instructions go here, process all the attributes of the node, return a JSON string,
        Key: xx, ref: xx,.... } '
        data = genData(el, state)
      }

      // Get an array of code for all the child nodes in the string format:
      // `['_c(tag, data, children)', ....] , normalizationType`
      const children = el.inlineTemplate ? null : genChildren(el, state, true)

      code = `_c('${el.tag}'${
        data ? `,${data}` : ' ' // data
      }${
        children ? `,${children}` : ' ' // children
      }) `
    }

    for (let i = 0; i < state.transforms.length; i++) {
      code = state.transforms[i](el, code)
    }
    return code
  }
}
Copy the code

You can see that in the picturegenElementInto theelseAnd elThe tag nameel.tagissome-comAs can be seen from the example,some-compComponent references pass in slot content for distribution:

SomeComp slot content

, so

The slot content is also rendered as a normal child node, with the above slot rendering function as follows:

"[_c('div',[_v(\"someCom socket contents \")])]"
Copy the code

Combining the above results, we get the code for the some-com component’s rendering function:

"_c (- com ', '{attrs: {\" some - key \ ": forProp}}, [_c (' div', [_v (\" someCom slot content \ ")])])"
Copy the code

GenElement handles dynamic components

You will always encounter dynamic component scenarios in your daily development. This is actually a good thing, and it gives developers a lot of imagination and play. The server can even return a string that corresponds to a specific view.

But it also makes it seem mysterious, so let’s find out today;

3.1 Examples of test.html

<div id="app">
 <component is="someCom">
  <div>The componet of the slot</div>
 </component>
</div>
Copy the code

3.2 genElement δΈ­ηš„ genComponent

The logic that genElement handles dynamic components is also handled in else, and the logic that el.componenthas a value is the part that handles dynamic components

export function genElement () :string {
  if (el.parent) {
  } else {
    let code
    if (el.component) {
      
       
      // el.component.ponet is the value of the DYNAMIC component binding's IS property, which is the component name
      code = genComponent(el.component, el, state)
    } else {
   
    return code
  }
}
Copy the code

3.3 genCompoent

Methods location: SRC/compiler/codegen/index. Js – > genComponent

Method parameters:

  1. componentName: Component name, that isisThe value of the property binding;
  2. el: astNode object;
  3. state: CodegenStateInstance;

The < Component >
method generates a render function for the < Component > dynamic component.

  1. To deal withcomponentGets the child element ofRender functionAn array of code;
  2. Concatenates the current dynamic component tocomponentNameThe rendering function code for the component looks like this:_c(compName, data, children)
function genComponent (componentName: string, el: ASTElement, state: CodegenState) :string {
  const children = el.inlineTemplate ? null : genChildren(el, state, true)
  return `_c(${componentName}.${genData(el, state)}${
    children ? `,${children}` : ' '
  }) `
}
Copy the code

Four,

This essay discusses the corresponding rendering functions of two other commonly used functions: custom components and dynamic components.

Both are processed into _C (componentName, data, children) call form;

Somewhat disappointingly, we realize that this is no different from rendering a normal div. What about custom components? What about the life cycle?

Don’t worry, as I mentioned earlier we are now dealing with the rendering function of the root instance. This custom component is a subinstance and it is not initialized at this time. So when does this subinstance get initialized? At this point in the compilation phase of the root instance, only when the compilation phase of the root instance is finished, the rendering function of the root instance is available, and then the rendering function of the root instance is created by Watcher.

_c/ _L /_t/ _S /_v… When executed, these helper functions, if encountered with a custom component, will proceed to create a new Vue instance. Creating a new Vue instance will redo the _init logic of the Vue including processing the data responsivity, compiling the template to generate the AST to get the subinstance render function. Wathcer executes the render function of the subinstance to get the DOM and then completes the mount.