vue元件化中slot的用法

阿飛飛飛發表於2019-04-30

slot可以在子元件中開啟插槽,在父元件引用該組建時,可以定義這個插槽內要展現的功能或模組

1.單個slot

子元件中在相應位置寫slot標籤,父元件在引用子元件時,在子元件標籤內寫要插入插槽的元素; 還可以設定slot在父元件沒有設定插槽時,子元件的插槽預設顯示內容; 父元件.vue

<template>
    <div class="home">
        <child-componment>
            <p>
                這是父元件的slot替代內容!
            </p>
        </child-componment>
    </div>
</template>
​
<script>
import childComponment from '@/components/childComponment.vue'
export default {
    name: "home",
    components:{
        childComponment
    },
    data(){
        return {
        message: ''
        }
    }
};
</script>
​
複製程式碼

子元件childComponment.vue

<template>
    <div class="childComponment">
        <h2>這是子元件childComponment!</h2>
        <slot>
            <span style="color: red;">如果父元件沒有插入內容,我這樣可以設定預設的顯示內容</span>
        </slot>
    </div>
</template>
​
<script>
export default {
    name: "childComponment",
    data(){
        return {
            message: ''
        }
    }
};
</script>
複製程式碼

2.具名slot(同時使用多個插槽)

給slot指定一個名稱,可以分發多個slot插槽,但是隻能有一個無名slot; 父元件的slot插槽內容,不寫slot="xxx"的都會插到子元件的無名slot中; 如果沒有指定無名slot(預設slot),父元件內多餘的內容將會被拋棄。

<template>
    <div class="home">
        <child-componment>
            <h1 slot="header">
                父元件的header
            </h1>
            <h6 slot="footer">父元件的footer</h6>
            
            <h6>父元件的無名slot-1</h6>
            <p>
                父元件的無名slot-2
            </p>
        </child-componment>
    </div>
</template>
​
<script>
import childComponment from '@/components/childComponment.vue'
export default {
    name: "home",
    components:{
        childComponment
    },
    data(){
        return {
            message: ''
        }
    }
};
</script>
​
複製程式碼

子元件

<template>
    <div class="childComponment">
        <span>這是子元件childComponment的正常內容!</span>
        <div class="header">
            <slot name="header">
                <span style="color: red;">子元件預設header-slot</span>
            </slot>
        </div>
        <div class="container">
            <!-- 如果沒有指定無名slot(預設slot),父元件內多餘的內容將會被拋棄 -->
            <slot>
                <span style="color: red;">子元件預設無名slot</span>
            </slot>
        </div>
        <div class="footer">
            <slot name="footer">
                <span style="color: red;">子元件預設footer-slot</span>
            </slot>
        </div>
    </div>
</template>
​
<script>
export default {
    name: "childComponment",
    data(){
        return {
            message: ''
        }
    }
};
</script>
<style scoped>
.childComponment{
    font-size: 16px;
}
.header{
    height: 100px;
    border:1px solid red;
    color: red;
}
.container{
    height: 500px;
    border: 1px solid black;
    color: black;
}
.footer{
    height:100px;
    border: 1px grey solid;
    color: grey;
}
</style>
複製程式碼

vue元件化中slot的用法

3.作用域插槽

<template>
    <div class="home">
        <child-componment>
            <template slot-scope="slotProps">
                <!-- 這裡顯示子元件傳來的資料 -->
                <p>{{slotProps}}</p>
            </template>
        </child-componment>
    </div>
</template>
​
<script>
import childComponment from '@/components/childComponment.vue'
export default {
    name: "home",
    components:{
        childComponment
    }
};
</script>
​
複製程式碼

子元件

<template>
    <div class="childComponment">
        <span>這是子元件childComponment的正常內容!</span>
        <div class="container">
            <!-- 如果沒有指定無名slot(預設slot),父元件內多餘的內容將會被拋棄 -->
            <slot msg="子元件資訊" slotData="子元件資料"></slot>
        </div>
    </div>
</template>
複製程式碼

vue元件化中slot的用法
Tips: 作用於插槽也可是具名插槽

案例:列表元件

這是作用於插槽使用最多的案例,允許元件自定義應該如何渲染元件的每一項。

<template>
  <div class="about">
    <h1>This is about page</h1>
    <my-list :books="books">
        <template slot="bookList" slot-scope="myListProps">
            <li>{{myListProps.bookName}}</li>
        </template>
    </my-list>
  </div>
</template>
<script>
import myList from '@/components/myList.vue'
export default {
    components:{
        myList
    },
    data(){
        return {
            books: [
                {name: 'css揭祕'},
                {name: '深入淺出nodejs'},
                {name: 'javascript設計模式與開發實戰'}
            ]
        }
    }
}
</script>
複製程式碼

子元件myList.vue

<template>
  <div class="myList">
    <h1>This is myList page</h1>
    <ul>
        <slot name="bookList" v-for="book in books" :bookName="book.name"></slot>
    </ul>
  </div>
</template>
<script>
export default {
    props:{
        books:{
            type: Array,
            default: function(){
                return []
            }
        }
    },
    mounted(){
        console.log(this.books)
    }
}
</script>
複製程式碼

vue元件化中slot的用法
其實上面的案例可直接在父元件中for迴圈就好,此處只是作為演示slot的作用域插槽; 實際開發中作用域插槽的使用場景主要為:既可以複用子元件的slot,又可以使slot內容不一致。

4.訪問slot

vue2.0提供了$slot方法來訪問slot 此處程式碼以**“具名slot(同時使用多個插槽)”**的程式碼為例,修改一下子元件childComponment.vue

export default {
    name: "childComponment",
    data(){
        return {
            message: ''
        }
    },
    mounted(){
        let header = this.$slots.header
        let main = this.$slots.default
        let footer = this.$slots.footer
        console.log(header)
        console.log(main)
        console.log(footer)
        console.log(footer[0].elm.innerHTML)
    }
};
複製程式碼

列印結果:

vue元件化中slot的用法
其中elm的內容為插槽內容,結構如下:

vue元件化中slot的用法

相關文章