vue 插槽 slot 的用法

vue 插槽 slot 的用法

  • 一、简单定义、使用 slot
  • 二、slot 变量传值
  • 三、跨组件传递 slot
    • 方法1: 多定义一个中间插槽
    • 方法2:使用 scopedSlots 字段 传递作用域插槽
    • 方法3:动态组件渲染[TODO]
    • 方法4:Provide/Inject 将Slot主动传递给子节点 [TODO]
  • 附加

一、简单定义、使用 slot

  1. 新建 child 子组件,定义 container 插槽。

<template>
  <div>
    <p> child 组件p>
    <slot name="container">slot>
  div>
template>
  1. 新建 father 组件,引用子组件 childcontainer 插槽。

<template>
  <div>
    <p> father 组件p>
    <child>
     <template slot="container">写法1template>
      
      
    child>
  div>
template>
<script>
import child from "./child.vue";
export default {
  name: "father",
  components: { child }
};
script>

效果如图所示:
vue 插槽 slot 的用法_第1张图片

注:如果 father 组件引用插槽的时候不加具插槽名slot="container", 则默认替换整个 child 组件的内容。

二、slot 变量传值

  1. 在子组件 child 的基础上,给 slot 绑定 message 变量,值为 data 中的 msg 变量值

<template>
  <div>
    <p> child 组件p>
    <slot name="container" :message="msg">slot>
  div>
template>
<script>
export default {
  name: 'child',
  data() {
    return {
      msg: '我是子组件 data 中的 msg 变量'
    }
  }
}
script>
  1. 在父组件 father 的基础上,接收子组件 childcontainer 插槽传过来的 message 变量。

<template>
  <div>
    <p> father 组件p>
    <child>
      
      
      <template v-slot:container="{message}">{{message}}template>
    child>
  div>
template>
<script>
import child from "./child.vue";
export default {
  name: "father",
  components: { child }
};
script>

效果如图所示:
vue 插槽 slot 的用法_第2张图片

三、跨组件传递 slot

需求描述:
目前有三个组件,GrandFather.vue 组件、father.vue 组件 和 child.vue 组件, GrandFather.vue 组件 想直接引用并向 child.vue 的 slot 传递变量。
我们期望的正确展示效果如下图所示:
vue 插槽 slot 的用法_第3张图片


<template>
  <div>
    <p> 我是 child 组件p>
    <slot name="child-container">slot>
  div>
template>

<template>
  <div>
    <p> 我是 father 组件p>
    <slot name="father-container">slot>
    <child>
      <template slot="child-container">这里的值是 father 组件在 child 组件中的 child-container 插槽中展示template>
    child>
  div>
template>
<script>
import child from "./child.vue";
export default {
  name: "father",
  components: { child }
};
script>

<template>
  <div>
    <p> 我是 GrandFather 组件p>
    <father>
      <template slot = "father-container">这里的值是 GrandFather 组件 想在 father 组件中的 father-container 插槽中展示template>
      
      <template slot = "child-container">这里的值是 GrandFather 组件 想在 child 组件中的 child-container 插槽中展示template>
    father>
  div>
template>

<script>
import father from "./father.vue";
export default {
  name: "GrandFather",
  components: { father}
};
script>

vue 插槽 slot 的用法_第4张图片
上面的图片结果是初始化代码运行的结果,但似乎与我们期望的代码结果不一致。这是为什么呢?注意在 vue 官网中强调过一点:

父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

所以,在 GrandFather 组件中,仅能访问到 father 组件中定义过的插槽,而 child 组件中定义的插槽,GrandFather 组件是无法直接访问到的。那么要怎么实现上面的这种效果,有以下几种方法。

方法1: 多定义一个中间插槽

在不改动 child.vueGrandFather.vue 的前提下,我们单独改动 father.vue 组件如下:


<template>
  <div>
    <p> 我是 father 组件p>
    <slot name="father-container">slot>
    <child>
      <template slot="child-container"> 
        <slot name="child-container">slot> 
      template>
    child>
  div>
template>
<script>
import child from "./child.vue";
export default {
  name: "father",
  components: { child }
};
script>

方法2:使用 scopedSlots 字段 传递作用域插槽

在 vue 官网上有句话叫做:vm.$scopedSlots 在使用 渲染函数 开发一个组件时特别有用。这个方法的改动也需要借助渲染函数。在不改动 child.vueGrandFather.vue 的前提下,我们单独改动 father.vue 组件如下:


<script>
import child from "./child.vue";
export default {
  name: "father",
  components: { child },
  render(createElement) {
    const defaultChildSlotMsg = '这里的值是 father 组件在 child 组件中的 child-container插槽中展示'
    return createElement("div", [
      createElement("p", "我是 father 组件"),
      createElement("slot", this.$slots["father-container"]), // 创建插槽,内容为 GrandFather.vue 中引用 'father-container' 的内容
      createElement("child", {
        scopedSlots: {
          // child.vue 中的插槽名: ()=> GrandFather.vue 引用的插槽名 
          "child-container": () => this.$slots["child-container"] || defaultChildSlotMsg
        }
      }),
    ]);
  }
};
script>

方法3:动态组件渲染[TODO]

该方法的大概思路为:子组件 主动去获取 父级组件 的 slot 对象,然后再创建一个动态组件进行渲染。将代码恢复至初始状态之后,在不改动GrandFather.vuefather.vue 的前提下,我们单独改动 child.vue 组件。

方法4:Provide/Inject 将Slot主动传递给子节点 [TODO]

附加

  1. $slots 可以拿到当前作用域的所有slot插槽

参考文件:
https://cn.vuejs.org/v2/guide/components-slots.html
https://cn.vuejs.org/v2/guide/render-function.html#%E6%8F%92%E6%A7%BD

你可能感兴趣的:(vue,vue.js)