vue2.X基礎知識六之slot內容分發

    當需要讓組件組合使用,混合父組件的內容與子組件的模板時,就會用到slot,這個過程叫做內容分發。

1、slot內容分發

在子組件內使用特殊的<slot>元素就可以爲這個子組件開啓一個slot(插槽),在父組件模板裏,插入在子組件標籤內的所有內容將替代子組件的<slot>標籤及它的內容。例如:

<div id="app">
    <child-component>
	<div>分發的內容</div>
	<p>更多分發的內容</p>
    </child-component>
    <!-- 子組件裏沒有內容時,顯示slot裏面的內容 -->
    <child-component></child-component>
</div>
<script>
			
    /* slot 當子組件沒有內容的時候顯示(備用內容) */
    Vue.component('child-component',{
	template: '<div>\
	               <slot>如果父組件裏的子組件標籤裏沒有插入內容,我將作爲默認出現</slot>\
		   </div>',
		   data: function(){
		   	    return {
			        name: '子組件的數據;'
			    }
			}
			});
			
    var app = new Vue({
        el: '#app'
    });
</script>

沒有name屬性的slot將作爲默認slot出現,父組件沒有使用slot特性的元素與內容都將出現在這裏;如果沒有指定默認的匿名slot,父組件內多餘的內容片段都將被拋棄。例如:

               <div id="app">
			<child-component>
				<h2 slot="header">標題</h2>
				<p>正文內容</p>
				<p>更多的正文內容</p>
				<div slot="footer">底部信息</div>
			</child-component>
		</div>
            <script>	
         	Vue.component('child-component',{
				template: `
				<div class="container">
					<div class="header">
						<slot name="header"></slot>
					</div>
					<div class="main">
						<slot></slot>
					</div>
					<div class="footer">
						<slot name="footer"></slot>
					</div>
				</div>
				`
			});
			
			var app = new Vue({
				el: '#app'
			});
            </script>

以上代碼中,類名爲main的div裏面的slot沒有name屬性,是默認的slot,顯示的內容正是子組件child-component裏的兩個沒有slot屬性的p標籤裏面的內容;子組件<slot>內的備用內容,它的作用域是子組件本身。

2、作用域插槽

    作用域插槽是一種特殊的slot,使用一個可以複用的模板替換已渲染元素。例如:

                <div id="app">
			<child-component>
				<!-- 臨時變量props,用於訪問來自子組件插槽的數據msg -->
				<template slot-scope="props">
					<p>來自父組件的內容</p>
					<p>{{ props.msg }}</p>
				</template>
			</child-component>
		</div>
		<script>
			/*
			 沒有name的slot將作爲默認slot出現,父組件沒有使用slot特性的元素與內容都將
			 出現在這裏;如果沒有指定默認的匿名slot,父組件內多餘的內容片段都將被拋棄
			 * 
			 * */
			Vue.component('child-component',{
				template: `
				<div class="container">
					<slot msg="來自子組件的內容"></slot>
				</div>
				`
			});
			
			var app = new Vue({
				el: '#app'
			});
                </script>

作用域插槽更具代表性的用例是列表組件;允許組件自定義應該如何渲染列表每一項。例如:

                <div id="app">
			<my-list :books="books">
				<!-- 作用域插槽也可以是具名的slot -->
				<template slot="book" slot-scope="props">
					
						<li>{{ props.bookName }}</li>

				</template>
			</my-list>
		</div>
		<script>
			Vue.component('my-list', {
				props: {
					books: {
						type: Array,
						default: function () {
							return [];
						}
					}
				},
				template: `
					<ul>
						<slot name="book" v-for="book in books" :book-name="book.name">
						</slot>
					</ul>
					
				`
			});
			var app = new Vue({
				el: '#app',
				data: {
					books: [
						{name: '《vue.js實戰》'},
						{name: '《javascript語言精粹》'},
						{name: '《javascript高級程序設計》'}
					]
				}
			});
		</script>
3、訪問slot

    通過$slot可以訪問某個具名slot,this.$slots.default包括了所有沒有被包含在具名slot中的節點。例如:                   

            <div id="app">
			<child-component>
				<h2 slot="header">標題</h2>
				<p>正文內容</p>
				<p>更多正文內容</p>
				<div slot="footer">底部信息</div>
			</child-component>
		</div>
		<script>
			Vue.component('child-component', {
				template: `
					<div class="container">
						<div class="header">
							<slot name="header"></slot>
						</div>
						<div class="main">
							<slot></slot>
						</div>
						<div class="footer">
							<slot name="footer"></slot>
						</div>
					</div>
				`,
				mounted: function () {
					var header = this.$slots.header;
					var main = this.$slots.default;
					var footer = this.$slots.footer;
					console.log(footer); // 打印出footer元素的虛擬dom對象
					console.log(footer[0].elm.innerHTML); // "底部信息"
				}
			});
			
			var app = new Vue({
				el: '#app'
			});
		</script>


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章