【Vue3 从入门到实战 进阶式掌握完整知识体系】027-Vue中的高级语法:更加底层的render函数

215 阅读1分钟

4、更加底层的render函数

通过render函数实现显示不同的h标签

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>hello vue</title>
  <!-- 引入Vue库 -->
  <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
  <div id="root"></div>
</body>

<script>

  const app = Vue.createApp({
    template: `
      <my-title :level="3">
        hello
      </my-title>
    `
  });

  // 不同的参数呈现不同的标签
  app.component("my-title", {
    props: ['level'],
    // 使用 render
    render(){
      const { h } = Vue;
      // 匿名插槽 this.$slots.default()
      return h('h' + this.level, {}, this.$slots.default());
      // return h('h' + this.level, {}, 'hello world');
    }
    // 使用 template 写起来很复杂
    // template: `
    //     <h1 v-if="level === 1"><slot /></h1>
    //     <h2 v-if="level === 2"><slot /></h2>
    //     <h3 v-if="level === 3"><slot /></h3>
    //     <h4 v-if="level === 4"><slot /></h4>
    //     <h5 v-if="level === 5"><slot /></h5>
    // `
  });

  const vm = app.mount('#root');
</script>

</html>

运行结果

image-20210614122150396.png

render函数和template对比

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>hello vue</title>
  <!-- 引入Vue库 -->
  <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
  <div id="root"></div>
</body>

<script>

  const app = Vue.createApp({
    template: `
      <my-title :level="3">
        hello
      </my-title>
    `
  });

  // 不同的参数呈现不同的标签
  app.component("my-title", {
    props: ['level'],
    // 真实 DOM
    // <div>hello</div>
    // render函数 -> 虚拟 DOM (是对真实 DOM 的映射)
    // {
    //   tagName: 'div',
    //   text: 'hello',
    //   attributes: {}
    // }
    // 使用 render 的好处
    // 1、使得 vue 的性能更快;
    // 2、使得 vue 跨平台能力更强;
    // 使用 render
    render(){
      const { h } = Vue;
      // 匿名插槽 this.$slots.default()
      // 虚拟 DOM 
      // tagName:'h' + this.level
      // attributes:{}
      // text:this.$slots.default()
      // vue 会将虚拟 DOM 转换成真实的 DOM ,就显示在了页面上
      return h('h' + this.level, {}, this.$slots.default());
      // return h('h' + this.level, {}, 'hello world');
    }
    // 使用 template 写起来很复杂
    // template: `
    //     <h1 v-if="level === 1"><slot /></h1>
    //     <h2 v-if="level === 2"><slot /></h2>
    //     <h3 v-if="level === 3"><slot /></h3>
    //     <h4 v-if="level === 4"><slot /></h4>
    //     <h5 v-if="level === 5"><slot /></h5>
    // `
  });

  const vm = app.mount('#root');
</script>

</html>

执行逻辑

template模板 ——> render函数 ——> h 系列标签——> 虚拟DOM(JS对象)——> 真实DOM ——> 展示到页面;

无限嵌套render

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>hello vue</title>
  <!-- 引入Vue库 -->
  <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
  <div id="root"></div>
</body>

<script>

  const app = Vue.createApp({
    template: `
      <my-title :level="3">
        hello
      </my-title>
    `
  });

  // 不同的参数呈现不同的标签
  app.component("my-title", {
    props: ['level'],
    render(){
      const { h } = Vue;
      return h('h' + this.level, {}, [
        this.$slots.default(),
        h("div", {}, [
          "我是div内容-嵌套1",
          h("h1", {style:"color:red;"}, "我是h1内容-嵌套2")
        ])
      ]);
    }
  });

  const vm = app.mount('#root');
</script>

</html>

运行结果

image-20210614124033834.png