vue-render函数和插槽

Vue render函数,官方文档定义绝大部分时候我们使用template 来创建html 模板,但是纯html 和css都基本上都不具有编程能力,而当我们想使用

  javascript的编程能力时,我们可以用render 函数来创建html 模板

  1.使用简单的tamplate 去创建html 模板

// 使用简单的template 去创建html 模板
new Vue({
        el:'#test',
        data:{
            msg:'czczczcz'
        },
        template: '<h1> {{this.msg}} </h1>' // 我们使用template 去创建html 模板
    })

  2.当我们现在需求比较复杂,根据传入的一组标签组去创建模板,让我们先看看使用tamplate的方法

<div >
    <div v-html="jstem()">
    </div>
</div>
<script type="text/javascript">
    new Vue({
        el:'#test',
        data:{
            msg:['h1','h3','span','ul'] //简单的一组标签组
        },
        // 如果是直接使用标签我实在没想到办法 。我能想到的只能是        
        methods: {
            jstem () {
                let html = '';
                if(this.msg) {
                    this.msg.forEach(item => {
                        html += `<${item}>${item}</${item}>`
                    })
                }
                return html
            }
        }
    })
</script>

  上面的话还是使用javascript的编程你能力,我总结的是,就是当组件的html 模板都不固定,可能都需要一定的业务逻辑才能确定时,我们就可以考虑去使用render 函数,创建html模板,官方文档还讲明,template 最终还是要通过模板解析的,一系列底层操作后生成虚拟dom,而rander函数比tamplate更接近编辑器,也就是更容易转话成虚拟dom。

  render 函数

    render 函数传入一个createElement 方法,而这个方法,我们一般简写为h ,可以参阅vue-cli main.js 的 render: h => h(App)

<div >
    
</div>
<script type="text/javascript">
    new Vue({
        el:'#test',
        data:{
            msg:['h1','h3','span','ul'] //简单的一组标签组
        },
        render: function(h) {
            return h(
                'div', //传入的为一个节点的名称
{}, this.msg.map(function(item){ //第二个传入的为节点的值,值可以时一组元素节点 return h(item,item) }) ) } })

</script>

  render 函数内传入的第二个参数 data ,一系列属性,包括 class,style,arrts,props,domprops,on,nativeOn,directives,scopedSlots,slot,key,ref,refInfor

具体的用法请详见官方文档

  vue 插槽,主要是用于组件标签内信息,在组件内部展示,最新的slot 和slot-scope已经被官方放弃,且不会出现Vue3中,vue 新引入了v-slot 指令

    官方文档上的列子

//定义一个baseLayout 组件
<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>
// 上面定义了一个子组件, 子组件有三个插槽,header,footer,还有一个匿名插槽,其实是default

// 父组件内容  使用了v-slot 
<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

// 如果不使用v-slot 旧特性,定义具名
<base-layout>
    <h1 slot='header'>Here might be a page title</h1>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>
    <p slot='footer'>Here's some contact info</p>
  </slot >

最终会渲染出
<div class="container">
  <header>
    <h1>Here might be a page title</h1>
  </header>
  <main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </main>
  <footer>
    <p>Here's some contact info</p>
  </footer>
</div>

  具名插槽v-slot 的缩写为#

    v-slot='header' 可以写成 #header