派大星

vuePress-theme-reco 派大星    2021 - 2022
派大星 派大星
主页
博客
  • 前端
  • JavaScript文章
  • 三级目录
  • 笔记
  • 学习笔记
  • 页面
  • CSS
  • HTML
  • 技术
  • 技术文档
  • GitHub技巧
  • 技术笔记
  • 实用工具
  • Nodejs
  • 博客搭建
  • 更多
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • JavaScript
  • 浏览器&网络
  • 前端框架
  • 资源工具
  • 持续集成
  • 小程序
  • 杂谈
  • React
  • Mysql
  • 面试题
  • uniapp
  • 《ES6 教程》笔记
  • 《Git》学习笔记
  • 《JavaScript教程》笔记
  • 《React》笔记
  • 核心概念
  • 高级指引
  • Hook
  • 案例演示
  • 《TypeScript 从零实现 axios》
  • 初识 TypeScript
  • TypeScript 常用语法
  • ts-axios 项目初始化
  • ts-axios 基础功能实现
  • ts-axios 异常情况处理
  • ts-axios 接口扩展
  • ts-axios 拦截器实现
  • ts-axios 配置化实现
  • ts-axios 取消功能实现
  • ts-axios 更多功能实现
  • ts-axios 单元测试
  • ts-axios 部署与发布
  • 《Vue》笔记
  • 基础
  • 组件
  • 过渡&动画
  • 工具
  • 规模化
  • 可复用性&组合
  • 其他
  • Vuex
标签
时间轴
关于
author-avatar

派大星

272

文章

69

标签

主页
博客
  • 前端
  • JavaScript文章
  • 三级目录
  • 笔记
  • 学习笔记
  • 页面
  • CSS
  • HTML
  • 技术
  • 技术文档
  • GitHub技巧
  • 技术笔记
  • 实用工具
  • Nodejs
  • 博客搭建
  • 更多
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • JavaScript
  • 浏览器&网络
  • 前端框架
  • 资源工具
  • 持续集成
  • 小程序
  • 杂谈
  • React
  • Mysql
  • 面试题
  • uniapp
  • 《ES6 教程》笔记
  • 《Git》学习笔记
  • 《JavaScript教程》笔记
  • 《React》笔记
  • 核心概念
  • 高级指引
  • Hook
  • 案例演示
  • 《TypeScript 从零实现 axios》
  • 初识 TypeScript
  • TypeScript 常用语法
  • ts-axios 项目初始化
  • ts-axios 基础功能实现
  • ts-axios 异常情况处理
  • ts-axios 接口扩展
  • ts-axios 拦截器实现
  • ts-axios 配置化实现
  • ts-axios 取消功能实现
  • ts-axios 更多功能实现
  • ts-axios 单元测试
  • ts-axios 部署与发布
  • 《Vue》笔记
  • 基础
  • 组件
  • 过渡&动画
  • 工具
  • 规模化
  • 可复用性&组合
  • 其他
  • Vuex
标签
时间轴
关于

插槽slot

vuePress-theme-reco 派大星    2021 - 2022

插槽slot

{ "name": "xugaoyi", "link": "https://github.com/xugaoyi" } 2020-02-16 11:46:27 Vue

# 插槽slot

API (opens new window)

# 插槽

<div id="root">
    <child> <!-- 组件标签 -->
        <h1>hello</h1>
    </child>
</div>

<script type="text/javascript">
    Vue.component('child', { // 子组件
        template: '<div><slot></slot></div>'
    })

    var vm = new Vue({
        el: '#root'
    })
</script>

上面代码中,组件标签内的h1是要插入子组件内部的元素,子组件内使用slot标签接收父组件插入的h1标签。

# 默认值

Vue.component('child', {
    template: '<div><slot>默认值</slot></div>'
})

子组件slot标签内可以添加默认值,它只会在父组件没有传入内容的时候被渲染。

# 具名插槽

自 2.6.0 起有所更新。使用 slot attribute 的语法已废弃。

<div id="root">
    <child>
        <div slot="header">header</div> <!--旧语法 使用template标签或其他标签都可以-->
        <div slot="footer">footer</div>
    </child>
</div>

<script type="text/javascript">
    Vue.component('child', {
        template: `<div>
                        <slot name="header"></slot>
                        <div>content</div>
                        <slot name="footer"></slot>
                    </div>`
    })

    var vm = new Vue({
        el: '#root'
    })
</script>

上面代码中,组件标签内有两个元素,分别添加了slot属性赋予不同的值,子组件内分别有两个slot插槽,添加了对应的name属性,用于分别接收父组件传入的内容。

自 2.6.0 起,使用v-slot指令代替slot attribute 的语法。

<div id="root">
    <child>
        <template v-slot:header> <!--新语法 只能使用template标签-->
            <h1>标题</h1>
        </template>
        <p>内容</p>
        <template v-slot:footer>
            <p>页脚</p>
        </template>
    </child>
</div>
<script type="text/javascript">
	Vue.component('child', {
		template: `<div>
						<header>
						   <slot name="header"></slot>
						</header>
						<main>
						  <slot></slot>
						</main>
						<footer>
						  <slot name="footer"></slot>
						</footer>
					</div>`
	})

    var vm = new Vue({
        el: '#root'
    })
</script>

自2.6.0版本起,具名插槽由原来的slot标签属性改为v-slot指令,例v-slot:header。子组件内仍然是在slot插槽标签添加name属性用于分别接收内容。未具名的插槽接收未使用v-slot指定的内容。

另外,具名插槽同样可以使用默认值。

注意 v-slot 只能添加在 <template 上 (只有一种例外情况 (opens new window)),这一点和已经废弃的 slotattribute (opens new window)不同。

# 作用域插槽

自 2.6.0 起有所更新。使用 slot-scope attribute 的语法已废弃。

<div id="root">
    <child>
        <template slot-scope="dataObj"> <!--可使用其他标签,但注意其他标签将会被带到插槽里面-->
            <li>{{dataObj.dataItem}}</li>
        </template>
    </child>
</div>
<script type="text/javascript">
	Vue.component('child', {
        data(){
            return {
                list: [1, 2, 3, 4]
            }
        },
        template: `<div>
						<ul>
							<slot
								v-for="item of list"
								:dataItem=item
							>
							</slot>
						</ul>
					  </div>`
    })

    var vm = new Vue({
        el: '#root'
    })
</script>

上面代码中,组件标签内需要使用template标签并且设置slot-scope属性 用于接收子组件内传递的值,template标签内的li标签是传入插槽的元素,dataObj.dataItem数据由子组件内提供。子组件内通过v-for循环插入父组件提供的li标签,并且通过:dataItem=item把每个item数据传递出去。

子组件提供数据,父组件中接收数据,可以对数据处理并插入到元素,然后把元素放入子组件插槽。

# 作用:

数据由子组件提供,但渲染什么元素由父组件决定,并且可以对数据做二次处理。

自 2.6.0 起。使用v-slot代替 slot-scope attribute 的语法。

为了让 user 在父级的插槽内容中可用,我们可以将 user 作为 <slot> 元素的一个 attribute 绑定上去:

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

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

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

在这个例子中,我们选择将包含所有插槽 prop 的对象命名为 slotProps,但你也可以使用任意你喜欢的名字。

<div id="root">
    <child>
        <template v-slot:default="dataObj"> <!--default是默认具名,可省略。但有多个插槽时不能省略。-->
            <li>{{dataObj.dataItem}}</li>
        </template>
    </child>
</div>

<script type="text/javascript">
	Vue.component('child', {
        data(){
            return {
                list: [1, 2, 3, 4]
            }
        },
        template: `<div>
						<ul>
							<slot
								v-for="item of list"
								:dataItem=item
							>
							</slot>
						</ul>
					  </div>`
    })

    var vm = new Vue({
        el: '#root'
    })
</script>

# 具名插槽的缩写

跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header:

<base-layout>
  <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 some contact info</p>
  </template>
</base-layout>

然而,和其它指令一样,该缩写只在其有参数的时候才可用。这意味着以下语法是无效的:

<!-- 这样会触发一个警告 -->
<current-user #="{ user }">
  {{ user.firstName }}
</current-user>

如果你希望使用缩写的话,你必须始终以明确插槽名取而代之:

<current-user #default="{ user }">
  {{ user.firstName }}
</current-user>

# Demo

See the Pen 插槽slot by xugaoyi (@xugaoyi) on CodePen.