Vue diff algorithm and virtual dom knowledge collation (5) Handwrite your own h function

The significance of this article is to teach you how to write an h function by hand

In the above, we briefly understood the h function. Its function is to build a virtual dom node.
It is necessary to master this function. First, if you want to write it, you have to read the original ts code.

Here we don't need to pay too much attention to TS, so here we look at the ts code and then copy the js code

We found snabbdom/src/h.ts under the node_modules of the case. Open this file. After
insert image description here
reading the h function, you will find that it returns a vnode function at the end.
insert image description here
Good guy is in this doll.
Let’s open vnode.ts in the same directory

This vnode function looks relatively simple. Simply put, it takes a
insert image description here
series of parameters and limits the types of these parameters.
In ts, sel: string |
It is a string string type or it can also be undefined undefined

After processing these parameters, convert them into a json and return them,
so the h function finally returns vnode, which is to return a virtual node object processed by the vnode function

The more troublesome thing in the object is the children, because it may be nested. There may be another virtual node nested in a virtual node. There may be n layers of nested virtual nodes under the nested virtual node.

So we look at the position above the h function, which
will process the children in a loop, and create vonde nodes layer by layer.
insert image description here
Here, the h function does not involve recursion, but uses a loop to adjust down layer by layer.

Here we see that there are many if h functions above. This position involves the overloading
insert image description here
of the h function. Many back-end languages ​​have ts and bring this concept into the front-end development by
defining many functions with the same name to receive. Different types of parameters call different logic functions.
If you don’t understand it, you can read my article
TypeScript method overloading.
We have demonstrated it above and
know that there are many tuning methods for the h function.
insert image description here

Ok, so let's try to write our own h function

We see that what we have been writing is supposed to create a folder called snabbdom under src in the root directory

Then create a h.js under the snabbdom we just created
, and we just saw that the h function returns a vnode function to process the format,
so create another vnode.js under the snabbdom.
The reference code is as follows

export default function(sel,data,children,text,elm) {
    
    
    let key = data.key?data.key:undefined;
    return {
    
    
        sel,
        data,
        key,
        children,
        text,
        elm
    }
}

The logic is very simple
. It is to export a function. This function receives five parameters
and then defines a local variable called key. Its assignment uses a ternary operator
to determine if there is a key field in the data, then use the key in the data to assign the value to the key.
If not, the key is equal to key:undefined
and an object is returned, that is, the field name is equal to the value corresponding to the field. Friends who have learned ES6 will understand

{
    
    
    key
}

and

{
    
    
    key: key
}

is a meaning

Then let's write the code in the h.js we just created

Then first of all, we need to explain that our h function does not handle method overloading, because overloading is a troublesome concept that anyone can write, and I think it is not a very beautiful thing in the h function, so the function we write like this
is Three parameters must be passed

Then we write the code in h.js as follows

//引入我们刚刚写的vnode
import vnode from "./vnode";
//默认导出一个函数
export default function(a,b,c) {
    
    
    //确认调用时是否传了三个参数
    if(arguments.length != 3)
      //如果参数不是三个  抛出异常警告
      throw new Errow("对不起,本h函数必须传三个参数 我们是低配版");

    //  判断 如果传入的第三个参数 是  string或者number  表示 形态为 第一种  h(标签。属性,文本)
    if(typeof c == "string"||typeof c == 'number') {
    
    
        return vnode(a,b,undefined,c,undefined);
    //如果传的是一个数组  那么 是调的第二种形式  h(标签。属性,数组)
    }else if(Array.isArray(c)) {
    
    
        //定义一个children数组  来存一下当前这个节点的子集
        let children = [];
        //循环c这个数组
        for(let i = 0;i < c.length;i++) {
    
    
            //判断当前下标是不是一个对象  因为h函数一定会返回一个对象
            if(c[i] instanceof Object) {
    
    
                children.push(c[i]);
            }else{
    
    
                //如果不是 抛出异常提示
                throw new Errow(`第三个参数的第${
      
      (i+1)}项不是一个h函数`);
            }
        }
        //循环结束  表示children收集子集也结束了
        return vnode(a,b,children,undefined,undefined);
    //判断c是否是一个对象  如果是  表示调用了第三种  h(标签。属性,h对象)
    }else if(c instanceof Object) {
    
    
        //第三种 说明  他是唯一的子集  我们直接将他的子集放入children就好了
        return vnode(a,b,[c],undefined,undefined);
    //如果以上格式 全部都不符合  排除错误
    }else{
    
    
        throw new Errow("对不起,传入的第三个参数格式错误 请认真加粗");
    }
}

Because this thing is not easy to describe, so I will work harder to write comments, hoping that everyone can understand through comments that
this is not called recursion, but the thinking of nesting h functions is really ingenious. There is no complicated code, but design thinking is. People feel very interesting and very clever

Then let's test three situations.
We rewrite the index.js code under src as follows

import h from "./snabbdom/h";

const dom1 = h("div",{
    
    
  props: {
    
    class: "dom"}
},"文本测试");

const dom2 = h("div",{
    
    
  props: {
    
    class: "dom"}
},[
  h("div",{
    
    },"java"),
  h("div",{
    
    },"html"),
  h("div",{
    
    },[
    h("div",{
    
    },"react"),
    h("div",{
    
    },"css")
  ])
]);

const dom3 = h("div",{
    
    
  props: {
    
    class: "dom"}
},h("div",{
    
    },"java"));

console.log(dom1);
console.log(dom2);
console.log(dom3);

Here we pass the third text array of various situations directly to an h function
, and then we run the project.
insert image description here
We open all three and have a look.

The first type
insert image description here
The second type
insert image description here
The third type
insert image description here

Guess you like

Origin blog.csdn.net/weixin_45966674/article/details/130545233