VUE插槽

介绍

在我们构建页面过程中一般会把用的比较多的公共部分抽取出来作为一个单独的组件,但是在实际使用这个组件的时候不能完全满足需求,希望在这个组件中添加其他东西,这时候就需要用到vue的插槽来分发内容
可以想象一下电脑的主板,主板上有有很多插槽,而每个插槽可能对应了不同的配置,那么在vue总结就可以这么理解,各个插槽有各个插槽的功能,他们可以互相独立,可以用于组件之间的通信,让用户可以拓展组件,去更好的复用组件对其做定制化处理。
插槽分类:匿名插槽,具名插槽,作用域插槽。

快速了解组件

父组件:test.vue

<template>
    <div>
      <div>大家好我是父组件</div>
      <myslot>
        <p>测试一下吧内容写在这里了能否显示</p>
      </myslot>
    </div>
</template>

<script>
  import myslot from './myslot';
  export default {
    components: {
      myslot
    }
  }
</script>

<style>
</style>

子组件: myslot.vue

<template>
  <div>
      <div>我是子组件</div>
  </div>
</template>

<script>
</script>

<style>
</style>

运行结果:
在这里插入图片描述
如果想事想显示父组件中p标签的内容,那么就可以修改子组件:msolt.vue即可

<template>
  <div>
      <div>我是子组件</div>
      <p>现在测试一下slot</p>
      <slot></slot>
  </div>
</template>

<script>
</script>

<style>
</style>

渲染结果:
在这里插入图片描述
由上面的例子可以看出,插槽的应用场景,我们经常像一个逐渐传递VUE自定义的元素让这变得非常简单,只需要在需要的地方加入插槽就行了!
综合上面的例子来理解:
1.父组件在引用子组件的时候,希望向子组件传递模板内容

测试一下吧内容写在这里是否显示


2.子组件让父组件传过来的模板内容在所在的位置显示。
3.子组件中的“solt”就是一个槽,可以接受父组件传过来的模板内容,solt元素自身将被替换。
4.mysolt组件没有包含一个solt元素,则该组件起始标签和结束标签之间的任何内容将被抛弃。

插槽的分类:

一、默认插槽
在一个< submit-button >组件中,我们希望这个button内绝大多数情况下都渲染文本"submit",但是有时候却希望渲染文本为别的东西,如何实现呢?

<button type="submit">
  <slot></slot>
</button>

我们可以将"“submit"作为后备内容,将它放在"slot标签内”

<button type="submit">
  <slot>Submit</slot>
</button>

当在一个父级组件中使用< submit-button > 并且不提供任何插槽内容时候

<submit-button></submit-button>

后被内容"submit"将被渲染

<button type="submit">
  Submit
</button>

但是如果我们提供内容

<submit-button>
  Save
</submit-button>

则这个提供的内容将会被渲染,从而取代后备内容

<button type="submit">
  Save
</button>

二、具名插槽
写一个子组件,想:

<template>
    <div class="container">
      <header>
        <!-- 我们希望把页头放这里 -->
      </header>
      <main>
        <!-- 我们希望把主要内容放这里 -->
      </main>
      <footer>
        <!-- 我们希望把页脚放这里 -->
      </footer>
    </div>
</template>

上面这种情况,slot元素有一个特殊的attribute:name。这个attribute可以用来定义额外的插槽:

<template>
  <div class="container">
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

一个不带name的solt出口会带有隐含的名字"default",父组件在象具名插槽提供内容的时候,我们可以在一个"template"元素上使用v-solt指令,并以v-solt的参数提供其名称:

<template>
  <myslot>
    <div>大家好我是父组件</div>
    <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 footer info</p>
    </template>
  </myslot>
</template>

<script>
  import myslot from './myslot';
  export default {
    components: {
      myslot
    }
  }
</script>

最终的渲染结果:在这里插入图片描述
父组件会向子组件中具名传递对应的模板内容,而没有指定的名字的模板内容会传递给子组件中不带有name属性的solt,当然,如果负组件中

<template v-slot:default>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
</template>

负组件中同样是传递给子组件中不带name的slot,注意:v-slot只能添加template上,具名插槽在书写的时候还可以使用缩写“v-solt使用’#'来代替”

<template>
  <myslot>
    <div>大家好我是父组件</div>
    <template #header>
      <h1>Here might be a page title</h1>
    </template>

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

    <template #footer>
      <p>Here's footer info</p>
    </template>
  </myslot>
</template>

<script>
  import myslot from './myslot';
  export default {
    components: {
      myslot
    }
  }
</script>

<style>
</style>

三、作用域插槽
作用域插槽主要解决的是父组件在向子组件插槽传递模板内容的时候存在访问子组件数据的问题,默认插槽:如果子组件中卸载slot标签内,后背内容是与该组件的data属性双向数据绑定的。

<template>
  <div>
    <span>
      <slot>{{user.firstName}}</slot>
    </span>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        user:{
          firstName:'gerace',
          lastName:'haLi'
        }
      }
    }
  }
</script>
<style>
</style>

父组件在引用子组件时,希望能够换掉备用内容

<template>
  <myslot>{{ user.firstName }}</myslot>
</template>

<script>
  import myslot from './myslot';
  export default {
    components: {
      myslot
    }
  }
</script>
<style>
</style>

这段代码是错误的在这里插入图片描述
这是因为,父级模板里的而所有内容都是在父级作用域中编译的,子模版里的所有内容都是在子作用域中编译的,如果让user在父级插槽内容中可用,我们可以将user作为solt元素的一个attribute绑定上去:

<span>
  <slot v-bind:user="user">
    {{ user.lastName }}
  </slot>
</span>

绑定在solt元素上的attribute被称为插槽prop,现在在父级作用域中,我们可以使用带值的v-solt来定义我们提供的prop的名字:

<template>
  <myslot>
      <template v-slot:default="slotProps">
      {{ slotProps.user.firstName }}
      </template>
  </myslot>
</template>

<script>
  import myslot from './myslot';
  export default {
    components: {
      myslot
    }
</script>
<style>
</style>

上面的内容,我们选择将包含所有的插槽prop的对象命名为slotProps,但你也可以使用任意可使用的名字,针对上面只给默认插槽传递模板内容的李至,也可以采取以下默认插槽的语法:

<template>
  <myslot v-slot:default="slotProps">
     {{ slotProps.user.firstName }}
  </myslot>
</template>

<script>
  import myslot from './myslot';
  export default {
    components: {
      myslot
    }
</script>
<style>
</style>

上面代码直接改为下面形式

<template>
  <myslot v-slot="slotProps">
     {{ slotProps.user.firstName }}
  </myslot>
</template

值得注意的是:默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确:

<template>
  <myslot v-slot="slotProps">
     {{ slotProps.user.firstName }}
     <template v-slot:other="otherSlotProps">
   		slotProps is NOT available here
     </template>
  </myslot>
</template>

下面看一下多个插槽的情况
子组件

<template>
  <div>
    <span>
      <slot v-bind:userData="user" name="header">
        {{ user.msg }}
      </slot>
      <slot v-bind:hobbyData="hobby" name="footer">
        {{ hobby.fruit }}
      </slot>
    </span>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        user:{
          firstName: 'gerace',
          lastName: 'haLi',
        },
        hobby:{
          fruit: "apple",
          color: "blue"
        }
      }
    }
  }
</script>
<style>
</style>

父组件

<template>
  <myslot>
      <template v-slot:header="slotProps">
        {{ slotProps.userData.firstName }}
      </template>
      <template v-slot:footer="slotProps">
        {{ slotProps.hobbyData.fruit }}
      </template>
  </myslot>
</template>

<script>
  import myslot from './myslot';
  export default {
    components: {
      myslot
    }
</script>
<style>
</style>

针对多个插槽的情况,在写法上可以解构插槽prop,父组件的写法如下

<template>
  <myslot>
      <template v-slot:header="{userData}">
        {{ userData.firstName }}
      </template>
      <template v-slot:footer="{hobbyData}">
        {{ hobbyData.fruit }}
      </template>
  </myslot>
</template>

<script>
  import myslot from './myslot';
  export default {
    components: {
      myslot
    }
  }
</script>
<style>
</style>

在具名插槽的介绍部分有讲过,具名插槽可以使用缩写,v-slot可以使用#来代替,所以以上代码可以写成:

<template>
  <myslot>
      <template #header="{userData}">
        {{ userData.firstName }}
      </template>
      <template #footer="{hobbyData}">
        {{ hobbyData.fruit }}
      </template>
  </myslot>
</template>

<script>
  import myslot from './myslot';
  export default {
    components: {
      myslot
    }
  }
</script>
<style>
</style>

但是需要注意的是该缩写只在其有参数的时候才可用。这意味着以下语法是无效的:

<!-- 这样会触发警告 -->
<template>
  <myslot>
      <template #="{userData}">
        {{ userData.firstName }}
      </template>
      <template #="{hobbyData}">
        {{ hobbyData.fruit }}
      </template>
  </myslot>
</template>
Logo

前往低代码交流专区

更多推荐