1.template模板

父组件:App,子组件:Test
app.vue中

<template>
  <div id="app">
    <h1>这是app组件</h1>
    <Test></Test>
  </div>
</template>
<script>
import Test from './Test.vue'
export default {
  name: 'App',
  components: {
    Test
  }
}
</script>

Test.vue组件 是使用template模板

<template>
  <div>
    <h2>hello,我是Test组件</h2>
  </div>
</template>
<script>
export default {
  name: 'Test'
}
</script>

2.使用render函数

当不使用template模板,直接使用render函数,实现了同样的效果。

<script>
export default {
  name: 'Test',
  //  createElement与下面一致
  render(createElement){
    // 传三个参数       标签/组件名、选项、子元素(直接文本元素、或者使用data定义的数据等)
    return createElement('h2',{},'hello,我是Test组件')
  }
}
</script>

所以:实际上template 在Vue内部最终也会编译成render函数

<template>
  <div>
    <h2>hello,我是Test组件</h2>
  </div>
</template>

   //编译成render函数:
  //  createElement与下面一致
  render(createElement){
    // 传三个参数       标签/组件名、选项、子元素(直接文本元素、使用data定义的数据)
    return createElement('h2',{},'hello,我是Test组件')
  }

3.第一个参数

1.动态创建标签

第一个参数 标签/组件名 也可以由父组件传来,
也就是render函数实现了动态创建标签
App.vue中传来tag=“h5”

<template>
  <div id="app">
    <h1>这是app组件</h1>
    <Test tag="h5"></Test>
  </div>
</template>
<script>
import Test from './Test.vue'
export default {
  name: 'App',
  components: {
    Test
  }
}
</script>

在Test.vue中定义props,实现了渲染’hello,我是Test组件’ 为h5标签:

<script>
export default {
  name: 'Test',
  props: {
    tag: String
  },
  render (createElement) {
    return createElement(this.tag, {}, 'hello,我是Test组件')
  }
}
</script>
2.第一个参数是组件

再建一个Demo.vue组件

<template>
  <div>
    我是Demo组件,接受到我的父组件Test传来的数据是:{{ message }}
  </div>
</template>
<script>
export default {
  name: 'Demo',
  props: {
    message: String
  }
}
</script>

Test.vue

<script>
import Demo from './Demo.vue'
export default {
  name: 'Test',
  components: {
    Demo
  },
  render (createElement) {
    return createElement(
      // 第一个参数
      Demo,
      // 第二个参数
      {
        props: {
          message: 'hello message'
        }
      },
      // 没有第三个参数  
    )
  }
}
</script>

App.vue:

<template>
  <div id="app">
    <h1>这是app组件</h1>
    <Test ></Test>
  </div>
</template>
<script>
import Test from './Test.vue'
export default {
  name: 'App',
  components: {
    Test
  }
}
</script>

4.第二个参数

给test组件的添加了类名、click点击事件。
给标签添加样式
点击 ‘hello,我是Test组件’ 就会console.log打印。
Test.vue

<script>
export default {
  name: 'Test',
  render (createElement) {
    return createElement(
      //  第一个参数
      'h2',
      //  第二个参数
      {
        attrs:
        {
          class: 'test'
        },
        on: {
          click: () => { console.log('打印') }
        }
      },
      // 第三个参数
      'hello,我是Test组件')
  }
}
</script>
<style>
.test{
  color: red;
}
</style>

App.vue:

<template>
  <div id="app">
    <h1>这是app组件</h1>
    <Test ></Test>
  </div>
</template>
<script>
import Test from './Test.vue'
export default {
  name: 'App',
  components: {
    Test
  }
}
</script>

5.第三个参数

Test.vue
使用data定义的数据

<script>
export default {
  name: 'Test',
  data () {
    return {
      msg: 'hello 我是test组件'
    }
  },
  render (createElement) {
    return createElement(
      // 第一个参数
      'h2',
      // 第二个参数
      {},
      // 第三个参数  
      this.msg
    )
  }
}
</script>

App.vue

<template>
  <div id="app">
    <h1>这是app组件</h1>
    <Test ></Test>
  </div>
</template>
<script>
import Test from './Test.vue'
export default {
  name: 'App',
  components: {
    Test
  }
}
</script>

第三个参数为引用类型数组
Test.vue:

<script>
export default {
  name: 'Test',
  data () {
    return {
      people: ['何幸福', '关涛', '王庆来', '万善堂']
    }
  },
  render (createElement) {
    return createElement(
      // 第一个参数
      'ul',
      // 第二个参数
      {
        attrs:{
          class:'test'
        }
      },
      // 第三个参数  使用data的数据
      this.people.map((name) => {
        return createElement(
          // 第一个参数
          'li',
          // 第二个参数
          {
            attrs: {
              class: 'people'
            },
            on: {
              click: () => {
                console.log('点击li啦')
              }
            }
          },
          `${name}`
        )
      })
    )
  }
}
</script>
<style>
.test{
  list-style: none;
}
.people{
  font-size:20px;
}
</style>

相当于使用template如下:

<template>
  <ul class="test">
    <li v-for="(item, index) in people" :key="index" class="people" >
      {{ item }}
    </li>
  </ul>
</template>
<script>
export default {
  data () {
    return {
      people: ['何幸福', '关涛', '王庆来', '万善堂']
    }
  }
}
</script>
<style>
.test {
  list-style: none;
}
.people {
  font-size: 20px;
}
</style>

App.vue:

<template>
  <div id="app">
    <h1>这是app组件</h1>
    <Test ></Test>
  </div>
</template>
<script>
import Test from './Test.vue'
export default {
  name: 'App',
  components: {
    Test
  }
}
</script>

6.render函数妙用

父组件App传递level的值,子组件Test根据level的值使用不同的h标签渲染内容
App.vue:

<template>
  <div id="app">
    <h1>这是app组件</h1>
    <Test :level="1"></Test>
    <Test :level="2"></Test>
    <Test :level="3"></Test>
    <Test :level="4"></Test>
    <Test :level="5"></Test>
    <Test :level="6"></Test>
  </div>
</template>
<script>
import Test from './Test.vue'
export default {
  name: 'App',
  components: {
    Test
  }
}
</script>

Test.vue:

<template>
  <div>
    <h1 v-if="level === 1">h1标签:aaa</h1>
    <h2 v-else-if="level===2">h2标签:bbb</h2>
    <h3 v-else-if="level===3">h3标签:ccc</h3>
    <h4 v-else-if="level===4">h4标签:ddd</h4>
    <h5 v-else-if="level===5">h5标签:eee</h5>
    <h6 v-else-if="level===6">h6标签:fff</h6>
  </div>
</template>
<script>
export default {
  name: 'Test',
  props: {
    level: Number
  }
}
</script>
改造第一步:插槽

App.vue

<template>
  <div id="app">
    <h1>这是app组件</h1>
    <Test :level="1">h1标签:aaa</Test>
    <Test :level="2">h2标签:bbb</Test>
    <Test :level="3">h3标签:ccc</Test>
    <Test :level="4">h4标签:ddd</Test>
    <Test :level="5">h5标签:eee</Test>
    <Test :level="6">h6标签:fff</Test>
  </div>
</template>
<script>
import Test from './Test.vue'
export default {
  name: 'App',
  components: {
    Test
  }
}
</script>

Test.vue:

<template>
  <div>
    <h1 v-if="level === 1"><slot></slot></h1>
    <h2 v-else-if="level===2"><slot></slot></h2>
    <h3 v-else-if="level===3"><slot></slot></h3>
    <h4 v-else-if="level===4"><slot></slot></h4>
    <h5 v-else-if="level===5"><slot></slot></h5>
    <h6 v-else-if="level===6"><slot></slot></h6>
  </div>
</template>
<script>
export default {
  name: 'Test',
  props: {
    level: Number
  }
}
</script>
改造第二步:render

Test组件使用render函数,动态创建标签

<script>
export default {
  name: 'Test',
  props: {
    level: Number
  },
  render (createElement) {
    return createElement(
      // 第一个参数
      'h' + this.level,
      {},
      this.$slots.default
    )
  }
}
</script>

可见这个Test.vue组件中仅使用script标签
可改造为Test.js文件

export default {
  props: {
    level: Number
  },
  render (createElement) {
    return createElement(
      'h' + this.level,
      this.$slots.default
    )
  }
}

或者:

export default {
  props: {
    level: Number
  },
  render (createElement) {
    // console.log(createElement);
    const tag = 'h' + this.level;
    return (
      <tag>
        {this.$slots.default}
      </tag>
    )
  }
}
Logo

前往低代码交流专区

更多推荐