vue插槽slot

儒清發表於2018-08-31

前言

當父元件在使用一個子元件的時候,可以使用單標籤的形式,也可以使用雙標籤的形式,比如<Child /> 或者<Child></Child>。當時使用雙標籤的形式時,如果我們在兩個標籤中放入一些內容,比如<Child>hello world</Child>,子元件是可以通過插槽slot來獲取標籤中的內容,下面是官網的幾個demo

demo1

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <div id="app">
            <!-- 使用子元件 -->
            <navigation-link>這是父元件上的一些內容</navigation-link>
        </div>
    </body>
</html>

<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
    // 註冊子元件navigation-link
    Vue.component(`navigation-link`, {
        data() {},
        // 如果 <navigation-link> 沒有包含一個 <slot> 元素,則任何傳入它的內容都會被拋棄。
        template: `
            <a v-bind:href="url" class="nav-link" >
              <slot></slot>
            </a>`
     })
    
    new Vue({
        el: `#app`,
        data: {
            
        }
    })
</script>

demo2-具名插槽

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <div id="app">
            <base-layout>
                <!-- template 也可以是個普通元素,請看footer的slot -->
              <template slot="header">
                <h1>頁面標題</h1>
              </template>
            
              <p>A paragraph for the main content.</p>
              <p>And another one.</p>
            
              <div slot="footer">
                <mark>頁面底部資訊</mark>
              </div>
            </base-layout>
        </div>
    </body>
</html>

<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
    // slot具名以後就可以插到對應的位置,否則規則跟非具名插槽一樣
    Vue.component(`base-layout`, {
        template: `
            <div class="container">
              <header>
                <slot name="header"></slot>
              </header>
              <main>
                <slot></slot>
              </main>
              <footer>
                <slot name="footer"></slot>
              </footer>
            </div>`
    })
    
    new Vue({
        el: `#app`
    })
</script>

demo3-預設值

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <div id="app">
            <Child>提交</Child>
            <!--當Child中間不傳入內容時使用預設值-->
            <Child></Child>
        </div>
    </body>
</html>

<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
    Vue.component(`Child`,{
        template: `
            <button type="submit">
              <slot>Submit</slot>
            </button>`
    });
    
    new Vue({
        el: `#app`
    })
    
</script>

demo4-作用域插槽

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <div id="app">
            <todo-list :todos="todos">
                <!-- 用slot-scope接收子元件回傳的資訊 -->
                <template slot-scope="slotProps">
                    <span v-if="slotProps.todo.isComplete"></span> {{ slotProps.todo.text }}
                </template>
            </todo-list>
        </div>
    </body>
</html>

<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
    Vue.component(`todo-list`, {
        props: [`todos`],
        template: `
            <ul>
              <li
                v-for="todo in todos"
                v-bind:key="todo.id">
                <!-- 回傳資訊 -->
                <slot v-bind:todo="todo">
                  {{ todo.text }}
                </slot>
              </li>
            </ul>`
    })

    new Vue({
        el: `#app`,
        data: {
            todos: [
            {
                text: `買機械鍵盤`,
                isComplete: true
            }, {
                text: `打羽毛球`,
                isComplete: true
            },
            {
                text: `去教會做禮拜`,
                isComplete: false
            }]
        }
    })
</script>


相關文章