Vue scoped slot

by Albert

HTML

<!-- 子組件 -->
<template id="child">
    <main>
        <slot name="owner" :user="user" />
        
        <!-- 變量名稱 "item" 可自訂, 但是外界要遵守 -->
        <slot name="child-slot" 
              v-for="browser in browserList"
              :item="browser" />
    </main>
</template>

<!-- 父組件 -->
<template id="parent">
    <div>
        <header>
            <ul>
                <li>Home</li>
                <li>About</li>
            </ul>
        </header>
        
        <h2>使用者</h2>
        <c-child>
            <h3 slot="owner" slot-scope="{ user }" style="color:blue;">
                {{ user.name }} - {{ user.id }}
            </h3>
        </c-child>
        
        <hr/>

        <h1>瀏覽器</h1>
        <!-- 
            變量名稱 "item" 要遵守子組件, 但是Vue會再加一層
        -->
        <c-child>
        
            <!-- destructuring assignment -->
            <template slot="child-slot"
                      slot-scope="{ item }">
                <article>
                    <h1>{{ item.title }}</h1>
                    <p>{{ item.description }}</p>
                </article>
            </template>
            
            <!-- deep destructuring assignment -->
            <!-- <template slot="child-slot"
                      slot-scope="{ item:{ title }, item:{ description } }" >
                <article>
                    <h1>{{ title }}</h1>
                    <p>{{ description }}</p>
                </article>
            </template> -->
            
            <!-- regular syntax -->
            <!-- <template slot-scope="props" slot="child-slot">
                <article>
                    <h1>{{ props.item.title }}</h1>
                    <p>{{ props.item.description }}</p>
                </article>
            </template> -->
        </c-child>
    </div>
</template>

<div id="app">
    <c-parent></c-parent>
</div>

CSS

* {
  margin: 0;
  padding: 0;
	line-height: 1.5em;
	font-family: "consolas", "微軟正黑體";
}

html, body, menu {
	margin: 0;
	padding: 0;
}

body {
	background: #EDEDED;
}

p {
	color: #727272;
}

header {
	/*position: fixed;
	top: 0px;
	left: 0px;
	right: 0px;*/
	background: #0ba495;
	color: white;
	padding: 0 1em;
}

footer {
	background: #D9D9D9;
	padding: 0 38px;
	line-height: 60px;
	height: 60px;

}

footer p {
	line-height: 60px;
}

main {
	padding: 0 1em;
	margin: 0 auto;
	padding: 0 38px;

}
menu {
	float: left;
}

.item {
	float: left;
	margin-right: 20px;
}

.item:last-child {
	margin-right: 0px;
}

.user {
	float: right;
}

.clear {
	clear: both;
}

ul {
	margin: 0;
	padding: 0;
}
li {
	display: inline-block;
	margin-right: 1em;
	line-height: 60px;
	font-size: 22px;
	transition: 0.5s all;
}

li:hover {
	background: #1ABFAF;
}

header li {
	padding: 0 1em;
	display: inline-block;
	margin: 0px;
	cursor: pointer;
	text-align: left;
}

h1 {
	color: #444444;

	border-bottom: 1px inset #C8C8C8;
	color: #000000;
}

article h1 {
	color: #727272;
}

JavaScript

// 子組件
Vue.component('c-child', {

    template: '#child',
    
    data: function () {
        return {
        	user: {
            	id: 101,
                name: 'Albert'
            },
            
            browserList: [
                {title: 'Chrome', description: 'Chrome 描述...'},
                {title: 'IE', description: 'IE 描述...'},
                {title: 'Firefox', description: 'Firefox 描述...'},
            ]
        }
    }
})

// 父組件
Vue.component('c-parent', {
    template: '#parent'
})

// App
var vm = new Vue({
    el: '#app'
})