组件插槽

单个插槽

  • 如果我们希望组件标签可以像HTML标签一样设置内容,那么组件的使用灵活度会很高。

    <div id="app">
    <p>示例内容</p>
    <com-a>实力内容2</com-a>
    </div>
  • 但平常我们书写的组件,组件首尾标签中书写的内容会被抛弃。(上面的“实力内容2”)
  • 我们需要通过<slot>进行插槽设置。

    Vue.component('com-a',{
    template:`
      <div>
        <p>示例内容</p>
        <slot></slot> // 插槽
      </div>
    `
    })

    自定义组件内添加内容,替换slot标签,普通文本和标签都可设置成功

    <div id="app">
    <com-a>
      示例内容
      <span>组件主体</span>
    </com-a>
    </div>

    注意:

  • 模板内容的渲染位置

    • 当前结构模板属于父组件的视图
    • 内部所以内容,代码,数据都是由父组件进行模板渲染的
    • 插槽是父组件给子组件设置的,数据是父组件的数据(当然也可以使用子组件数据,通过作用域插槽后面讲)
    • 父级组件模板的所有内容都是在父级作用域中编译执行,子组件模板的内容在子组件作用域内编译执行

      <div id="app">
      <com-a>
      这里只能访问父组件的数据
      {{ parValue }}
      </com-a>
      </div>
      new Vue({
      data:{ parValue:'父组件数据' },
      components:{
      ComA
      }
      })
      var ComA={
      template:`
      <div>
        <p>组件A:{{ value }}</p>
        <slot></slot>
      </div>
      `,
      data(){
      return {
        value:'子组件数据'
      }
      }
      }
  • 插槽的作用是组件对当前子组件的内容进行便捷设置,内容由父组件进行设置
  • 如果父组件并没有传入数据,我们可以在<slot>中为插槽设置默认值,也称为后备内容。

    var ComA={
    template:`
      <div>
        <p>组件A:</p>
        <slot>这是默认文本</slot>  // 默认值
      </div>
    `,
    data(){
      return {
        value:'子组件数据'
      }
    }
    }
    <div id="app">
    <com-a></com-a>  // 插槽没接收到值,显示默认值
    </div>

    具名插槽

  • 如果组件中有多个位置需要设置插槽,据需要给<slot>设置name,称为具名插槽。

子组件结构内内设置多个插槽

Vue.component('ComA',{
  template:`
    <div>
      <header>
        <slot name="header"></slot> // 具名
      </header>
      <main>
        <slot></slot>
      </main>
      <footer>
        <slot name="footer"></slot>
      </footer>
    </div>
  `
})

父组件使用插槽,传入数据

  • template 是占位符,不显示标签
  • v-slot 只能在template中设置
  • 未设置具名的插槽,默认为default
  • 默认slot可以简写,所有没有被v-slot指定的插槽内容都被认为是 默认插槽内容
  • 具名可以简写为#header #footer
  • 具名插槽只能分配具名对应的内容,无法显示默认内容
  • 一般内容比较多的插槽部分,设置为 default 形式

    <com-a>
    <template v-slot:header> // 设置
      <h1>组件头部内容</h1>
    </template>
    
    <template v-slot:default> // 默认
      <p>组件主体内容</p>
    </template>
    
    <template v-slot:footer>
      <p>组件底部内容</p>
    </template>
    </com-a>

    简写形式

    <com-a>
    <template #header>
      <h1>组件头部内容</h1>
    </template>
    
    <p>组件主体内容</p>
    
    <template #footer>
      <p>组件底部内容</p>
    </template>
    </com-a>

    作用域插槽

  • 插槽可以由父组件向子组件便捷内容设置,但是由于组件渲染规则,组件插槽内部只能使用父组件的数据,因为这段结构是父组件渲染的
  • 如果希望父组件插槽内部使用子组件数据的话,需要使用作用域插槽进行设置
  • 作用域插槽:用于让插槽可以使用子组件的数据。

组件将需要被插槽使用的数据通过v-bind绑定给<slot>,这种用于给插槽传递数据的属性称为插槽prop。

子组件插槽绑定

// 子组件选项对象

var ComA = {
  template:`
    <div>
      <p>组件A:</p>
      <slot :value="value">这是默认文本</slot>
    </div>
  `,
  data(){
    return {
      value:"子组件数据"
    }
  }
}

父组件接收数据

  • 子组件绑定数据后,父组件的插槽中需要通过v-slot接收数据。
  • 接收的是包含所有插槽prop的对象(子组件可以绑定多个属性传递,都在这个对象中),可以给对象任意命名

    <div id="app">
    <com-a>
      <template v-slot:default="dataObj"> 
        {{ dataObj.value }}
      </template>
    </com-a>
    </div>
  • 如果只存在默认插槽,同时又需要接收数据,可以进行简写(特殊)

    <div id="app">
    <com-a v-slot:default="dataObj">
      {{ dataObj.value }}
    </com-a>
    </div>
  • 再次简写,注意: 之前操作 v-slot 可简写成 #。 但是 v-slot:default="数据" 写成#=数据 不可以
  • 存在slot名称的时候才能用#简化,当前情况只是接收数据,不具备名称功能
  • #defaultv-slot 均可

    <div id="app">
    <com-a v-slot="dataObj">
      {{ dataObj.value }}
    </com-a>
    </div>
    <div id="app">
    <com-a #default="dataObj">
      {{ dataObj.value }}
    </com-a>
    </div>
  • 还可以通过ES6的解构操作进行数据接收。

    <div id="app">
    <com-a #default="{ value }">
      {{ value }}
    </com-a>
    </div>

mcgee0731
60 声望4 粉丝

不会做饭的程序猿不是一个好厨子