Vue 插槽(Day40)

18 阅读1分钟

插槽

默认插槽

  1. 在App组件内使用双标签引用子组件
  2. 在子组件内写入slot(插槽)标签等待接收传递内容
  3. 在双标签内传入需要插槽接收的内容

App组件

<template>
    <div class="container">
        <Category title="美食">
            <img src="https://img2.baidu.com/it/u=2152778983,3447357881&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500">
        </Category>
        <Category title="游戏">
            <ul>
                <li v-for="(item,index) in games" :key="index">
                    {{ item }}
                </li>
            </ul>
        </Category>
        <Category title="电影">
            <video controls src="http://vjs.zencdn.net/v/oceans.mp4"></video>
        </Category>
    </div>
</template><script>
import Category from "@/components/Category.vue";
​
export default {
    name: 'App',
    components: {
        Category
    },
    data(){
        return{
            foods:['烧烤','火锅','小龙虾','牛排'],
            games:['扫雷','俄罗斯方块','推箱子','超级玛丽'],
            films:['《熊出没》','《大鱼》','《哈利波特》','《教父》'],
        }
    }
}
</script>

Category组件

<script>
import {defineComponent} from 'vue'export default defineComponent({
    name: "Category",
    props: ['title']
})
</script><template>
    <div class="category">
        <h3>{{ title }}分类</h3>
        <!--  定义一个插槽,若在插槽中配置默认值,当用户传值展示用户内容,用户不传值展示默认值     -->
        <slot></slot>
    </div>
</template>

具名插槽

  1. 同时使用多个slot插槽时,为每一个插槽添加一个name属性进行命名
  2. 在相应的插入内容的元素中添加一个slot属性与name命名对应
  3. 注: 当元素是template标签时,可不用slot属性使用v-slot属性

App组件

<template>
    <div class="container">
        <Category title="美食">
            <img slot="center"
                 src="https://img2.baidu.com/it/u=2152778983,3447357881&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500"
                 alt="">
            <a slot="footer" href="https://www.baidu.com">更多美食</a>
        </Category>
        <Category title="游戏">
            <ul slot="center">
                <li v-for="(item,index) in games" :key="index">
                    {{ item }}
                </li>
            </ul>
            <div slot="footer" class="foot">
                <a href="https://www.baidu.com">单机游戏</a>
                <a href="https://www.baidu.com">网络游戏</a>
            </div>
        </Category>
        <Category title="电影">
            <video slot="center" controls src="http://vjs.zencdn.net/v/oceans.mp4"></video>
            //用法1
            <template slot="footer">
                <div class="foot">
                    <a href="https://www.baidu.com">经典</a>
                    <a href="https://www.baidu.com">热门</a>
                    <a href="https://www.baidu.com">推荐</a>
                </div>
                <h4>欢迎前来观影</h4>
            </template>
            //用法2
            <template v-slot:footer>
                <!--v-slot:footer只能用在template标签上-->
                <div class="foot">
                    <a href="https://www.baidu.com">经典</a>
                    <a href="https://www.baidu.com">热门</a>
                    <a href="https://www.baidu.com">推荐</a>
                </div>
                <h4>欢迎前来观影</h4>
            </template>
        </Category>
    </div>
</template>

Category组件

<template>
    <div class="category">
        <h3>{{ title }}分类</h3>
        <slot name="center"></slot>
        <slot name="footer"></slot>
    </div>
</template>

作用域插槽

理解:

  • 数据存放在定义插槽的组件自身中
  • 结构由插槽的使用者决定
  • 作用域插槽可以有名字
  1. 使用双标签引用子组件
  2. 子组件的结构由template标签包裹,标签添加scope属性或slot-scope属性,属性值由子组件动态传入
  3. 子组件中存放data数据
  4. 子组件定义插槽时动态绑定自定义名称的数据对象

App组件

<template>
    <div class="container">
        <Category title="游戏">
           <template scope="game">
               <ul>
                   <li v-for="(item,index) in game.games" :key="index">
                       {{ item }}
                   </li>
               </ul>
           </template>
        </Category>
​
        <Category title="游戏">
            <template slot-scope="{games}">
                <ol>
                    <li v-for="(item,index) in games" :key="index">
                        {{ item }}
                    </li>
                </ol>
            </template>
        </Category>
​
        <Category title="游戏">
            <template scope="{games}">
                <h4 v-for="(item,index) in games" :key="index">
                    {{ item }}
                </h4>
            </template>
        </Category>
    </div>
</template>

Category组件

<script>
import {defineComponent} from 'vue'export default defineComponent({
    name: "Category",
    props: ['title'],
    data() {
        return {
            games: ['扫雷', '俄罗斯方块', '推箱子', '超级玛丽'],
        }
    }
})
</script><template>
    <div class="category">
        <h3>{{ title }}分类</h3>
        <slot :games="games"></slot>
    </div>
</template>

总结

  1. 作用: 让父组件可向子组件的指定位置插入HTML结构,是组件间一中通信方式
  2. 分类: 默认插槽、具名插槽、作用域插槽