📝个人主页:五敷有你
🔥系列专栏:Vue
⛺️稳中求进,晒太阳
插槽
作用:让组件内部一些 结构 支持 自定义
插槽的分类:
- 默认插槽。
- 具名插槽。
基础语法
组件内需要定制的结构部分,改用占位
<template>
<div class="main">
<h2>确认吗</h2>
<slot></slot>
<div class="bottom">
<button>确认</button><button>取消</button>
</div>
</div>
</template>
使用组件时,标签内部,传入结构替换slot
<BaseA>我是插槽练习</BaseA>
插槽的默认值
通过插槽完成内容的定制,传什么显示什么,但是不传,则是空白
插槽的后备内容:封装组件时,可以为预留的插槽提供后备内容(默认内容)
- 语法:在slot标签内,放置内容,作为默认显示内容
- 效果:
- 外部使用组件不传东西,则slot会显示后备内容
- 外部使用组件传东西了,则slot整体会被替换掉
具名插槽(一个组件有多处结构需要外部传入标签,进行定制)
语法:
多个slot使用name属性区分名字
简写:v-slot:插槽名 简化---- #插槽名
<div class="main">
<h2>
<slot name="head"></slot>
</h2>
<slot name="body">我是默认值</slot>
<div class="bottom">
<slot name="foot"></slot>
</div>
</div>
template配置v-slot:名字 来分发对应标签
<BaseA>
<template v-slot:head>
我是标题
</template>
<template v-slot:body>
<p>我是身体</p>
</template>
<template v-slot:foot>
<button>确认</button><button>取消</button>
</template>
</BaseA>
作用域插槽
作用域插槽:定义slot插槽的同时,是可以传值的,给插槽上 可以绑定数据, 将来 使用组件时可以用
场景:封装表格组件
基本使用步骤:
1. 给slot标签,以添加属性的方式传值。
<slot :id="item.id" msg="测试文本"></slot>
2. 所有添加属性,都会收集到一个对象中
{id:3,msg:"测试文本"}
3. 在template中,通过 #插槽名='obj'接收,默认插槽名为 default
<MyTable :list="list">
<template #default="obj">
<button @click="del(obj.id)">删除</button>
</template>
</MyTable>
商品列表(实战):
App.vue
<template>
<div id="app">
<MyTable :list="list">
<template #thead>
<td>编号</td>
<td>图片</td>
<td>名称</td>
<td>标签</td>
</template>
<template #tbody="{item,index}" >
<td>{{ index+1 }}</td>
<td>{{ item.img }}</td>
<td>{{ item.name }}</td>
<td><MyEle v-model="item.sign"></MyEle></td>
</template>
</MyTable>
</div>
</template>
<script>
import MyEle from "./components/MyEle.vue"
import MyTable from "./components/MyTable.vue"
export default {
data(){
return{
list:[
{id:101,img:'001',name:"紫砂壶",sign:"茶具"},
{id:102,img:'001',name:"皮鞋",sign:"男鞋"},
{id:103,img:'001',name:"棉衣",sign:"衣服"},
{id:104,img:'001',name:"毛衣",sign:"衣服"},
{id:105,img:'001',name:"帽子",sign:"衣服"}
]
}
},
components:{
MyEle,
MyTable
},
methods:{
},
//局部注册指令
directives:{
//指令名:指令配置项
color:{
inserted(el,binding){
el.style.color=binding.value
},
update(el,binding){
el.style.color=binding.value
}
}
},
}
</script>
<style scoped>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
margin-top: 60px;
display: flex;
justify-content: space-around;
}
</style>
MyTable.vue
<template>
<div class="main">
<table border="1">
<thead>
<tr>
<!-- <td>编号</td>
<td>图片</td>
<td>名称</td>
<td>标签</td> -->
<slot name="thead">
</slot>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in list" :key="item.id">
<slot name="tbody" :item="item" :index="index" ></slot>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
props:{
"list":Array,
}
}
</script>
<style scoped>
</style>
Mytag.vue
<template>
<div class="main">
<div class="ele" v-if="isShow" @click="isShow=false">
{{ value }}
</div>
<div v-else>
<input type="text" :value="value" v-focus @keyup.enter='update'>
</div>
</div>
</template>
<script>
export default {
props:{
"value":String
},
data(){
return {
isShow:true,
}
},
directives:{
focus:{
inserted(el){
el.focus()
}
}
},
methods:{
update(e){
this.$emit("input",e.target.value)
this.isShow=true
}
}
}
</script>
<style scoped>
.ele{
text-align: center;
color:rgb(50, 49, 49);
font-size: 15px;
}
input{
padding: 3px 4px;
color:gray;
font-size: 13px;
}
</style>