在使用组件时,我们常常要像这样组合它们:
<app>
<app-header></app-header>
<app-footer></app-footer>
</app>
单个插槽
假定 my-component 组件有如下模板:
<div>
<h2>我是子组件的标题</h2>
<slot>
只有在没有要分发的内容时才会显示。
</slot>
</div>
父组件模板
<div>
<h1>我是父组件的标题</h1>
<my-component>
<p>这是一些初始内容</p>
<p>这是更多的初始内容</p>
</my-component>
</div>
结果
<div>
<h1>我是父组件的标题</h1>
<div>
<h2>我是子组件的标题</h2>
<p>这是一些初始内容</p>
<p>这是更多的初始内容</p>
</div>
</div>
具名插槽
有时我们需要多个插槽。例如,假定我们有一个 app-layout 组件:
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
slot 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽:
父组件模板
<app-layout>
<h1 slot="header">这里可能是一个页面标题</h1>
<p>主要内容的一个段落。</p>
<p>另一个主要段落。</p>
<p slot="footer">这里有一些联系信息</p>
</app-layout>
结果为:
<div class="container">
<header>
<h1>这里可能是一个页面标题</h1>
</header>
<main>
<p>主要内容的一个段落。</p>
<p>另一个主要段落。</p>
</main>
<footer>
<p>这里有一些联系信息</p>
</footer>
</div>
一个不带 name 的 出口会带有隐含的名字“default”
案例
<!DOCTYPE html>
(html)
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>*{margin:0;padding: 0;}</style>
<link rel="stylesheet" href="../components/modal/modal.css">⭐
<script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>⭐
</head>
<body>
<div id="app">
<h1>弹框组件</h1>
<!-- 通过单击 flag设置为true,显示弹框 -->
<button @click="flag=true">弹框</button>
<button @click="flag2=true">弹框2</button>
<!-- visible 控制弹框是否显示 flag默认是false 默认不显示 -->
<!-- <modal :visible="flag" @update:visible="flag=$event"></modal> -->
<modal :visible.sync="flag" :title="'编辑对象'"></modal>
<!-- :visible.sync="flag" 是一个简写形式 等同于
:visible="flag" 和@update:visible="flag=$event" -->
<!-- :visible="flag" 给子组件传递一个visible属性 值是flag -->
<!--@update:visible="flag=$event" 监听子组件的update事件visible参数 设置flag为值为事件对象 -->
<modal :visible.sync="flag2" :title="'创建对象'"></modal>
</div>
<script type="module">
// 单击x关闭
// 告诉父元素把visible属性值改成false
// $emit("update:visble",false)
import modal from '../components/modal/modal.js';⭐导入
new Vue({
components:{modal},
el:"#app",
data:{
flag:false,//控制弹框是否显示
flag2:false
}
})
</script>
</body>
</html>
(css)
.modal {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
z-index: 500;
background-color: rgba(0, 0, 0, .4);
}
.modal-content {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
width: 400px;
height: 300px;
margin: auto;
background-color: #fff;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 0 12px rgba(0, 0, 0, .2);
}
.modal-title {
line-height: 44px;
padding: 0 15px;
display: flex;
font-size: 1.2em;
background-color: #f0f0f0;
justify-content: space-between;
}
.modal .close {
display: inline-block;
line-height: 44px;
color: #ff0000;
cursor: pointer;
}
(js)
const modal = {
template:`<div class="modal" v-if="visible">
<div class="modal-content">
<div class="modal-title">{{title}}
<span class="close"
@click="$emit('update:visible',false)">
×</span>
</div>
<div class="modal-body">
<slot></slot>
</div>
</div>
</div>`,
props:{
// 通过属性来接收
"visible":{type:Boolean,default:false},
"title":{type:String,default:''}
}
}
export default modal;//⭐导出