Vue2.x 插槽slot学习笔记
Posted 胖鹅68
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue2.x 插槽slot学习笔记相关的知识,希望对你有一定的参考价值。
文章目录
一、slot插槽分类——具名插槽、默认插槽
具名插槽
- 具名插槽定义(三种)
<div>
<slot name="up"></slot>
</div>
<div>
<span slot="up"></span>
</div>
<div>
<template v-slot:up></template>
</div>
- 具名插槽使用(四种)
<组件名>
<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名字)
- 默认插槽定义
一个不带 name 的 出口会带有隐含的名字“default”
<div>
<slot></slot>
</div>
template 和 v-slot:default 配合使用
<div>
<template v-slot:default></template>
</div>
- 默认插槽的使用
不需要任何包裹
<组件名>
<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>
</组件名>
案例
- 组件定义插槽的位置(组件模板)
<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>
- 使用组件
<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 绑定上去
作用域与定义作用域的组件无关(只起到占位符的作用),只与使用组件的父组件有关系(因为是父组件传递参数)
具名插槽作用域
- 插槽名字是up, 作用域的变量名是 user
<div>
<template v-slot:up="user">
{{ user.lastName }}
</template>
</div>
- 插槽名字是 header, 作用域的变量名是 user
<span>
<slot v-bind:header="user">
{{ user.lastName }}
</slot>
</span>
默认插槽作用域
<组件名 v-slot="slotProps">
<current-user v-slot="user">
<slot>{{ user.lastName }}</slot>
</current-user >
<组件名 v-slot:default="slotProps">
<current-user v-slot:default="user">
<slot>{{ user.lastName }}</slot>
</current-user >
<组件名><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 概念
- 用来访问被插槽分发的内容。
每个具名插槽有其相应的 property (例如:v-slot:foo 中的内容将会在 vm.$slots.foo 中被找到)。
- default property 包括了所有没有被包含在具名插槽中的节点,或 v-slot:default 的内容
案例说明
- 父组件
<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>
- 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>
- 结果
- 父组件的$slots 为空对象
- 子容器的子组件有四个,不由子容器实现决定:
- huangbiao 这个插槽在子容器没有实现
- 插槽的内部实际上是虚拟dom的实现
思维导图和附件
以上是关于Vue2.x 插槽slot学习笔记的主要内容,如果未能解决你的问题,请参考以下文章