1. 程式人生 > 其它 >682 vue3非父子元件的通訊之插槽Slot:多個插槽,具名插槽,動態插槽名,渲染作用域

682 vue3非父子元件的通訊之插槽Slot:多個插槽,具名插槽,動態插槽名,渲染作用域

認識插槽Slot


如何使用插槽slot?


插槽的基本使用


插槽的預設內容


多個插槽的效果


App.vue

<template>
  <div>
    <my-slot-cpn>
      <button>我是按鈕</button>
    </my-slot-cpn>

    <my-slot-cpn>
      我是普通的文字
    </my-slot-cpn>

    <my-slot-cpn>
      <!-- 也可以插入元件 -->
      <my-button />
    </my-slot-cpn>

    <!-- 沒有插入對應的內容,那麼會顯示插槽預設的內容 -->
    <my-slot-cpn></my-slot-cpn>

    <!-- 插入很多的內容,每個插槽都會獲取插入的內容來顯示 -->
    <my-slot-cpn>
      <h2>哈哈哈</h2>
      <button>我是按鈕</button>
      <strong>我是strong</strong>
    </my-slot-cpn>
  </div>
</template>

<script>
  import MySlotCpn from "./MySlotCpn.vue";
  import MyButton from "./MyButton.vue";
  // C0C8D2  C0C8D2
  export default {
    components: {
      MySlotCpn,
      MyButton,
    },
  };
</script>

<style scoped></style>

MySlotCpn.vue

<template>
  <div>
    <h2>元件開始</h2>
    <slot>
      <i>我是預設的i元素</i>
    </slot>
    <slot>
      <i>我是預設的i元素</i>
    </slot>
    <slot>
      <i>我是預設的i元素</i>
    </slot>
    <h2>元件結束</h2>
    <hr />
  </div>
</template>

<script>
  export default {};
</script>

<style scoped></style>

MyButton.vue

<template>
  <div>
    <button>哈哈哈 我是button元件</button>
  </div>
</template>

<script>
  export default {};
</script>

<style scoped></style>

具名插槽的使用


動態插槽名


具名插槽使用的時候縮寫


App.vue

<template>
  <div>
    <nav-bar :name="name">
      <!-- 要用template元素包裹 -->
      <template #left>
        <button>左邊的按鈕</button>
      </template>
      <template #center>
        <h2>我是標題</h2>
      </template>
      <template #right>
        <i>右邊的i元素</i>
      </template>
      <template #[name]>
        <i>why內容</i>
      </template>
    </nav-bar>
  </div>
</template>

<script>
  import NavBar from "./NavBar.vue";

  export default {
    components: {
      NavBar,
    },
    data() {
      return {
        name: "why",
      };
    },
  };
</script>

<style scoped></style>

<template>
  <div class="nav-bar">
    <!-- <slot name="default"></slot> -->
    <div class="left">
      <slot name="left"></slot>
    </div>
    <div class="center">
      <slot name="center"></slot>
    </div>
    <div class="right">
      <slot name="right"></slot>
    </div>
    <div class="addition">
      <slot :name="name"></slot>
    </div>
  </div>
</template>

<script>
  export default {
    props: {
      name: String,
    },
    // data() {
    //   return {
    //     name: "why"
    //   }
    // }
  };
</script>

<style scoped>
  .nav-bar {
    display: flex;
  }

  .left,
  .right,
  .center {
    height: 44px;
  }

  .left,
  .right,
  .addition {
    width: 80px;
    background-color: red;
  }

  .center {
    flex: 1;
    background-color: blue;
  }
</style>

渲染作用域


渲染作用域案例


認識作用域插槽


作用域插槽的案例


獨佔預設插槽的縮寫


預設插槽和具名插槽混合


App.vue

<template>
  <div>
    <!-- 編譯作用域 -->
    <!-- <child-cpn>
      <button>{{title}}</button>
    </child-cpn> -->

    <show-names :names="names">
      <template v-slot="coderwhy">
        <button>{{ coderwhy.item }}-{{ coderwhy.index }}</button>
      </template>
    </show-names>

    <!-- 獨佔預設插槽的縮寫 -->
    <!-- 【注意,v-slot是加給元件標籤,不是加給其他標籤。】 -->
    <show-names :names="names" v-slot="coderwhy">
      <button>{{ coderwhy.item }}-{{ coderwhy.index }}</button>
    </show-names>

    <!-- 注意: 如果還有其他的具名插槽, 那麼預設插槽也必須使用template來編寫 -->
    <show-names :names="names">
      <template v-slot="coderwhy">
        <button>{{ coderwhy.item }}-{{ coderwhy.index }}</button>
      </template>

      <template v-slot:why>
        <h2>我是why的插入內容</h2>
      </template>
    </show-names>

    <show-names :names="names">
      <template v-slot="slotProps">
        <strong>{{ slotProps.item }}-{{ slotProps.index }}</strong>
      </template>
    </show-names>
  </div>
</template>

<script>
  import ChildCpn from "./ChildCpn.vue";
  import ShowNames from "./ShowNames.vue";

  export default {
    components: {
      ChildCpn,
      ShowNames,
    },
    data() {
      return {
        names: ["why", "kobe", "james", "curry"],
      };
    },
  };
</script>

<style scoped></style>

ChildCpn.vue

<template>
  <div>
    <slot></slot>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        title: "我是title",
      };
    },
  };
</script>

<style scoped></style>

ShowNames.vue

<template>
  <div>
    <template v-for="(item, index) in names" :key="item">
      <slot :item="item" :index="index"></slot>

      <slot name="why"></slot>
    </template>
  </div>
</template>

<script>
  export default {
    props: {
      names: {
        type: Array,
        default: () => [],
      },
    },
  };
</script>

<style scoped></style>