乐趣区

关于前端:vue3中h函数的常见用法

个别状况下每个 vue 组件都用 ”\<template\>” 写 html, 但理论还能够在 js 代码中通过 render 函数生成 dom. 最次要常见组件库也须要配合 ”h” 应用.

render

render 是组件的一个选项, 他的返回值会被作为组件的 DOM 构造.

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

试试插入 html:

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

能够看到 html 标签被当做字符串渲染了, 并没有生成 h2 标签. 如何正确插入 h2 标签呢?

VNode

如果想插入 DOM 就要用到 ”VNode”, VNode 是 vue 对页面 DOM 节点的形容, 其是一个 Object 类型.

h

构造这么简单的 ”VNode” 必定不是本人拼写的, 官网提供了 ”h” 函数, 能够帮忙咱们生成 ”VNode”

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

这次生成了真正 ”h2″:

“h” 函数的第 1 个参数是 ”标签名 “, 第2 个是 ”属性 “, 在这个例子里能够了解为 html 的所有属性, 第3 个是 ”内容“. “ 内容 ” 不仅仅能够是字符串, 还能够是 ”VNode” 或 2 者混合:

<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>

如果理论只传入 2 个参数, 那么第二 2 参数就会作为内容, 比方这里的 ”small”.

渲染组件

“h” 还能够渲染 ” 组件 ”, 这一下灵便度就上来了, 假如咱们有一个 ”switch” 组件, 其反对<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>

这里留神第 1 个参数还 反对传入组件对象 .
成果如下:

然而你能够发现了, “switch” 尽管显示了, 然而点击后 按钮并不能切换.

h 函数中应用 ”v-model”

下面不能切换是因为没有像在模板中那样应用 ”v-model”.

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

回顾下后面讲过的 ” 自定义双向数据绑定 ” 课中讲的如何实现 ”v-model”, 比照下能够发现下面 ”h” 中, 没有定义 ”props” 和 ”v-on 事件监听 ”, 怎么写呢?
先说一个 重要的知识点: 组件上的事件监听其实也可通过 ”props” 传入:

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

所有的自定义事件, 都能够通过 ”:on” 前缀通过 props 传入 . 所以在 ”h” 中能够通过第2 个参数传入 ”checked“ 属性和 ”onUpdate:checked“ 事件实现 ”v-model“ 的等同操作.

<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>

应用场景

理论开发中很多第三方组件都设计了能够接管 ”VNode” 的 ” 属性 ”, 比方 ”ant-design-vue” 的 ”Table” 组件的 ”columns” 属性中的 ”customRender” 属性, 能够通过传入 ”VNode” 实现款式自定义:

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

代码中通过 ”h” 渲染了 ”Tag” 组件, 成果如下:

总结

这节课讲了 3 个概念, 帮大家整顿下他们 3 者的关系: “render” 函数的返回值须要是 ”VNode” 格局, “h” 函数能够结构 ”VNode” 格局数据.

🍕学习互动

感激大家的浏览, 如有疑难能够加我微信, 我拉你进入 微信群

退出移动版