Vue中插槽的简单使用

插槽

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

  • 默认插槽:让父组件可以向子组件指定位置插入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>
  • 15
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值