前言
vue 为我们提供了很多复用性的方式,slot 和 mixins 就是其中两种...下面对这两种方式做一下记录
插槽使用场景
- 该组件被多个地方使用
- 每个父组件中对该组件的内部有一部分需要特殊定制
- slot可以让我们更好的复用组件的同时并对其定制化处理
- 可以理解为父组件想子组件传递了一段 html 文本
要求:
1.子组件模板包含至少一个 插槽 <slot></slot>
2.父组件整个内容片段将插入到 slot 所在的 DOM 位置,并替换掉 slot 标签本身
1.普通插槽 slot
父组件: 负责分发插槽内容
<child ref=child>
我是父组件分发给 child 的所有内容
</child>
父组件获取子组件可以通过 this.$refs.child 来做操作
子组件: <template>
<slot>这里可以放一些默认值</slot>
</template>
模板中放置一个 <slot></slot>组件,
我们可以自定义组件中的方法和数据,封装一些通用逻辑,比如前几篇中封装的 scroll滚动组件
2.具名插槽 子组件通过 name 属性 来匹配父组件分发的内容
父组件: 添加 slot 属性来作为标识
<div slot="header">我是 header 分发的内容 111</div>
<div slot="main">我是 main 分发的内容222</div>
<div slot="footer">我是 footer 分发的内容333</div>
在2.6.0 以上使用的是 v-slot:header; 默认插槽为: v-slot:default
子组件: slot 添加 name 属性来接受父组件分发的 DOM 元素
<template>
<slot name="header"></slot>
<slot name="main"></slot>
<slot name="footer"></slot>
</template>
当然,我们还可以调换插槽的位置...
3.作用域插槽 父组件可以接收来自子组件的 slot 传递过来的参数值
可以理解为: 子组件中的作用域插槽可以为父组件中的插槽的展示提供数据
子组件:
<template>
<div>
<slot name="header" :value="value"></slot>
</div>
</template>
<script>
export default {
data() {
return {
value: '我是子组件的值'
}
}
}
</script>
父组件:
<child>
<template slot="header" slot-scope="slotHeaderProps">
渲染子组件传过来的对象中 value值{{ slotHeaderProps.value }}
</template>
</child>
在 2.6 以上绑定值的方式: v-slot:header="slotHeaderProps"
而且可以使用解构 v-slot:header="{value}", 将子组件传过来的值解构
还有就是, 我们可以把 slot直接写在子组件行内, 不必另起一个 template
即这样: <child v-slot:header="{value}">{{value}}</child>
vue3.0以后 slot 和 slot="xxx",slot-scope 的方式会被废弃...
新的用法slot, v-slot:xxx || v-slot:default, v-slot:xxx="slotProps"
简写: v-slot:header 可以被重写为 #header
混入 Mixins 使用
- 也是为了实现代码逻辑复用
- 当多个组件中出现业务逻辑重复时我们就可以抽离重复代码片段,写成一个混入对象
- 父组件直接引入这个对象
代码演示
就拿一个比较常见的场景: 下拉加载更多数据; 这类业务在H5端可以说是非常常见了,当我们很多页面都要用到时,就可以抽离成一个混入对象
// 滚动加载
import {throttle} from "@/common/js/tool";
export const scrollMixin = {
methods: {
doScrollLoading() {
// 滚动超出高度
let scrollTop =
window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop;
// 滚动区域高度
let scrollHeight =
document.body.scrollHeight || document.body.scrollHeight;
// 可视区高度
let clientHeight =
document.documentElement.clientHeight || document.body.clientHeight;
if (scrollHeight - clientHeight - scrollTop <= this.bottomHeight) {
// 组件中需加入开关和加载更多; 还是有些耦合了...
if (!this.isLoadMore) {
this.loadMore();
}
}
}
},
computed: {
bottomHeight() {
return this.$store.state.footerHeight;
}
},
mounted() {
window.addEventListener("scroll", throttle(this.doScrollLoading, 100, 1));
},
destroyed() {
window.removeEventListener("scroll", throttle(this.doScrollLoading, 100, 1));
}
}
父组件中引入使用
import { scrollMixin } from "@/mixins/scrollMixin";
mixins: [scrollMixin]
注意组件中重写的方法会覆盖混入中的方法,loadMore和 isloadMore 需要在
引用的组件中进行重写
总结
当混合对象与组件包含同名选项时,这些选项将以适当的策略合并。例如,同名钩子函数被并入一个数组,因而都会被调用。另外,混合的钩子将在组件自己的钩子之前调用。
值为对象的选项,如 methods, components 和 directives 将合并到同一个对象内。如果键冲突则组件的选项优先。
组件:在父组件中引入组件,相当于在父组件中给出一片独立的空间供子组件使用,然后根据props来传值,但本质上两者是相对独立的。
Mixins:则是在引入组件之后与组件中的对象和方法进行合并,相当于扩展了父组件的对象与方法,可以理解为形成了一个新的组件。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。