4

Under normal circumstances, each vue component uses "\<template\>" to write html, but in fact, DOM can be generated by the render function in the js code. The most common component libraries also need to be used with "h".

render

render is an option of the component, and its return value will be used as the DOM structure of the component.

 <script>
import { defineComponent} from "vue";
export default defineComponent({
  render(){
    return '123456789'
  }
});
</script>

image.png

Try inserting html:

 <script>
import { defineComponent } from "vue";
export default defineComponent({
  render(){
    return '<h2>123456789</h2>'
  }
});
</script>

image (2).png

You can see that the html tag is rendered as a string, and the h2 tag is not generated. How to insert the h2 tag correctly?

VNode

If you want to insert the DOM, you need to use "VNode", VNode is the description of the DOM node of the page by vue, which is an Object type.

image (3).png

h

The "VNode" with such a complex structure must not be spelled by itself. The official "h" function is provided, which can help us generate "VNode"

 <script>
import { defineComponent, h } from "vue";
export default defineComponent({
  render() {
    const props = { style: { color: "red" } };
    return h("h2", props, "123456789");
  },
});
</script>

This time the real "h2" is generated:

image (4).png

The first parameter of the "h" function is " tag name ", the second is " attribute ", which can be understood as all attributes of html in this example, and the third is " content ". "Content" can not only be String, can also be "VNode" or a mix of the two:

 <script>
import { defineComponent, h } from "vue";
export default defineComponent({
  render() {
    const props = { style: { color: "red" } };
    const small = h("small", "副标题");
    return h("h2", props, ["123456789", small]);
  },
});
</script>

If only 2 parameters are actually passed in, then the second 2 parameters will be used as the content, such as "small" here.

image (5).png

render component

"h" can also render "components", which brings flexibility. Suppose we have a "switch" component that supports <switch v-model:checked="checked"/> .

 <script>
import { defineComponent, h } from "vue";
import ASwitch from "../components/ASwitch.vue";
export default defineComponent({
  components: { ASwitch },

  data() {
    return { checked: false };
  },

  render() {
    return h(ASwitch)
  }
});
</script>

Note here that the first parameter also supports passing in component objects .
The effect is as follows:

image (6).png

But you can find that although "switch" is displayed, the button cannot be switched after being clicked.

Use "v-model" in the h function

The above cannot be toggled because "v-model" is not used as in the template.

 <a-switch v-model:checked="checked"></a-switch>

Recall how to implement "v-model" in the " Custom Two-way Data Binding " class mentioned earlier. By comparison, you can find that "props" and "v-on event monitoring" are not defined in "h" above. How to write it?
Let's talk about an important knowledge point first: Event listeners on components can also be passed in through "props":

 <a-switch @update:checked="onChange"></a-switch>
<!-- 等价写法: -->
<a-switch :onUpdate:checked="onChange"></a-switch>

All custom events can be passed in through props with the ":on" prefix . So in "h", the " checked " property and the " onUpdate:checked " event can be passed as the second parameter to implement " v-model " equivalent operation.

 <script>
import { defineComponent, h } from "vue";
import ASwitch from "../components/ASwitch.vue";
export default defineComponent({
  components: { ASwitch },

  data() {
    return { checked: false };
  },

  render() {
    return h(ASwitch, {
      checked: this.checked,
      ["onUpdate:checked"]: (checked) => {
        this.checked = checked;
      },
    });
  },
});
</script>

scenes to be used

In actual development, many third-party components are designed to receive "properties" of "VNode", such as the "customRender" property in the "columns" property of the "Table" component of "ant-design-vue", which can be passed in " VNode" implements style customization:

 {
    title: '状态',
    customRender({ record }: any) {
    if (1 === record.state) {
      return h(Tag, { color: 'success' }, () => `开启`);
    } else {
      return h(Tag, { color: 'error' }, () => `关闭`);
    }
  },
},

The "Tag" component is rendered through "h" in the code, and the effect is as follows:

image (7).png

Summarize

This class talks about 3 concepts, and helps you sort out their relationship: The return value of the "render" function needs to be in "VNode" format, and the "h" function can construct data in "VNode" format.

🍕Learn to interact

Thank you for reading, if you have any questions, you can add me on WeChat, I will pull you into the WeChat group


铁皮饭盒
5k 声望1.2k 粉丝

喜欢写程序: [链接]