Vuejs:元件 slot 內容分發
本文是在官方文件的基礎上,更加細緻的說明,程式碼更多更全。
簡單來說,更適合新手閱讀
(二十八)Slot分發內容
①概述:
簡單來說,假如父元件需要在子元件內放一些DOM,那麼這些DOM是顯示、不顯示、在哪個地方顯示、如何顯示,就是slot分發負責的活。
②預設情況下
父元件在子元件內套的內容,是不顯示的。
例如程式碼:
<div id="app"> <children> <span>12345</span> <!--上面這行不會顯示--> </children> </div> <script> var vm = new Vue({ el: '#app', components: { children: { //這個無返回值,不會繼續派發 template: "<button>為了明確作用範圍,所以使用button標籤</button>" } } }); </script>
顯示內容是一個button按鈕,不包含span標籤裡面的內容;
③單個slot
簡單來說,只使用這個標籤的話,可以將父元件放在子元件的內容,放到想讓他顯示的地方。
<div id="app"> <children> <span>12345</span> <!--上面這行不會顯示--> </children> </div> <script> var vm = new Vue({ el: '#app', components: { children: { //這個無返回值,不會繼續派發 template: "<button><slot></slot>為了明確作用範圍,所以使用button標籤</button>" } } }); </script>
例如這樣寫的話,結果是:
<button><span>12345</span>為了明確作用範圍,所以使用button標籤</button>
即父元件放在子元件裡的內容,插到了子元件的<slot></slot>位置;
注意,即使有多個標籤,會一起被插入,相當於用父元件放在子元件裡的標籤,替換了<slot></slot>這個標籤。
④具名slot
將放在子元件裡的不同html標籤放在不同的位置
父元件在要分發的標籤裡新增 slot=”name名” 屬性
子元件在對應分發的位置的slot標籤裡,新增name=”name名” 屬性,
然後就會將對應的標籤放在對應的位置了。
示例程式碼:
<div id="app">
<children>
<span slot="first">12345</span>
<span slot="second">56789</span>
<!--上面這行不會顯示-->
</children>
</div>
<script>
var vm = new Vue({
el: '#app',
components: {
children: { //這個無返回值,不會繼續派發
template: "<button><slot name='first'></slot>為了明確作用範圍,<slot name='second'></slot>所以使用button標籤</button>"
}
}
});
</script>
顯示結果為:(為了方便檢視,已手動調整換行)
<button>
<span slot="first">12345</span>
為了明確作用範圍,
<span slot="second">56789</span>
所以使用button標籤
</button>
⑤分發內容的作用域:
被分發的內容的作用域,根據其所在模板決定,例如,以上標籤,其在父元件的模板中(雖然其被子元件的children標籤所包括,但由於他不在子元件的template屬性中,因此不屬於子元件),則受父元件所控制。
示例程式碼:
<div id="app">
<children>
<span slot="first" @click="tobeknow">12345</span>
<span slot="second">56789</span>
<!--上面這行不會顯示-->
</children>
</div>
<script>
var vm = new Vue({
el: '#app',
methods: {
tobeknow: function () {
console.log("It is the parent's method");
}
},
components: {
children: { //這個無返回值,不會繼續派發
template: "<button><slot name='first'></slot>為了明確作用範圍,<slot name='second'></slot>所以使用button標籤</button>"
}
}
});
</script>
當點選文字12345的區域時(而不是按鈕全部),會觸發父元件的tobeknow方法。
但是點選其他區域時則沒有影響。
官方教程是這麼說的:
父元件模板的內容在父元件作用域內編譯;子元件模板的內容在子元件作用域內編譯。
⑥當沒有分發內容時的提示:
假如父元件沒有在子元件中放置有標籤,或者是父元件在子元件中放置標籤,但有slot屬性,而子元件中沒有該slot屬性的標籤。
那麼,子元件的slot標籤,將不會起到任何作用。
除非,該slot標籤內有內容,那麼在無分發內容的時候,會顯示該slot標籤內的內容。
如示例程式碼:
<div id="app">
<children>
<span slot="first">【12345】</span>
<!--上面這行不會顯示-->
</children>
</div>
<script>
var vm = new Vue({
el: '#app',
components: {
children: { //這個無返回值,不會繼續派發
template: "<div><slot name='first'><button>【如果沒有內容則顯示我1】</button></slot>為了明確作用範圍,<slot name='last'><button>【如果沒有內容則顯示我2】</button></slot>所以使用button標籤</div>"
}
}
});
</script>
說明:
【1】name=’first’的slot標籤被父元件對應的標籤所替換(slot標籤內部的內容被捨棄);
【2】name=’last’的slot標籤,因為沒有對應的內容,則顯示該slot標籤內部的內容。
⑦假如想控制子元件根標籤的屬性
【1】首先,由於模板標籤是屬於父元件的,因此,將子元件的指令繫結在模板標籤裡,是不可以的(因為他歸屬於父元件);
【2】假如需要通過父元件控制子元件是否顯示(例如v-if或者v-show),那麼這個指令顯然是屬於父元件的(例如放在父元件的data下面)。可以將標籤寫在子元件的模板上。
如程式碼:
<div id="app">
<button @click="toshow">點選讓子元件顯示</button>
<children v-if="abc">
</children>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
abc: false
},
methods: {
toshow: function () {
this.abc = !this.abc;
}
},
components: {
children: { //這個無返回值,不會繼續派發
template: "<div>這裡是子元件</div>"
}
}
});
</script>
說明:通過父元件(點選按鈕,切換v-if指令的值)控制子元件是否顯示。
【3】假如需要通過子元件,控制子元件是否顯示(比如讓他隱藏),那麼這個指令顯然是屬於子元件的(會將值放在子元件的data屬性下),那麼就不能像上面這麼寫,而是必須放置在子元件的根標籤中。
<div id="app">
<button @click="toshow">點選讓子元件顯示</button>
<children>
<span slot="first">【12345】</span>
<!--上面這行不會顯示-->
</children>
</div>
<script>
var vm = new Vue({
el: '#app',
methods: {
toshow: function () {
this.$children[0].tohidden = true;
}
},
components: {
children: { //這個無返回值,不會繼續派發
template: "<div v-if='tohidden' @click='tohide'>這裡是子元件</div>",
data: function () {
return {
tohidden: true
}
},
methods: {
tohide: function () {
this.tohidden = !this.tohidden;
}
}
}
}
});
</script>
說明:
點選子元件會讓子元件消失;
點選父元件的按鈕,通過更改子元件的tohidden屬性,讓子元件重新顯示。
子元件的指令繫結在子元件的模板之中(如此才能呼叫);
轉自:https://blog.csdn.net/sinat_17775997/article/details/52484072#comments