vue中slot插槽

简介: vue中slot插槽

Be weird. Your strangeness is your magic.

我们在进行vue开发中,经常会使用到slot插槽

插槽允许我们在父组件引用子组件时,在组件其中放一段可以带标签的元素,甚至放入其他组件等

例如我这里定义一个组件

<template>
  <div>
    <header><slot name="header" :user="user">-------</slot></header>
    <main><slot :user="user">默认内容</slot></main>
    <footer><slot name="footer" :user="user">-------</slot></footer>
  </div>
</template>
<script>
export default {
  data() {
    return {
      user: {
        name: 'ruben'
      }
    };
  }
};
</script>

其中包含三个外部标签headermainfooter

我们在父页面外部引用时就可以这么写:

<navigation-link>
  <template v-slot:header>
    ----传入头部----
  </template>
  <template v-slot:default="slotProps">
    插槽{{ slotProps.user.name }}
  </template>
  <template v-slot:footer>
    ----传入底部----
  </template>
</navigation-link>

这样我们template标签内的内容会根据v-slot指定的插槽名自动匹配上面的name

注意,我这里使用的是新版api,旧版已被废弃,但仍然可使用,感兴趣可以看官方文档

最后渲染出来的效果:

当然这里我每个插槽在组件内定义时都写了默认值,这样就算我们没有传入,也可以使用默认值

这里我们可能还会有一个需求,我们想访问子组件内部的值怎么办?因为我们从父页面传给子组件的插槽的模板引用到的作用域是外部,也就是我们父页面的,此时大家注意到我定义组件时,绑定了一个user标签,指向我们子组件内部的值user

这样,我们在外部使用时就可以像我上方那样,使用v-slot设置一个属性变量,通过它就能访问到子组件内部的值

当你会用这个了之后你还可以使用ES6中变量的解构赋值,省掉我们上面定义slotProps变量这一步骤

而且:default也是可以省略的

这里可以看到我传入的template标签很繁重,其实如果我们只给默认的slot传模板的话,可以简写为下方形式:

1
2
<!-- 缩写形式 只能在只有一个slot下使用,如有多个,则需要写全 -->
<navigation-link v-slot:header="{ user: person }">缩写{{ person.name }}</navigation-link>

注意上方我还将user进行了重命名为person

vue官方文档还提到可以使用如下语法设置备选值,用于在userundefined的时候,但我发现我引入这段代码会编译报错,暂时不是很想去探究,有可能是我的版本问题吧

<navigation-link v-slot="{ user = { name: 'Guest' } }">备用值{{ user.name }}</navigation-link>

我们在写插槽名的时候,其实可以使用动态插槽名如下,并且v-slot在指定插槽名的时候也可以进行简写为#

<navigation-link #[dynamicSlotName]="{ user }">动态插槽{{ user.name }}</navigation-link>

这里dynamicSlotName在下方定义如下:

最后完整代码如下:

<template>
  <div>
    <div :class="[{ active: active }, isButton ? prefix + '-button' : null]">:class="[{ active: active }, isButton ? prefix + '-button' : null]"</div>
    <div :class="{ active, [`${prefix}-button`]: isButton }">:class="{ active, [`${prefix}-button`]: isButton }"</div>
    <hello-world msg="Hello World"></hello-world>
    <div v-html="'<div class=\'ruben-html\'>我是富文本</div>'"></div>
    <navigation-link>
      <template v-slot:header>
        ----传入头部----
      </template>
      <template v-slot:default="slotProps">
        插槽{{ slotProps.user.name }}
      </template>
      <template v-slot:footer>
        ----传入底部----
      </template>
    </navigation-link>
    <navigation-link>
      <template v-slot="{ user }">
        解构{{ user.name }}
      </template>
    </navigation-link>
    <!-- 缩写形式 只能在只有一个slot下使用,如有多个,则需要写全 -->
    <navigation-link v-slot:header="{ user: person }">缩写{{ person.name }}</navigation-link>
    <!-- <navigation-link v-slot="{ user = { name: 'Guest' } }">备用值{{ user.name }}</navigation-link> -->
    <navigation-link #[dynamicSlotName]="{ user }">动态插槽{{ user.name }}</navigation-link>
  </div>
</template>
<script>
import HelloWorld from '@/components/HelloWorld.vue';
import NavigationLink from '@/components/navigation-link.vue';
export default {
  components: { HelloWorld, NavigationLink },
  data() {
    return {
      active: true,
      isButton: true,
      prefix: 'ruben',
      dynamicSlotName: 'footer'
    };
  }
};
</script>
<style scoped>
.hello {
  text-align: center;
}
>>> .hello-ruben {
  color: #f06431;
}
.hello /deep/ a {
  color: #0000ee;
}
>>> .ruben-html {
  color: #ff0000;
}
</style>
相关文章
|
1天前
|
JavaScript 前端开发
Vue,如何引入样式文件
Vue,如何引入样式文件
|
1天前
|
JavaScript
|
1天前
|
JavaScript
|
1天前
|
JavaScript
Vue搭配ELEMENT之后,右侧点击栏点击跳转到空白页解决方法
Vue搭配ELEMENT之后,右侧点击栏点击跳转到空白页解决方法
|
1天前
|
JavaScript
vue : 无法将“vue”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保 路径正确,然后再试一次。
vue : 无法将“vue”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保 路径正确,然后再试一次。
|
9月前
|
JavaScript API
Vue | Vuejs 组件化 - 插槽Slot/非父子通信
Vue | Vuejs 组件化 - 插槽Slot/非父子通信
|
10月前
|
JavaScript
Vue插槽 slot 标签
Vue插槽 slot 标签
103 0
|
1月前
|
JavaScript
VUE组件: 请解释Vue的插槽(slot)是什么?
VUE组件: 请解释Vue的插槽(slot)是什么?
31 1
|
7月前
|
JavaScript 前端开发
Vue系列教程(14)- 插槽(slot)
Vue系列教程(14)- 插槽(slot)
40 0
|
11月前
|
JavaScript 前端开发
Vue之插槽Slot理解
Vue之插槽Slot理解
70 0