Vue2.x 插槽slot学习笔记

Posted 胖鹅68

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue2.x 插槽slot学习笔记相关的知识,希望对你有一定的参考价值。

一、slot插槽分类——具名插槽、默认插槽

具名插槽

  1. 具名插槽定义(三种)
<div>
	<slot name="up"></slot>
</div>
<div>
	<span slot="up"></span>
</div>
<div>
	<template v-slot:up></template>
</div>
  1. 具名插槽使用(四种)
<组件名>
	<template v-slot:header>
	  <h1>Here might be a page title</h1>
	</template>
</组件名>

v-slot 只能添加在 <template>

等价于

<组件名>
	<template #header>
	  <h1>Here might be a page title 222</h1>
	</template>
</组件名>

等价于

<组件名>
	<h1 slot="header">Here might be a page title</h1>
</组件名>

等价于

<组件名>
	<slot name="header">
	  <h1>Here might be a page title111</h1>
	</slot>
</组件名>

默认插槽(没有slot名字)

  1. 默认插槽定义

一个不带 name 的 出口会带有隐含的名字“default”

<div>
	<slot></slot>
</div>

template 和 v-slot:default 配合使用

<div>
	<template v-slot:default></template>
</div>
  1. 默认插槽的使用

不需要任何包裹

<组件名>
	<p>A paragraph for the main content.111</p>
	<p>And another one.</p>
</组件名>

使用v-slot

<组件名>
	<template v-slot:default>
	  <p>A paragraph for the main content.111</p>
	  <p>And another one.</p>
	</template>
</组件名>

案例

  1. 组件定义插槽的位置(组件模板)
<template>
  <div class="container">
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

<script>
export default {
  data() {
    return {};
  },
  mounted() {},
  methods: {}
};
</script>

<style lang="scss" scoped></style>
  1. 使用组件
<template>
  <div class>
    1111
    <SlotContainer ref="slotContainer">
      <!-- <template v-slot:header>
        <h1>Here might be a page title</h1>
      </template> -->
      <!-- 等价于 -->
      <template #header>
        <h1>Here might be a page title 222</h1>
      </template>
      <!-- 等价于 -->
      <!-- <slot name="header">
        <h1>Here might be a page title111</h1>
      </slot> -->

      <!-- <p>A paragraph for the main content.222</p>
      <p>And another one.</p> -->

      <!-- <template v-slot:default>
        <p>A paragraph for the main content.111</p>
        <p>And another one.</p>
      </template> -->

      <template v-slot:footer>
        <p>Here's some contact info</p>
      </template>
    </SlotContainer>
  </div>
</template>

<script>
import SlotContainer from "./SlotContainer";
window.SlotContainer = SlotContainer
console.log(SlotContainer);
debugger
export default {
  data() {
    return {};
  },
  components: {
    SlotContainer
  },
  mounted() {
    console.log(this.$slots);
    console.log(this.slotContainer.$slots);
    debugger;
  },
  methods: {}
};
</script>

<style lang="scss" scoped></style>

二、作用域插槽

原则: 父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

解决办法:为了让 user 在父级的插槽内容中可用,我们可以将 user 作为 元素的一个 attribute 绑定上去

作用域与定义作用域的组件无关(只起到占位符的作用),只与使用组件的父组件有关系(因为是父组件传递参数)

具名插槽作用域

  1. 插槽名字是up, 作用域的变量名是 user
<div>
	<template v-slot:up="user">
		{{ user.lastName }}
	</template>
</div>
  1. 插槽名字是 header, 作用域的变量名是 user
<span>
  <slot v-bind:header="user">
    {{ user.lastName }}
  </slot>
</span>

默认插槽作用域

  1. <组件名 v-slot="slotProps">
<current-user  v-slot="user">
  <slot>{{ user.lastName }}</slot>
</current-user >
  1. <组件名 v-slot:default="slotProps">
<current-user  v-slot:default="user">
  <slot>{{ user.lastName }}</slot>
</current-user >
  1. <组件名><template v-slot:default="slotProps"></组件名>
<current-user >
  <template v-slot:default="user">
	{{ user.lastName }}
  <template>
</current-user >

具名插槽和默认插槽混合使用

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>

  <template v-slot:other="otherSlotProps">
    ...
  </template>
</current-user>

默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确,错误示范:

<!-- 无效,会导致警告 -->
<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
  <template v-slot:other="otherSlotProps">
    slotProps is NOT available here
  </template>
</current-user>

三、API $slots

$slots 概念

  1. 用来访问被插槽分发的内容。
  2. 每个具名插槽有其相应的 property (例如:v-slot:foo 中的内容将会在 vm.$slots.foo 中被找到)。
  3. default property 包括了所有没有被包含在具名插槽中的节点,或 v-slot:default 的内容

案例说明

  1. 父组件
<template>
  <div class>
    1111
    <SlotContainer ref="slotContainer">
      <!-- <template v-slot:header>
        <h1>Here might be a page title</h1>
      </template> -->
      <!-- 等价于 -->
      <!-- <template #header>
        <h1>Here might be a page title 22233</h1>
      </template> -->
      <!-- 等价于 -->
      <h1 slot="header">Here might be a page title</h1>
      <!-- 等价于 -->
      <!-- <slot name="header">
        <h1>Here might be a page title111</h1>
      </slot> -->

      <!-- <p>A paragraph for the main content.222</p>
      <p>And another one.</p> -->

      <h1 slot="huangbiao">Here might be a page title</h1>

      <template v-slot:default>
        <p>A paragraph for the main content.</p>
        <p>And another one.</p>
      </template>

      <template v-slot:footer>
        <p>Here's some contact info</p>
      </template>
    </SlotContainer>
  </div>
</template>

<script>
import SlotContainer from "./SlotContainer";
// window.SlotContainer = SlotContainer
// console.log(SlotContainer);
// debugger
export default {
  data() {
    return {};
  },
  components: {
    SlotContainer
  },
  mounted() {
    // 容器组件中的 $slots, 没有任何数据
    console.log(this.$slots);
    // 找到容器组件的slots,定义了 header default  footer三个插槽,里面的数据是以虚拟dom展现
    console.log(this.$refs.slotContainer.$slots);
    debugger
  },
  methods: {}
};
</script>

<style lang="scss" scoped></style>
  1. slot的子组件
<template>
  <div class="container">
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

<script>
export default {
  data() {
    return {};
  },
  mounted() {},
  methods: {}
};
</script>

<style lang="scss" scoped></style>
  1. 结果
    在这里插入图片描述
    1. 父组件的$slots 为空对象
    2. 子容器的子组件有四个,不由子容器实现决定:
      1. huangbiao 这个插槽在子容器没有实现
      2. 插槽的内部实际上是虚拟dom的实现

思维导图和附件

vue插槽slot学习
在这里插入图片描述

以上是关于Vue2.x 插槽slot学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

简单对比vue2.x与vue3.x响应式及新功能

VUE学习笔记:12.组件化之:slot组件插槽讲解

Vue笔记:插槽(slot)

在 @html 中使用插槽

Vue第四天学习笔记之组件化高级

Vue学习笔记入门篇——组件的内容分发(slot)