slot插槽

Nevermore毓2023年5月7日
大约 3 分钟

插槽示例

插槽的使用过程其实是抽取共性、预留不同,将共同的元素、内容依然在组件内进行封装,将不同的元素使用 slot 作为占位,让外部决定到底显示什么样的元素

基本用法

  <div id=#app>
    <cpn><button>具有按钮功能的cpn个性化组件</button></cpn>
    <cpn><p>带有p标签的cpn个性化组件</p></cpn>
    <cpn></cpn>
    <cpn>
      <i>呵呵呵</i>
      <div>我是div元素</div>
      <p>我是p元素</p>
    </cpn>
  </div>

  <template id="cpn">
    <div>
      <span>我是cpn组件</span>
      <p>slot的基本使用</p>
      <slot></slot>
      <!-- 插槽默认带按钮(后备内容) -->
      <!-- <slot><button>按钮</button></slot> -->
    </div>
  </template>

具名插槽

v-slot:#(缩写)

注意 :v-slot** 只能添加在 **<template>** 上** (只有一种例外情况open in new window),这一点和已经废弃的 slotopen in new window attributeopen in new window 不同(slot可以用在<template>上也可以用在普通元素上)。

  <div id = "app">
    <!-- 在中插槽指定位置插入 -->
    <!-- 2.6.0以下的写法 -->
    <cpn><span slot="center">标题</span></cpn>

    <!-- 2.6.0以上的写法 -->
    <template v-slot:center>
      <cpn><span>标题</span></cpn>
    </template>

    <!-- 缩写 -->
    <template #center>
      <cpn><span>标题</span></cpn>
    </template>

    <!-- 动态插槽(name从data里面取出) -->
    <template v-slot:[name]>
      <cpn><span>标题</span></cpn>
    </template>
  </div>

  <template id="cpn">
    <div>
      <slot name="left"><span>左插槽</span></slot>
      <slot name="center"><span>中插槽</span></slot>
      <slot name="right"><span>右插槽</span></slot>
    </div>
  </template>

编译作用域

  • 父组件模板的所有东西都会在父级作用域内编译
  • 子组件模板的所有东西都会在子级作用域内编译
  <div id="app">
    <cpn v-show="isShow"></cpn> <!-- true -->
    <cpn v-for="item in names"></cpn>
  </div>

  <template id="cpn">
    <div>
      <h2>我是子组件</h2>
      <button v-show="isShow">按钮</button> <!-- false -->
    </div>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        isShow: true
      },
      components: {
        cpn: {
          template: '#cpn',
          data() {
            return {
              isShow: false
            }
          }
        },
      }
    })
  </script>

作用域插槽

父组件替换插槽的标签,但是内容由子组件来提供。

作用域插槽:子组件提供内容(数据),在父组件中展示,延伸了子组件的作用域,用于定制化显示。(如elementui中的table表格数据定制)。

插槽:父组件提供内容,在子组件中展示。

  <!-- 父组件 -->
  <cpn>
    <!-- 目的是获取子组件中的pLanguages数据内容 -->
    <!-- 不加slot-scope的话,访问不到子组件的pLanguages数据,因为编译作用域 -->
    <template slot-scope="slot">
      <span v-for="item in slot.data"> - {{item}}</span>
    </template>
  </cpn>

  <!-- 子组件 -->
  <template id="cpn">
    <div>
      <slot :data="pLanguages">
        <ul>
          <li v-for="item in pLanguages">{{item}}</li>
        </ul>
      </slot>
    </div>
  </template>

  <script>
    new Vue({
      // ...
      components: {
        cpn: {
          template: #cpn,
          data() {
            return { pLanguages: ['JavaScript', 'C++', 'Java', 'C#', 'Python', 'Go', 'Swift'] }
          }
        }
      }
    })
  </script>

默认插槽和具名插槽混合

  • 只有默认插槽时,组件的标签可以被当做插槽的模板来使用,v-slot 直接用在组件上
<show-names :names="names" v-slot="slotProps">
  <span>{{slotPorps.item}}--{{slotProps.index}}</span>
</show-names>
  • 若有默认插槽和具名插槽,则必须按照完整的 template 来编写,否则报错
<show-names :names="names">
  <!-- 默认插槽(v-slot:default="slotProps"的缩写) -->
  <template v-slot="slotProps">
    <span>{{slotPorps.item}}--{{slotProps.index}}</span>
  </template>

  <!-- 具名插槽 -->
  <template v-slot:center>
    <h2>哈哈哈</h2>
  </template>
</show-names>
Loading...