組件的插槽
組件本身就是一個容器,也可以是一個vue對象,也是一個虛擬DOM
普通插槽
組件本身是一個容器,這個容器本身是空的,當我們把需要封裝的html結構裝進去之后,我們可以認為這個容器被塞滿了,那就意味著,我們無法想組件內部添加新的html結構進去,但是我們想在每次調用組件的時候需要渲染一些個性化的東西,這個時候我們就需要給組件做一個預留空間,這個預留空間就是插槽
<body><div id="app"><one><p>我是子標題</p></one></div><template id="temp1"><div><h2>我是標題</h2></div></template>
</body>
<script src="js/vue.js"></script>
<script>let one = {template:"#temp1"}new Vue({el:"#app",components:{one}})
</script>
代碼分析:
以上的代碼渲染之后,我們在虛擬DOM中寫入了一個p標簽,著就是所謂的插入,但是并沒有效果,因為我們并沒有在one組件中預留空間,也就是插槽
如果想在組件內部預留插槽,使用
<slot></slot>
<body><div id="app"><one><p>我是子標題</p><p>我是子標題</p><p>我是子標題</p><p>我是子標題</p><p>我是子標題</p><p>我是子標題</p></one></div><template id="temp1"><div><h2>我是標題</h2><slot><!-- 組件內預留給插槽的空間 --></slot></div></template>
</body>
<script src="js/vue.js"></script>
<script>let one = {template:"#temp1"}new Vue({el:"#app",components:{one}})
</script>
一個插入點插入多個插槽
現在我們想讓剛才的代碼中前3個p標簽出現在標題的上方,后面3個出現在標題的下方
<body><div id="app"><one><p>我是子標題</p><p>我是子標題</p><p>我是子標題</p><p>我是子標題</p><p>我是子標題</p><p>我是子標題</p></one></div><template id="temp1"><div><slot></slot><h2>我是標題</h2><slot></slot></div></template>
</body>
<script src="js/vue.js"></script>
<script>let one = {template:"#temp1"}new Vue({el:"#app",components:{one}})
</script>
代碼分析:
上面的代碼中,我們發現,在模板中的標題上方也制作了一個插槽slot,但是,從效果上來看只是單純把插入的內容復制了一份,分別插入不同的插槽里面
其實我們上面寫的都是默認插槽,把插槽語法寫完成如下
<div id="app"><one><p slot="default">我是子標題</p><p slot="default">我是子標題</p><p slot="default">我是子標題</p><p slot="default">我是子標題</p><p slot="default">我是子標題</p><p slot="default">我是子標題</p></one>
</div>
<template id="temp1"><div><slot name="default"></slot><h2>我是標題</h2><slot name="default"></slot></div>
</template>
默認情況下,所有的slot都必須要指定一個name,只是如果我們不自己指定的話,系統會給我們指定一個默認的名稱default
具名插槽
在上面的插槽中,我們所有的slot如果在不指定name的情況下全都是default,但是這個name屬性可以設置的,如果設置一些其他的值,我們就把這個插槽叫做具名插槽
<div id="app"><one><p slot="top">我是子標題</p><p slot="top">我是子標題</p><p slot="top">我是子標題</p><p slot="bottom">我是子標題</p><p slot="bottom">我是子標題</p><p slot="bottom">我是子標題</p></one>
</div>
<template id="temp1"><div><slot name="top"></slot><h2>我是標題</h2><slot name="bottom"></slot></div>
</template>
代碼分析:
在上面的代碼中,我們可以為插槽取一個名字,從而實現一對多,或者多對一的插入,當插槽有了名字之后,我們就可以在插入的時候指定插入到某一個插槽中
- 我們組件里面定義插槽的時候使用slot標簽,并且這個標簽上面定義name屬性,成為具名插槽
- 在調用組件的時候,我們可以向指定的插槽插入內容,只需要在這個插入的元素上面添加一個slot=“插槽名”即可
- 具名插槽是可以多次使用的,所以我們可以把上面的top復制一份放到bottom的下面,這樣上面三個p標簽也會出現在下面的插槽里面
插槽作用域
<body><div id="app"><one><p>我想要拿到組件內部的userName</p></one></div><template id="temp1"><div><h2>我是一個組件</h2><slot><!-- 組件的預留空間 --></slot></div></template>
</body>
<script src="js/vue.js"></script>
<script>let one = {template:"#temp1",data(){return {userName:"zhangsan"}}}new Vue({el:"#app",components:{one}})
</script>
之前我們一直都是外部的數據傳遞給內部,如果要把組件內部的數據傳遞給外部,我們可以:
1、利用對象的堆棧原理
2、自定義事件
注意:
我們現在要做一個區分,我們是可以把數據渲染在組件里面的,也可以渲染在插槽里面,但是這兩種方式在向組件外部傳值的時候是有區別的,我們上面說的這兩種方法,只針對在組件內渲染的,如果是渲染在組件的插槽內部的,我們可以通過插槽作用域取拿
比如我們現在要userName的值傳遞到外面,我們可以在插入的標簽上面添加一個slot-scope=“scope”
<body><div id="app"><one><div slot-scope="scope"><p>{{scope.userName}}</p><p>{{scope.age}}</p></div> </one></div><template id="temp1"><div><h2>我是一個組件</h2><slot :user-name="userName" :age="18"><!-- 組件的預留空間 --></slot></div></template>
</body>
<script src="js/vue.js"></script>
<script>let one = {template:"#temp1",data(){return {userName:"zhangsan"}}}new Vue({el:"#app",components:{one}})
</script>
插槽作用域舊版本語法
<div id="app"><one><div slot="footer" slot-scope="scope"><p>{{scope.userName}}</p><p>{{scope.age}}</p></div> </one></div><template id="temp1"><div><h2>我是一個組件</h2><slot name="footer" :user-name="userName" :age="18"><!-- 組件的預留空間 --></slot></div></template>
新版本語法
<one><template v-slot:footer="scope"><p>{{scope.userName}}</p><p>{{scope.age}}</p></template>
</one>
最新語法
<one><template #footer="{userName,age}"><p>{{userName}}</p>"<p>{{age}}</p></template>
</one>
代碼分析:
最新語法可以直接解構獲取,并且v-slot這個指令也直接使用#來替代,簡化代碼