关于vue.js:Vue中vslot插槽详解

3次阅读

共计 7873 个字符,预计需要花费 20 分钟才能阅读完成。

  • 筹备工作

    • 搭建 vite
    • 装置 Windi CSS 或者 Tailwind

不应用插槽

<!--App.vue 父组件 -->
<template>
 <div class="container flex flex-row justify-center">
   <!-- 将 title 和 listData 数据传给子组件, 上面展现了两种应用组件形式 -->
   <Category title="动漫" :listData="cartoons"></Category>
   <Category title="游戏" :listData="games"/>
   <Category title="电影" :listData="films"/>
 </div>
</template>

<script>
import Category from './components/category.vue'
export default {
  name: 'App',
  components: {Category},
  data(){
    return{cartoons:['海贼王','名侦探柯南','一人之下','未闻花名'],
      games:['4399','斗地主','王者光荣','战争精英'],
      films:['《你好,李焕英》','《夏洛特搅扰》','《你的名字》','《蜘蛛侠》']
    }
  }
}
</script>

<style scoped>
.footer a {@apply ml-10;}
.container {background-image: url(https://cdn.jsdelivr.net/gh/ashunun/netbian/bian/1.jpg);
  @apply h-200 bg-auto bg-cover bg-contain;
}
</style>
<!-- category 组件子 -->
<template>
 <div>
     <h3>{{title}}分类 </h3>
      <ul>
        <li v-for="(item,index) in listData" :key="index">{{item}}</li>
      </ul>
 </div>
</template>

<script>
export default {
  name:'Category',
  //props 接管传过来的数据
  props:['listData','title']
}
</script>

<style scoped>
div{@apply bg-yellow-200 m-5 w-60 h-100 rounded-lg shadow-lg shadow-yellow-700/50;}
h3{@apply text-center bg-yellow-600 text-xl;}
</style>

默认插槽

<!--App.vue 父组件 -->
<template>
 <div class="container flex flex-row justify-center">
   <!-- 将 title 和 listData 数据传给子组件, 上面展现了两种应用组件形式 -->
   <Category title="动漫" :listData="cartoons">
     <img class="w-60" src="https://img2.baidu.com/it/u=4117582627,679171248&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500" alt="">
   </Category>
   <Category title="游戏" >
      <ul>
        <li v-for="(g,index) in games" :key="index">{{g}}</li>
      </ul>
   </Category>
   <Category title="电影">
     <video class="w-60" controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
   </Category>
 </div>
</template>

<script>
import Category from './components/category.vue'
export default {
  name: 'App',
  components: {Category},
  data(){
    return{cartoons:['海贼王','名侦探柯南','一人之下','未闻花名'],
      games:['4399','斗地主','王者光荣','战争精英'],
      films:['《你好,李焕英》','《夏洛特搅扰》','《你的名字》','《蜘蛛侠》']
    }
  }
}
</script>

<style scoped>
.footer a {@apply ml-10;}
.container {background-image: url(https://cdn.jsdelivr.net/gh/ashunun/netbian/bian/1.jpg);
  @apply h-200 bg-auto bg-cover bg-contain;
}
</style>
<!-- category 组件子 -->
<template>
 <div>
    <h3>{{title}}分类 </h3>
    <!-- 定义一个插槽,等着组件的使用者 (<Category> 填充内容 </Category>) 进行填充 -->
    <slot> 这里能够填写默认值,当组件使用者没有进行填充时,会显示 </slot>      
 </div>
</template>

<script>
export default {
  name:'Category',
  //props 接管传过来的数据
  props:['listData','title']
}
</script>

<style scoped>
div{@apply bg-yellow-200 m-5 w-60 h-100 rounded-lg shadow-lg shadow-yellow-700/50;}
h3{@apply text-center bg-yellow-600 text-xl;}
</style>

具名插槽

<!--App.vue 父组件 -->
<template>
 <div class="container flex flex-row justify-center">
    <!-- 将 title 和 listData 数据传给子组件, 上面展现了两种应用组件形式 -->
    <Category title="动漫" :listData="cartoons">
    <!-- 应用具名插槽,须要用 template 标签包裹着,并应用 v -slot:name -->
     <template v-slot:center>
        <img class="w-60" src="https://img2.baidu.com/it/u=4117582627,679171248&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500" alt="">
     </template>
     <template v-slot:foot>
         <a  href="https://image.baidu.com/search/index?tn=baiduimage&ct=201326592&lm=-1&cl=2&ie=gb18030&word=%B6%AF%C2%FE%CD%BC%C6%AC&fr=ala&ala=1&alatpl=normal&pos=0"> 更多照片 </a>
     </template>  
   </Category>
    <Category title="游戏" >
      <template v-slot:center>
          <ul>
            <li v-for="(g,index) in games" :key="index">{{g}}</li>
          </ul>
      </template>
       <template v-slot:foot>
          <div  class="footer">
            <a href="https://www.csdn.net/"> 手机游戏 </a>
            <a href="https://www.csdn.net/"> 电脑游戏 </a>
          </div>
      </template>
    </Category>
   <Category title="电影">
     <template v-slot:center>
         <video class="w-60" controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
     </template>
      <template v-slot:foot>
        <div class="footer">
            <a href="https://www.csdn.net/"> 经典 </a>
            <a href="https://www.csdn.net/"> 热门 </a>
            <a href="https://www.csdn.net/"> 举荐 </a>
       </div>
      </template>
   </Category>
 </div>
</template>

<script>
import Category from './components/category.vue'
export default {
  name: 'App',
  components: {Category},
  data(){
    return{//cartoons:['海贼王','名侦探柯南','一人之下','未闻花名'],
      games:['4399','斗地主','王者光荣','战争精英'],
      //films:['《你好,李焕英》','《夏洛特搅扰》','《你的名字》','《蜘蛛侠》']
    }
  }
}
</script>

<style scoped>
.footer a {@apply ml-10;}
.container {background-image: url(https://cdn.jsdelivr.net/gh/ashunun/netbian/bian/1.jpg);
  @apply h-200 bg-auto bg-cover bg-contain;
}
</style>
<!-- category 组件子 -->
<template>
 <div>
    <h3>{{title}}分类 </h3>
    <!-- 定义一个插槽,等着组件的使用者 (<Category> 填充内容 </Category>) 进行填充 -->
    <slot name="center"> 这里能够填写默认值,当组件使用者没有进行填充时,center 会显示 </slot>
    <slot name="foot"> 这里能够填写默认值,当组件使用者没有进行填充时,foot 会显示 </slot>    
 </div>
</template>

<script>
export default {
  name:'Category',
  //props 接管传过来的数据
  props:['listData','title']
}
</script>

<style scoped>
div{@apply bg-yellow-200 m-5 w-60 h-100 rounded-lg shadow-lg shadow-yellow-700/50;}
h3{@apply text-center bg-yellow-600 text-xl;}
</style>

作用域插槽

<!--App.vue 父组件 -->
<template>
 <div class="container flex flex-row justify-center">
  <!-- 将 title 和 listData 数据传给子组件, 上面展现了两种应用组件形式 -->
    <Category title="动漫" :listData="cartoons">
      <!-- 应用具名插槽,须要用 template 标签包裹着,并应用 v -slot:name -->
      <template v-slot:default="obj">
        <ul>
          <li v-for="(g, index) in obj.cartoons" :key="index">{{g}}</li>
        </ul>
      </template>
    </Category>
    <Category title="游戏">
      <!-- 默认插槽的 slot 简便写法 -->
      <template v-slot="obj">
        <ol>
          <li v-for="(g, index) in obj.games" :key="index">{{g}}</li>
        </ol>
        <ul>
          <li v-for="(g, index) in obj.msg" :key="index">🐱‍🐉插槽{{g}}</li>
        </ul>
      </template>
    </Category>
    <Category title="电影">
      <!-- 解构插槽 -->
      <template v-slot="{films, msg}">
        <div>
          <h4 v-for="(g, index) in films" :key="index">{{g}}</h4>
          <h3 v-for="(g, index) in msg" :key="index">🐱‍🐉插槽{{g}}</h3>
        </div>
      </template>
    </Category>
 </div>
</template>

<script>
import Category from './components/category.vue'
export default {
  name: 'App',
  components: {Category},
  data(){
    return{//cartoons:['海贼王','名侦探柯南','一人之下','未闻花名'],
      //games:['4399','斗地主','王者光荣','战争精英'],
      //films:['《你好,李焕英》','《夏洛特搅扰》','《你的名字》','《蜘蛛侠》']
    }
  }
}
</script>

<style scoped>
.footer a {@apply ml-10;}
.container {background-image: url(https://cdn.jsdelivr.net/gh/ashunun/netbian/bian/1.jpg);
  @apply h-200 bg-auto bg-cover bg-contain;
}
</style>
<!-- category 组件子 -->
<template>
 <div>
    <h3>{{title}}分类 </h3>
    <!-- 定义一个插槽,等着组件的使用者 (<Category> 填充内容 </Category>) 进行填充 -->
    <slot :cartoons="cartoons"> 默认插槽 </slot>
    <slot :games="games"> 默认插槽 </slot>
    <slot :films="films"> 默认插槽 </slot>
    <slot :msg="msg"></slot>  
 </div>
</template>

<script>
export default {
  name:'Category',
  //props 接管传过来的数据
  props: ["listData", "title"],
  data(){
    return{cartoons: ["海贼王", "名侦探柯南", "一人之下", "未闻花名"],
      games: ["4399", "斗地主", "王者光荣", "战争精英"],
      films: [
        "《你好,李焕英》",
        "《夏洛特搅扰》",
        "《你的名字》",
        "《蜘蛛侠》",
      ],
      msg: [",👀作用域", "芭比"],
    }
  }
}
</script>

<style scoped>
div{@apply bg-yellow-200 m-5 w-60 h-100 rounded-lg shadow-lg shadow-yellow-700/50;}
h3{@apply text-center bg-yellow-600 text-xl;}
</style>

动静插槽名

<!--App.vue 父组件 -->
<template>
  <div class="container flex flex-col justify-center items-center">
    <Category title="游戏">
      <!-- v-slot: 缩写法 # -->
      <template #[dynamicSlotName]="obj">
        <ol>
          <li v-for="(g, index) in obj.games" :key="index">{{g}}</li>
        </ol>
      </template>
    </Category>
    <button @click="change"> 点这切换 </button>
  </div>
</template>

<script>
import Category from "./components/category.vue";

export default {
  name: "App",
  components: {Category,},
  data() {
    return {dynamicSlotName: "1",};
  },
  methods: {change() {if (this.dynamicSlotName == "1") {this.dynamicSlotName = "2";} else this.dynamicSlotName = "1";
    },
  },
};
</script>

<style scoped>
.footer a {@apply ml-10;}
.container {background-image: url(https://cdn.jsdelivr.net/gh/ashunun/netbian/bian/1.jpg);
  @apply h-200 bg-auto bg-cover bg-contain;
}
button {
  @apply rounded-lg p-2 w-30 cursor-pointer bg-gradient-to-r from-violet-500 to-fuchsia-500 hover:from-violet-700 text-white shadow-lg shadow-indigo-700/80 text-center;
  border: none;
}
</style>
<!-- category 组件子 -->
<template>
 <div>
    <h3>{{title}}分类 </h3>
    <!-- 具名 + 作用域 插槽 -->
    <!-- 两个插槽,传递的数据不一样。-->
    <slot name="1" :games="games1"></slot>
    <slot name="2" :games="games2"></slot> 
 </div>
</template>

<script>
export default {
  name:'Category',
  //props 接管传过来的数据
  props: ["listData", "title"],
  data(){
    return{games1:['4399','斗地主','王者光荣','战争精英'],
      games2:['我的世界','cf','LOL','cs']
    }
  }
}
</script>

<style scoped>
div{@apply bg-yellow-200 m-5 w-60 h-100 rounded-lg shadow-lg shadow-yellow-700/50;}
h3{@apply text-center bg-yellow-600 text-xl;}
</style>

和具名插槽的缩写

v-onv-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #

<template #center>
</template>

残缺代码

代码

举荐一个减速软件——DivSidecar
意为为开发者打辅助的边车工具,通过本地代理的形式将 https 申请代理到一些国内的减速通道上
1、GitHub 打不开,减速 Github 很有用。
2、dns 优选(解决净化问题)
3、Stack Overflow 减速
4、npm 减速

正文完
 0