Vue:插槽(slot、slot-scope、v-slot)

本文围绕Vue插槽展开,强调其重要性与实用性,可整合重复代码、统一样式。详细介绍了slot指定具名插槽名,slot-scope用于传递参数,v-slot是2.6.0版本引入的统一语法,能替代前两者。最后以element UI为例进行了封装分页查询的实例演示。

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

前言

最近复习Vue时发现插槽真的很重要、很有用。以前竟然没怎重视😅。使用插槽,可以将重复性的代码进行整合,可以将样式进行统一。
打个比方:elementUI中的表格和分页条经常搭配在一起使用,分页条这部分代码其实一直在重复。我们可以将这部分进行封装,然后在插槽中写表格的部分(这部分的代码会写在后面)
复习时发现插槽这部分有slotslot-scopev-slot 这三个东西真的很懵逼,然后只能看官方文档和其他博客进行分析。

slot

slot实际上就是用于指定具名插槽的名

实例1、

//全局组件Test 
Vue.component('test', {
	template: `
	  <div>
	    <slot>默认信息</slot>
	  </div>
	`
})
//使用,插槽内务内容
<test></test>
//插槽内有内容
<test>111<test>

在这里插入图片描述
在这里插入图片描述
当插槽内没有内容时会显示默认信息(当然你已经指定了默认内容),当插槽内有值时,插槽内的值会替换默认内容

现在还是没有用的slot,不是没用到而是对于默认的插槽,slot可以省略。上面的也可以写成下面的形式:

<test>  
    <div slot="default">111</div>
 </test>

实例2、

当给插槽起一个别名时,slot是不能够再省略的。通过不同的名字,会将不同的内容放在不同的位置。

//全局组件Test 
Vue.component('test', {
	template: `
	  <div>
	    <slot name="footer"></slot>
	    <slot name="header"></slot>
		<slot name="default"></slot>
	  </div>
	`
})

//使用
<test>
	<div slot="header">我是头</div>
	<div slot="footer">我是尾</div>
	<div slot="default">我是默认</div>
</test>

在这里插入图片描述
1、内容显示的位置取决于你定义的插槽的位置
2、对于未指定名称的内容,默认都是默认插槽(就是在默认插槽里显示)

slot-scope

上面的具名插槽只能显示内容,如果想要传递参数呢?那只能使用slot-scope

实例1、

<body>
	<div id="app">
		<test>
			<div slot-scope="scope">
				{{scope.info}}
			</div>
		</test>
	</div>

</body>

<script type="text/javascript">
	//全局组件Test 
	Vue.component('test', {
		template: `
		  <div>
			<slot  :info="msg"></slot>
		  </div>
		`,
		data() {
			return {
				msg: "111"
			}
		}
	})
	new Vue({
		el: '#app',
		data: {
		}
	})
</script>

在这里插入图片描述
实例2、

如果即想要指定名称又想要传参呢?slotslot-scope 都需要使用

<body>
	<div id="app">
		<test>
			<div slot="age" slot-scope="scope">{{scope.msg.name}}</div>
		</test>
	</div>

</body>

<script type="text/javascript">
	//全局组件Test 
	Vue.component('test', {
		template: `
		  <div>
		    <slot name="age" :msg="info"></slot>
		  </div>
	`,
		data() {
			return {
				info: {
					age: 2,
					name: 'ddsfd'
				}
			}
		}
	})
	new Vue({
		el: '#app',
	})
</script>

v-slot

在 2.6.0 中,官方为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。它取代了 slot 和 slot-scope,就是通过v-slot可以干slot和slot-scope两个的工作。

这里有个说明。使用v-slot后,v-slot不能再写在div上了,需要统一写在template中

实例1、只起slot的作用

<body>
<div id="app">
	<test>
		<template v-slot:name>
			dddd
		</template>
	</test>
</div>

</body>

<script type="text/javascript">
//全局组件Test 
Vue.component('test', {
	template: `
	  <div>
		<slot name="name"></slot>
	  </div>
	`
})
new Vue({
	el: '#app',
	data: {
		info: {
			name: '111',
			age: 5
		}
	}
})
</script>

注:
1、v-slot只在2.6版本及以上可以生效,最初用了2.2版本,没效果还以为出错了呢。
2、v-slot可以简写为#,例如:

<test>
	<template #name>
		dddd
	</template>
</test>

实例2、只起slot-scope的作用

<body>
	<div id="app">
		<test>
			<template v-slot="scope">
				{{scope.info}}
			</template>
		</test>
	</div>

</body>

<script type="text/javascript">
	//全局组件Test 
	Vue.component('test', {
		template: `
		  <div>
			<slot :info="msg"></slot>
		  </div>
		`,
		data() {
			return {
				msg: "你好"
			}
		}
	})
	new Vue({
		el: '#app',
		data: {
		}
	})
</script>

实例3:起两者的作用

<body>
<div id="app">
	<test>
		<template #msg="scope">
			{{scope.info}}
		</template>
	</test>
</div>

</body>

<script type="text/javascript">
//全局组件Test 
Vue.component('test', {
	template: `
	  <div>
		<slot name="msg" :info="msg"></slot>
	  </div>
	`,
	data() {
		return {
			msg: "你好"
		}
	}
})
new Vue({
	el: '#app',
	data: {
	}
})
</script>

实例

实例以element UI为基础

封装分页查询


<template>
    <div :style="tableStyle">
        <!-- 页面标题 -->
        <div class="item__title">{{ title }}</div>
        <!-- table表格内容 -->
        <slot name="table" :tableData="tableData"></slot>
        <!-- 分页条 -->
        <el-pagination :small="isSmall" background layout="prev, pager, next, sizes, total, jumper" :page-sizes="[20, 30, 50]" :page-size="tableData.pageSize"
                       :total="tableData.pageNumberAll" :current-page="tableData.pageNumber" @size-change="handleSizeChange" @current-change="page">
        </el-pagination>
    </div>
</template>

<script>

export default {
    components: {},
    props: {
        title: {
            type: String,
            default: ''
        },
        url: {
            type: String,
            default: '',
            required: true
        },
        params: {
            type: Object,
            default: () => {}
        },
        init: {
            type: Boolean,
            default: false,
            required: true
        },
        tableStyle: {
            type: Array,
            default: () => {}
        },
        isSmall: {
            type: Boolean,
            default: false
        }
    },
    data() {
        // 这里存放数据
        return {
            // 表格数据
            tableData: {
                tableInfo: [],
                loading: false,
                pageSize: 20,
                pageNumber: 1,
                pageNumberAll: 0
            }
        };
    },
    watch: {
        init(val) {
            if(val) {
                this.getTableInfo();
            }
        }
    },
    mounted() {
        this.getTableInfo();
    },
    // 方法集合
    methods: {
        // 主表格分页点击事件
        page(page) {
            this.tableData.pageNumber = page;
            this.getTableInfo(); // 更新
        },
        // 主表格调整每页显示条数
        handleSizeChange(val) {
            this.tableData.pageSize = val;
            this.getTableInfo();
        },
        // 获取表格数据
        getTableInfo() {
            let querys = {
                pageSize: this.tableData.pageSize,
                pageNumber: this.tableData.pageNumber,
                ...this.params
            };
            this.tableData.loading = true;
            this.$http.post(this.url,querys).then(({data: d}) => {
                if(d.code == 0) {
                    this.tableData.loading = false;
                    this.tableData.tableInfo = d.data.records;
                    this.tableData.pageNumberAll = d.data.total;
                }
            });
        }
    }
};
</script>
<style lang="scss" scoped>

</style>

使用

  <h-table title="售后核销分析" :init="true" :url="url" is-small :table-style="{height:'50%',width:'500px'}">
      <template #table="scope">
          <!-- {{ scope }} -->
          <el-table ref="tableDemo" v-loading="scope.tableData.tabloading" :data="scope.tableData.tableInfo" style="width: 100%" height="calc(100% - 150px)" border :row-key="row => row.id">
              <el-table-column type="selection" width="55" align="center" reserve-selection fixed></el-table-column>
              <el-table-column type="index" width="55" label="序号" fixed align="center"></el-table-column>
              <el-table-column label="创建日期" prop="gmtCreate" align="center" show-overflow-tooltip min-width="120">
                  <template v-slot:header>
                      <ever-table-header prop="gmtCreate" label="创建日期" type="date" @filtrate="filtrate"></ever-table-header>
                  </template>
              </el-table-column>
          </el-table>
      </template>
  </h-table>
  <h-table title="售后核销分析" :init="true" :url="url" :table-style="{height:'50%'}">
      <template #table="scope">
          <!-- {{ scope }} -->
          <el-table ref="tableDemo" v-loading="scope.tableData.tabloading" :data="scope.tableData.tableInfo" style="width: 100%" height="calc(100% - 150px)" border :row-key="row => row.id">
              <el-table-column type="selection" width="55" align="center" reserve-selection fixed></el-table-column>
              <el-table-column type="index" width="55" label="序号" fixed align="center"></el-table-column>
              <el-table-column label="创建日期" prop="gmtCreate" align="center" show-overflow-tooltip min-width="120">
                  <template v-slot:header>
                      <ever-table-header prop="gmtCreate" label="创建日期" type="date" @filtrate="filtrate"></ever-table-header>
                  </template>
              </el-table-column>
          </el-table>
      </template>
  </h-table>

效果

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无知的小菜鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值