一篇看懂vue.js內容分發
vue.js內容分發把組件上下文的內容注入到組件。
定義解析
現在我們看一個架空的例子,幫助理解剛剛說過的嚴謹而難懂的定義。假設有一個組件名為my-component,其使用上下文如下:
<my-component>
<p>hi,slots</p>
</my-component>
再假設此組件的模板為:
<div>
<slot></slot>
<div>
那么注入后的組件HTML相當于:
<div>
<p>hi,slots</p>
<div>
標簽<slot>會把組件使用上下文的內容注入到此標簽所占據的位置上。組件分發的概念簡單而強大,因為它意味著對一個隔離的組件除了通過屬性、事件交互之外,還可以注入內容。
此案例變成可以執行的代碼,就是這樣的:
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div class="" id="app">
<my-component>
<p>hi,slots</p>
</my-component>
</div>
<script>
Vue.component('my-component', {
template: `
<div>
<slot></slot>
<div>
`
});
new Vue({
el: "#app"
});
</script>
一個組件如果需要外部傳入簡單數據如數字、字符串等等的時候,可以使用property,如果需要傳入js表達式或者對象時,可以使用事件,如果希望傳入的是HTML標簽,那么使用內容分發就再好不過了。所以,盡管內容分發這個概念看起來極為復雜,而實際上可以簡化了解為把HTML標簽傳入組件的一種方法。所以歸根結底,內容分發是一種為組件傳遞參數的方法。
命名插槽
剛剛的案例通過slot標簽,一股腦的把組件上下文的內容全部注入到組件內的規定位置。vue.js也提供了命名插槽(named slot)的技術,可以把上下文內的內容分成多個有名字的部分,然后插入到組件的不同位置:
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div class="" id="app">
<my-component>
<p slot='slot1'>hi,slot1</p>
<p slot='slot2'>hi,slot2</p>
</my-component>
</div>
<script>
Vue.component('my-component', {
template: `
<div>
<slot name='slot1'></slot>
<slot name='slot2'></slot>
<div>
`
});
new Vue({
el: "#app"
});
</script>
此案例使用了兩個插槽分別為slot1,slot2,并且把它們放到組件的不同位置。
綜合案例
現在我們看一個高級的案例,我來做一個即時貼(sticky)組件,用來顯示一個有標題和主體的即時貼。組件會定義好即時貼的結構,外觀,而具體的標題和內容,而使用內容分發技術傳入的HTML標簽:
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div class="" id="app">
<sticky>
<div slot="title">
<h3>Title</h3></div>
<div slot="body"><p>
Body foo bar baz ddd
</p></div>
</sticky>
</div>
<script>
Vue.component('sticky', {
template: `
<div>
<div class="wrapper">
<div>
<div class="title">
<slot name="title"></slot>
</div>
<div class="body">
<slot name="body"></slot>
</div>
</div>
</div>
</div>`
});
new Vue({
el: "#app"
});
</script>
<style>
.wrapper {
display: flex;
width: 180px;
height: 150px;
background: yellow;
border-radius: 10px;
}
.title {
border-bottom:1px solid red
}
.body {
border-bottom:1px solid blue
}
</style>
本案例內,使用上下文通過屬性slot創建了兩個插槽,分別為title和body,在組件的模板內(template成員)通過<slot>標簽的name屬性引用title和body,并把它注入且放入到合適的位置上。
來自:https://segmentfault.com/a/1190000007591093