slot插槽
当组件中某一项需要单独定义,那么就应该使用solt
Vue 实现了一套内容分发的 API,将
<slot>
元素作为承载分发内容的出口。
单个slot(匿名插槽)
除非子组件模板包含至少一个
<slot>
插口,否则父组件的内容将会被丢弃 ,当子组件模板只有一个没有属性的 slot 时,父组件整个内容片段将插入到 slot 所在的 DOM 位置,并替换掉 slot 标签本身。
- 如果希望, 能够让组件中的部分, 使用时进行定制, 需要用到插槽
- 默认, 如果组件使用时, 组件标签中添加的内容, 不进行处理, 将被忽略
- slot 插槽, 作用: 分发内容
- 在组件使用时, 添加的内容, 将来会被分发到 slot 标签的位置去, 可以实现组件的定制
在组件的模版中定义slot
插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<style>
.com1 {
width: 300px;
padding: 20px;
border-radius: 10px;
background-color: salmon;
border: 2px solid black;
}
</style>
</head>
<body>
<div id="app">
<com1>
<p>发生未知错误,是否继续??</p>
</com1>
<com1>
<p>你确认要退出系统么??</p>
</com1>
</div>
<script src="./lib/vue@2.6.10.js"></script>
<script>
// 没有给<slot></slot>加name属性的插槽
Vue.component('com1', {
template: `
<div class="com1">
<h3>警告</h3>
<slot></slot>
<button>是</button>
<button>否</button>
</div>
`
})
const vm = new Vue({
el: '#app',
data: {}
})
</script>
</body>
</html>
具名插槽
如果一个组件中想使用多个slot那么此时就应该使用具名slot。
具名插槽: 配置了名字的插槽, 可以实现定向分发, 只接受指定的内容
- 给插槽起一个名字
<slot name="header"></slot>
- 用 template 标签, 将需要分发的内容进行包裹,通过设置 v-slot:插槽名, 实现分发到指定的插槽
Vue.component("modal", {
template: `
<div class="modal">
<slot name="header"></slot>
<slot name="content"></slot>
<slot name="footer"></slot>
</div>
`,
});
<!-- 模态框 -->
<modal>
<template v-slot:header>
<h3>警告</h3>
</template>
<template v-slot:content>
<p>你确认要退出系统么??</p>
</template>
<template v-slot:footer>
<button>删除</button>
<button>取消</button>
</template>
<template v-slot:default>
<p>测试的内容</p>
</template>
</modal>
<modal>
<template v-slot:header>
<h3>温馨提示</h3>
</template>
<template v-slot:content>
<h4>嘎嘎, 你确认要删除内容么??</h4>
</template>
<template v-slot:footer>
<button>是</button>
<button>否</button>
</template>
</modal>
.modal {
width: 400px;
background-color: pink;
border: 3px solid #000;
border-radius: 20px;
margin-bottom: 10px;
padding: 20px;
}
Vue.component('modal', {
template: `
<div class="modal">
<div class="header">
<slot name="header"></slot>
</div>
<div class="content">
<slot name="content"></slot>
</div>
<div class="footer">
<slot name="footer"></slot>
</div>
<slot name="default"></slot>
</div>
`
})
const vm = new Vue({
el: '#app',
data: {
msg: 'hello vue'
}
})
作用域插槽
如果在分发内容时, 需要用到子组件中的数据, 此时就可以用到作用域插槽
- 给 slot 添加自定义属性的方式, 传值
- 添加的自定义属性, 会以属性的方式添加到一个对象中去
{ money: 100, desc: ‘王校长’, yes: ‘是’, no: ‘否’ } - 在template中, 可以通过 = 进行接收传递的值
插槽也可以带有数据
Vue.component('modal', {
template: `
<div>
<h3><slot name="title"></slot></h3>
<p><slot name="content"></slot></p>
<slot name="confirm" value="确定"></slot>
</div>
`
})
作用域插槽的使用
<!-- 模态框 -->
<modal>
<template v-slot:header>
<h3>警告</h3>
</template>
<template v-slot:content>
<p>你确认要退出系统么??</p>
</template>
<template v-slot:footer="scoped">
<!--此时scoped是一个对象,由<slot name="footer" money="100" desc="王校长" :yes="yes" :no="no"></slot>标签传值,长这样:{money: '100', desc: '王校长', yes: '是', no: '否'},你也可以对scope进行解构-->
<!-- {{ scoped }} -->
<button>{{ scoped.yes }}</button>
<button>{{ scoped.no }}</button>
</template>
<!-- 虽然, 不加 template 包裹, 也能分发给 匿名插槽, 但是如果有额外的参数需要接收,
就必须用 template 包裹了 -->
<template v-slot:default="obj">
<p>测试的内容 {{ obj.house }} - {{ obj.car }}</p>
</template>
</modal>
.modal {
width: 400px;
background-color: pink;
border: 3px solid #000;
border-radius: 20px;
margin-bottom: 10px;
padding: 20px;
}
Vue.component('modal', {
template: `
<div class="modal">
<div class="header">
<slot name="header"></slot>
</div>
<div class="content">
<slot name="content"></slot>
</div>
<div class="footer">
<slot name="footer" money="100" desc="王校长" :yes="yes" :no="no"></slot>
</div>
<slot name="default" house="大房子" car="宝马车"></slot>
</div>
`,
data () {
return {
yes: '是',
no: '否'
}
}
})
const vm = new Vue({
el: '#app',
data: {
msg: 'hello vue'
}
})