Vue中插槽的简单使用

2024-01-07 23:30:43

插槽

  • 分类:默认插槽、具名插槽、作用域插槽

  • 默认插槽:让父组件可以向子组件指定位置插入html结构,也是一种组件通信的方式,适用于父组件(App)===>子组件(MyFooter)

  • 默认插槽的App组件

  • <template>
     ?<div class="container">
     ? ?<!-- 普通写法 -->
     ? ?<!-- title、listDate的位置为标签属性。 -->
     ? ?<MyFooter title="游戏" :listDate="games"/>
    ?
     ? ?<!-- 下面都是默认插槽的书写形式-->
     ? ?<!-- Vue会将img标签的内容解析后在传给MyFooter组件中的slot插槽中。故将普通写法:listDate="foods"删除掉 -->
     ? ?<!-- 标签体的位置为:<MyFooter>标签体</MyFooter> ? -->
     ? ?<MyFooter title="美食" >
     ? ? ?<img src="图片地址" alt="">
     ? ?</MyFooter>
    ?
     ? ?<MyFooter title="游戏" >
     ? ? ? <ul>
     ? ? ? ? ? ?<li v-for="(item,index) in games" :key="index" >{{ item }}</li>
     ? ? ? ?</ul>
     ? ?</MyFooter>
    ?
     ? ?<MyFooter title="电影" >
     ? ? ?<!-- controls让视频可以通过点击控制播放 -->
     ? ? ? ? <video controls src="视频地址"></video>
     ? ?</MyFooter>
     ? ? ?
     ? ?<router-view />
     ?</div>
    </template>
    <script>
    import MyFooter from './components/MyFooter.vue';
    export default {
     ?name: 'App',
     ?components: { MyFooter },
     ?data() {
     ? ?return {
     ? ? ?foods: ['火锅', '薯条', '汉堡'],
     ? ? ?games: ['只狼', '大表哥', '黑神话悟空'],
     ? ? ?files: ['《深海》', '《战狼》', '《流浪地球》']
     ?  }
      }
    }
    </script>
    <style lang="less" scoped>
    .container {
     ?display: flex;
     ?justify-content: space-around
    }
    img {
     ?width: 100%;
    }
    video {
     ?width: 100%;
    }
    </style>
    ?
  • 默认插槽的MyFooter组件

  • <template>
     ? ?<div class="category">
     ? ? ? ?<h3>{{ title }}分类</h3>
     ? ? ? ?<!-- 普通写法 -->
         ? ?<!-- 普通写法通过props将listDate传过来进行展示 -->
     ? ? ? ?<ul>
     ? ? ?       <li ?v-for="(item,index) in listDate" :key="index" >{{ item }}</li> ? 
     ?      </ul>
            <!-- 插槽写法 -->
     ? ? ? ?<!-- <slot></slot>为默认插槽,挖个坑等使用的组件填充坑的内容 -->
     ? ? ? ?<slot>如果图片或视频未展示,展示此处的文字</slot>
     ? ? ? 
     ? ?</div>
    </template>
    ?
    <script>
    export default {
     ? ?name: 'MyFooter',
     ? ?//这里保留应该只保留title,listDate仅是普通写法需求
     ? ?props: ['title','listDate'],
    }
    </script>
    <style scoped lang="css">
     ? ?.category {
     ? ? ? ?background-color: skyblue;
     ? ? ? ?width: 200px;
     ? ? ? ?height: 300px;
     ?  }
     ? ?h3 {
     ? ? ? ?text-align: center;
     ?  }
    </style>
    ?
  • 具名插槽的App

  • 具名插槽的给MyFooter的slot标上名字name="xxx",在App组件中使用那个插槽则slot="xxx"。进行相互匹配

  • <template>
     ?<div class="container">
    ?
     ? ?<!-- 有名插槽 -->
     ? ?<!-- title的位置为标签属性。-->
     ? ?<MyFooter title="美食" >
     ? ? ?<!-- 给img、a匹配相应的插槽名字,对应相应组件中的插槽 -->
     ? ? ?<img slot="center" src="图片地址" alt="">
     ? ? ?<a slot="footer" href="网址地址">美食地址</a>
     ? ? ?<a slot="footer" href="网址地址">电影地址</a>
     ? ?</MyFooter>
    ?
     ? ?<MyFooter title="游戏" >
     ? ? ? <ul slot="center">
     ? ? ? ? ? ?<li ?v-for="(item,index) in games" :key="index" >{{ item }}</li>
     ? ? ? </ul>
     ? ? ? <div slot="footer">
     ? ? ? ? ?<a slot="footer" href="网址地址">热门推荐</a>
     ? ? ? ? ?<a slot="footer" href="网址地址">网络共享</a>
     ? ? ? </div>
     ? ? ? 
     ? ?</MyFooter>
    ?
     ? ?<MyFooter title="电影" >
     ? ? ?<!-- controls让视频可以通过点击控制播放 -->
     ? ? ? ? <video slot="center" controls src="视频地址"></video>\
     ? ? ? ? <!-- template让下列的代码少了一层div 同时可以将slot="footer"去掉,改成在template标签属性的位置使用 v-slot:footer -->
     ? ? ? ? <template>
     ? ? ? ? ? ?<div slot="footer">
     ? ? ? ? ? ? ? ?<a slot="footer" href="网址地址">动漫</a>
     ? ? ? ? ? ? ? ?<a slot="footer" href="网址地址">生活</a>
     ? ? ? ? ? ?</div>
     ? ? ? ? ? ?<a slot="footer" href="网址地址">动画片</a>
     ? ? ? ? </template>
     ? ?</MyFooter>
     ? ?<router-view />
     ?</div>
    </template>
    <script>
    import MyFooter from './components/MyFooter.vue';
    export default {
     ?name: 'App',
     ?components: { MyFooter },
     ?data() {
     ? ?return {
     ? ? ?foods: ['火锅', '薯条', '汉堡'],
     ? ? ?games: ['只狼', '大表哥', '黑神话悟空'],
     ? ? ?files: ['《深海》', '《战狼》', '《流浪地球》']
     ?  }
      }
    }
    </script>
    <style lang="less" scoped>
    .container {
     ?display: flex;
     ?justify-content: space-around
    }
    img {
     ?width: 100%;
    }
    video {
     ?width: 100%;
    }
    </style>
     
  • 具名插槽的MyFooter

  • <template>
     ? ?<div class="category">
     ? ? ? ?<h3>{{ title }}分类</h3>
     ? ?
     ? ? ? ?<!-- <slot name=""></slot>为具名插槽,挖个坑等使用的组件填充坑的内容 -->
     ? ? ? ?<slot name="center">如果图片或视频未展示,展示此处的文字</slot>
     ? ? ? ?<slot name="footer">如果图片或视频未展示,展示此处的文字</slot>
     ? ? ? 
     ? ?</div>
    </template>
    ?
    <script>
    export default {
     ? ?name: 'MyFooter',
     ? ?props: ['title'],
    }
    </script>
    ?
    <style scoped lang="css">
     ? ?.category {
     ? ? ? ?background-color: skyblue;
     ? ? ? ?width: 200px;
     ? ? ? ?height: 300px;
     ?  }
     ? ?h3 {
     ? ? ? ?text-align: center;
     ?  }
    </style>
     
  • 作用域插槽理解:

    1、和上面两种插槽不同,作用域插槽数据(games) 在组件(MyFooter)但数据的结构需要组件的使用者(App)来决定

    2、在MyFooter通过slot传给App,App组件通过scope进行接收。

  • App组件(vm)的管家。App不仅是组件,也管理所有的组件

  • <template>
     ?<div class="container">
    ?
     ? ?<MyFooter title="游戏" >
     ? ? ?<!-- 要想接收MyFooter传过来的games需要写成template形式通过scope来接收传过来的值,注意这里不是scoped而是scope。 -->
     ? ? ?<template scope="boy">
     ? ? ? ? ?<ul >
     ? ? ? ? ? ?<!-- 通过{{ games }}可以知道,只有boy.games才可以拿到数组,games是MyFooter传过来的数组是不可以修改的。 -->
     ? ? ? ? ? ? ?<li ?v-for="(item, index) in boy.games" :key="index" >{{ item }}</li>
     ? ? ? ? </ul>
     ? ? ?</template>
     ? ?</MyFooter>
    ?
     ? ?<MyFooter title="游戏" >
     ? ? ?<!-- 可以将scope="xxx"改成slot-scope="xxx"。slot-scope="xxx"是新的书写方式 -->
     ? ? ?<template scope="boy">
     ? ? ? ? ?<ol >
     ? ? ? ? ? ? ?<li ?v-for="(item, index) in boy.games" :key="index" >{{ item }}</li>
     ? ? ? ? </ol>
     ? ? ?</template>
     ? ?</MyFooter>
    ?
     ? ?<MyFooter title="游戏" >
     ? ? ?<!-- 用ES6的形式写成{games},遍历的时候可以直接写games -->
     ? ? ?<template scope="{games}">
     ? ? ? ? ? ? ?<h4 ?v-for="(item, index) in games" :key="index" >{{ item }}</h4>
     ? ? ?</template>
     ? ? ?
     ? ?</MyFooter>
    ?
     ? ?<router-view />
     ?</div>
    </template>
    <script>
    import MyFooter from './components/MyFooter.vue';
    export default {
     ?name: 'App',
     ?components: { MyFooter }
    }
    </script>
    <style lang="less" scoped>
    .container {
     ?display: flex;
     ?justify-content: space-around
    }
    img {
     ?width: 100%;
    }
    video {
     ?width: 100%;
    }
    </style>
    ?
  • 作用域插槽的MyFooter组件

  • <template>
     ? ?<div class="category">
     ? ? ? ?<h3>{{ title }}分类</h3>
     ? ? ? ?<!-- :games="games"的意思是谁往插槽放数据games就传给谁 -->
     ? ? ? <slot :games="games"></slot>
     ? ?</div>
    </template>
    ?
    <script>
    export default {
     ? ?name: 'MyFooter',
     ? ?props: ['title','listDate'],
     ? ?data(){
     ? ? ? ?return {
     ? ? ? ? ? ?games: ['只狼', '大表哥', '黑神话悟空'],
     ? ? ?  }
     ?  }, ? 
    }
    </script>
    ?
    <style scoped lang="css">
     ? ?.category {
     ? ? ? ?background-color: skyblue;
     ? ? ? ?width: 200px;
     ? ? ? ?height: 300px;
     ?  }
     ? ?h3 {
     ? ? ? ?text-align: center;
     ?  }
    </style>
    ?

文章来源:https://blog.csdn.net/Yyds12300/article/details/135446037
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。