插槽详解

本文详细介绍了Vue.js中的插槽机制,包括插槽的概念、使用方式、后备内容、具名插槽、作用域插槽、动态插槽名、具名插槽的缩写以及其他示例。插槽允许父组件向子组件注入内容,实现组件的灵活组合。通过v-slot统一了之前的slot和slot-scope,同时支持具名插槽和作用域插槽,提升了组件的复用性和可定制性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

插槽详解

在 2.6.0 版本之后,slot 以及 slot-scope 由 v-slot 统一替代,但依然未被移除。

1. 什么是插槽

插槽是 vue.js 开发员人根据从 Web Components 规范草案中获取的灵感,设计的一套 API,这套 API 允许我们对组件进行组合。

插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。

类似于 React.js 中的组合(children prop),插槽允许将一些其他的组件作为子组件传递给指定组件。

2. 如何使用

比如下面的代码:

在子组件中:

<template>
	<div>
        <h1>
  			插槽的使用
    	</h1>
        <slot></slot>
    </div>
</template>
<script>
export default{
    name: 'child'
}
</script>

在父组件中:

<template>
	<div>
     	<div>
            使用插槽分发内容
    	</div>
        <Child>
    		<div>
                这里的 div 替代了 slot 标签。
    		</div>
    	</Child>
    </div>
</template>
<script>
import Child from './components/Child';
export default {
    name: 'Father',
}
</script>

这样,就会出现:

在这里插入图片描述

如果,在子组件中,去除 <slot></slot>,那么则不会出现 这里的 div 替代了 slot 标签

总结:如果子组件没有使用插槽,父组件如果需要往子组件中填充模板或html,是无法做到的。

但是,使用插槽需要注意作用域,子模板里的所有内容都是在子作用域中编译的。父级模板里的所有内容都是在父级作用域中编译的。

比如,还是上面的例子,如果我们这样使用,在父组件中,有一个 props:

<template>
	<div>
     	<div>
            使用插槽分发内容
    	</div>
        <child>
    		<div>
                这里的 div 替代了 slot 标签。
    		</div>
    	</child>
    </div>
</template>
<script>
import child from './components/Child';
export default {
    name: 'Father',
    props: ['name'],
}
</script>

在 App.vue 中导入 Father 组件:

<template>
  <div id="app">
	<Father name="father" />
  </div>
</template>

<script>
import Father from '@/components/Father';
export default {
  name: 'App',
  components: {
    Father,
  }
}
</script>

<style scope>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  height: 100%;
}

</style>

那么,子组件 Child 是访问不到 name,这个 props 的。

3. 后备内容

后备内容,指挥在没有提供内容的时候被渲染。来看一下官网的例子:

<submit-button> 组件中:

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

如果在 <slot></slot> 标签中,填入 Submit 内容,那么,当父组件没有向其中添加其他内容的时候,会默认渲染 Submit

<html>

<head>
    <meta charset="utf-8">
    
### Vue.js 中的作用域插槽 #### 概念 作用域插槽Vue.js 提供的一种特殊类型的插槽,允许父组件访问子组件的数据并自定义其显示方式。通过这种方式,可以更灵活地控制子组件内部的内容呈现[^2]。 #### 使用方法 要创建一个具有作用域插槽的子组件,在该组件模板内需指定 `<slot>` 元素,并为其设置 `scope` 属性(在较新版本中已改为 `v-slot`)。此属性接收的对象包含了希望暴露给父级使用的变量或数据项。对于父组件而言,则是在调用子组件时利用具名插槽语法传入相应内容的同时获取这些被共享出来的值作为局部变量来使用[^3]。 #### 详细解释 当涉及到复杂场景下不同页面布局的需求变化时,例如展示编程语言列表既可以按照行排列也可以按照列罗列出来;此时如果单纯依靠常规插槽可能无法满足多样化的要求。而借助于带有参数传递功能的作用域插槽则能够很好地解决这个问题——即让子组件负责准备所需的信息集合,由外部决定具体怎样去展现它们[^5]。 #### 示例代码 下面是一个简单的例子展示了如何在一个名为 `ChildComponent` 的子组件里定义好可供外界读取的语言数组资源并通过作用域插槽将其开放出去;与此同时,在另一个地方实例化这个类别的时候可以根据实际需要选择不同的表现形式: ```html <!-- ChildComponent.vue --> <template> <div class="child"> <!-- 定义带作用域的默认插槽 --> <slot :languages="pLanguages"></slot> </div> </template> <script> export default { data() { return { pLanguages: ['Java', 'C++', 'JavaScript', 'Python', 'C语言', 'Go', 'C#'] } } } </script> ``` ```html <!-- ParentComponent.vue --> <template> <div id="app"> <!-- 使用作用域插槽,以表格形式展示 --> <h3>水平方向展示:</h3> <ChildComponent v-slot="{ languages }"> <ul style="display:flex;"> <li v-for="(lang, index) in languages" :key="index">{{ lang }}</li> </ul> </ChildComponent> <!-- 使用作用域插槽,以列表形式展示 --> <h3>垂直列表展示:</h3> <ChildComponent v-slot="{ languages }"> <ol> <li v-for="(lang, index) in languages" :key="index">{{ lang }}</li> </ol> </ChildComponent> <!-- 直接输出原始数组 --> <h3>数组形式展示:</h3> <pre>{{ JSON.stringify(pLanguagesFromSlot, null, 2) }}</pre> <!-- 将上述三种情况封装成单独的方法以便重复利用 --> <button @click="changeDisplayType('horizontal')">切换为横向显示</button> <button @click="changeDisplayType('vertical')">切换为纵向显示</button> <button @click="changeDisplayType('array')">查看原生数组</button> </div> </template> <script> import ChildComponent from './components/ChildComponent'; export default { components: { ChildComponent }, methods: { changeDisplayType(type){ this.displayType = type; } }, computed:{ displayContent(){ switch(this.displayType){ case "horizontal": return ( <ChildComponent scopedSlots={{ default(props){return (<ul style="display:flex;"><li>{props.languages}</li></ul>)} }}/> ); case "vertical": return( <ChildComponent scopedSlots={{ default(props){return(<ol><li>{props.languages}</li></ol>)} }}/> ); case "array": return this.pLanguages; default: break; } } } }; </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值