vue插槽

392 阅读1分钟

1. 普通插槽

目的:显示子组件标签中的内容 “这是个插槽”

父组件中:

<template>
  <div>
    <HelloWorld>这是个插槽</HelloWorld>
  </div>
</template>

<script>
import HelloWorld from "@/components/HelloWorld.vue";
export default {
  components: {
    HelloWorld,
  },
  data() { return {}; },
};
</script>
<style scoped lang="less"></style>

子组件中:

<template>
  <div class="hello">
    <slot>这里是默认内容...</slot> //后备内容 如果父组件里没有设置 ‘这是个插槽’,就显示 ‘这里是默认内容...’
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
};
</script>
<style scoped lang="less"></style>

image.png

2. 具名插槽

目的:子组件里需要有多个插槽,
    ~格式:定义:<slot name="top"></slot> 使用:**v-slot : ‘插槽名’**,不设置名称是默认插槽
    ~缩写:#插槽名

父组件:

<template>
  <div class="home">
    <!-- 具名插槽 start -->
    <tmpSlot>
      <!-- v-slot 只能添加在template标签上(如果只有默认插槽,则可以直接用在组件上,没有name,就是默认的) -->
      <template v-slot:top> 这是头部 </template>
      <template> 这是内容(默认插槽) </template>
      <template v-slot:foot> 这是结尾 </template>
      <!-- 缩写 -->
      <template #suoName> 这是具名插槽缩写 </template>
    </tmpSlot>
    <!-- 具名插槽 end -->
  </div>
</template>

<script>
// @ is an alias to /src
import tmpSlot from "./component/tmpSlot.vue";

export default {
  name: "Home",
  components: {
    tmpSlot,
  },
  data() {
    return {
      msg: "hello",
    };
  },
};
</script>

子组件:

<template>
  <div class="tmp">
    <p>这是具名插槽页</p>
    <!-- <slot></slot> -->
    <div class="container">
      <header>
        <!-- 页头 -->
        <slot name="top"></slot>
      </header>
      <main>
        <!-- 内容 -->
        <slot></slot>
      </main>
      <footer>
        <!-- 页脚 -->
        <slot name="foot"></slot>
      </footer>
      <nav>
        <!-- 增加缩写插槽名 -->
        <slot name="suoName"></slot>
      </nav>
    </div>
  </div>
</template>
<style scoped>
.tmp {
  width: 600px;
  height: 150px;
  background-color: antiquewhite;
}
</style>

image.png

3. 作用域插槽

目的:希望在父组件能获取子组件的变量
    ~实现:子组件中绑定:list=list
                  父组件中<template v-slot:default="slotProp">{{ slotProp.list.name }}</template> 父组件:

<template>
  <div class="home">
    <!-- 作用域插槽 start -->
    <areaSlot>
      <template v-slot:default="slotProp">{{ slotProp.list.name }}</template>
    </areaSlot>
     <!-- 作用域插槽 end -->
     
    <!-- 简写  是默认插槽并且只有一个-->
    <areaSlot v-slot="slotProps">
      {{ slotProps.list.name }}
    </areaSlot>
   
  </div>
</template>

<script>
import areaSlot from "./component/areaSlot.vue";

export default {
  name: "Home",
  components: {
    areaSlot,
  },
  data() {
    return {
      msg: "hello",
    };
  },
};
</script>

子组件:

<template>
  <div class="area">
    <p>这是作用域插槽页</p>
    <div class="s">
      <slot :list="list">{{ list.age }}</slot> //标签里是后备内容
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      list: { name: "张三", age: 19, newName: "张小小" },
    };
  },
};
</script>
<style scoped lang="less">
.area {
  width: 400px;
  height: 200px;
  background-color: lightpink;
  .s {
    margin-top: 10px;
  }
}
</style>


image.png

4. 解构插槽

按照官方来说:

作用域插槽的内部工作原理是将你的插槽内容包裹在一个拥有单个参数的函数里:

function (slotProps) { 
        // 插槽内容 
    }

因此 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。所以在支持的环境下 (单文件组件现代浏览器),你也可以使用 ES2015 解构来传入具体的插槽 prop

 <!-- 解构插槽 start -->
    <areaSlot v-slot="{ list }">
      {{ list.age }}
    </areaSlot>
    
 <!-- 可以重命名 -->
    <areaSlot v-slot="{ list: newist }">
      {{ newist.newName }}
    </areaSlot>
    
 <!-- 可以给定义后备内容 -->
    <areaSlot v-slot="{ list = { name: '王一一' } }">
      {{ list.name }}
    </areaSlot>
    <!-- 解构插槽 end -->

这使作用域插槽更简洁