玩转vue的slot内容分发
vue的内容分发非常适合“固定部分+动态部分”的组件的场景,固定部分可以是结构固定,也可以是逻辑固定,比如下拉loading,下拉loading只是中间内容是动态的,而拉到底部都会触发拉取更多内容的操作,因此我们可以把下拉loading做成一个有slot的插件。
单个Slot
在children这个标签里面放Dom,Vue不会理你,也就是不会显示,类似React:this.props.children。
//父
<children>
<span>12345</span>//这边不会显示
</children>
//子
components: {
children: {
template: "<button>为了明确作用范围,所以使用button标签</button>"
}
}
你需要写成这样
children: {
template: "<button><slot></slot>为了明确作用范围,所以使用button标签</button>"
}
注意这边 slot 相当于一个坑,等着父组件给填上,这边 slot 代表的就是上面的 span
多个Slot
这边需要加name属性,说白了,多个Slot就不像上面单个,需要有个对应关系。
父-> slot="name1"
子-> <slot name="name1"
//父
<children>
<span slot="name1">12345</span>
</children>
//子
components: {
children: {
template: "<button>
<slot name="name1"></slot>
button标签
</button>"
}
}
这边写了一个name1,如果有多个,就插多个,比较简单。
使用场景
“下拉加载更多”的场景在移动端相对来说出现得比较多。我们知道下拉触底都要监听触底事件,触底的操作也相同(去后台拉取数据),分页算法也相同,因此我们会想到把它做成一个组件,重用这些相同的地方,让其他地方可以共用这个组件,从而减少代码量。
然而,下拉loading并不是一个可以完全重用的组件,因为列表里面的内容不同,空白页(没有内容时)的内容也可能不同,如果要做成组件,那么就要考虑到这方面的“不同”,因此我们想到利用vue的内容分发slot来做。下面是本人在开发的时候做的一个下拉loading,大家可以参考下。
组件代码:
<template>
<div>
<slot name="list" v-if="total > 0"></slot>
<slot name="empty" v-else></slot>
</div>
</template>
<script>
import Toast from 'lib/xl-toast'
import Tool from 'tool/tool'
export default {
data() {
return {
page: 1,
isLoading: false,
busy: false,
isFirstLoad: false
}
},
props: {
pageSize: {
default: 10 // 每页展示多少条数据
},
total: {
default: 0 // 总共多少条记录
}
},
computed: {
totalPage() {
return Math.ceil(this.total / this.pageSize)
}
},
created() {
this.getList()
},
mounted() {
this.addScrollListener()
},
methods: {
addScrollListener() {
// 添加监听滚动操作,用到函数防抖
this.scrollFn = Tool.throttle(this.onScroll, 30, 30)
document.addEventListener('scroll', this.scrollFn, false)
},
getList() {
// 正在拉取数据或者没有数据了,则取消滚动监听
if(this.isLoading || this.isFirstLoad && (this.page > this.totalPage)) {
document.removeEventListener('scroll', this.scrollFn, false)
return
}
this.busy = true
this.isLoading = true
// 通知父组件去拉取更多数据
this.$emit("getList", this.page, () => {
this.isFirstLoad = true
this.isLoading = false
this.page++
}, () => {
Toast.show('网络错误,请稍后重试')
this.total = 0
this.isLoading = false
})
},
reset() {
// 重新拉取数据
this.page = 1
this.total = 0
this.isLoading = false
this.isFirstLoad = false
this.addScrollListener()
this.getList()
},
onScroll() {
// 到底拉取更多数据
if(Tool.touchBottom()) {
this.getList()
}
}
}
}
</script>
前端全栈学习交流圈:866109386,面向1-3经验年前端开发人员,帮助突破技术瓶颈,提升思维能力,群内有大量PDF可供自取,更有干货实战项目视频进群免费领取。
总之,遇到一些有想对比较固定的部分,包括js操作或者结构固定,又有一些动态的部分,我们应该就应该考虑到使用:组件+slot。
意向不到的slot另类用法
我在做需求的时候,做了一个组件,该组件分为上下两个部分,这两个部分耦合度很高(不然我怎么把它当成一个组件呢哈哈哈),如下图所示:
本来C区域是一个组件,然后产品突然说,需要把这两个部分分开,把A移到C1的位置,C1移到A的位置(心里感觉到憋屈)。
这里我的第一个想法就是拆开来做成两个组件,但是问题来了,之前这两部分的耦合度很高,如果强制把它拆开成两个组件,那么这两个组件之间的交互必然会多很多。比如,C1改变了某个东西会影响到C2,那么C1需要触发事件通知父组件,父组件再调用C2的某个方法来更新状态。这种跨组件之间的通讯在组件之间频繁交互的情况下,将会是噩梦,而我这边却需要频繁的交互,所以如果把它拆分为两个组件,那么工作量和复杂度将会大大的增加。当然,你可以想到通过Event Hub的方式来实现两个组件之间的交互,但是根本问题还是没有实质性得得到解决。
那么,有什么方法可以做到不拆分成两个组件又能移动位置的方法呢,答案就是slot。以我的例子为例,把A和B作为C的内容分发,原来是这样的:
<A></A>
<B></B>
<C></C>
改为slot以后是这样的
<C>
<A slot="c1"></A>
<B slot="c2"></B>
</C>
这样就能做到不把C模块拆分,又能调整位置了,以最小的代价完成需求~~。
总结
vue的slot不仅可以用来内容分发,还可以用来做位置调整。如果在需要拆分组件来做位置调整,又不想因为拆分耦合度很高的组件,可以考虑使用slot来进行位置调整。一点愚见,希望对大家有所帮助。
原文链接:https://my.oschina.net/u/3970421/blog/2993054
玩转vue的slot内容分发的更多相关文章
- Vue中slot内容分发
<slot>元素是一个内容分发API,使用多个内容插槽时可指定name属性 <!DOCTYPE html> <html> <head> <meta ...
- vue slot内容分发
当需要让组件组合使用,混合父组件的内容和子组件的模板的时候,就会用到slot.这个过程就叫内容分发. 最为常用的是两种slot:一种是匿名slot, 一种是具名slot. 匿名 很好理解: 就是默认, ...
- slot内容分发
vue实现了一套内容分发的API,这套API基于当前的web components规范草案,将<slot>元素作为承载分发内容的出口. 在前面的父子组件中,我们提到过,在vue中,组件实例 ...
- 使用slot-scope复制vue中slot内容
有时候我们的vue组件需要复制使用者传递的内容. 比如我们工程里面的轮播组件需要使用复制的slot来达到循环滚动的效果 使用者关注轮播内容的静态效果,组件负责让其滚动起来 组件: <div cl ...
- Vue结合slot插槽分发父组件内容实现高度复用、更加灵活的dialog组件
之前写过一篇关于vue实现dialog会话框组件的文章(http://www.cnblogs.com/fozero/p/8546883.html)[http://www.cnblogs.com/foz ...
- Vue中的slot内容分发
①概述: 简单来说,假如父组件需要在子组件内放一些DOM,那么这些DOM是显示.不显示.在哪个地方显示.如何显示,就是slot分发负责的活. ②默认情况下 父组件在子组件内套的内容,是不显示的. 例如 ...
- 使用Vue的slot插槽分发父组件内容实现高度复用、更加灵活的组件
写在前面 之前写过一篇关于vue实现dialog会话框组件的文章http://www.cnblogs.com/fozero/p/8546883.html, 讲到了如何实现一个vue对话框组件,其中涉及 ...
- Vuejs——(11)组件——slot内容分发
版权声明:出处http://blog.csdn.net/qq20004604 目录(?)[+] 本篇资料来于官方文档: http://cn.vuejs.org/guide/components ...
- Vuejs——slot内容分发
①概述: 简单来说,假如父组件需要在子组件内放一些DOM,那么这些DOM是显示.不显示.在哪个地方显示.如何显示,就是slot分发负责的活. ②默认情况下父组件在子组件内套的内容,是不显示的. 例如代 ...
随机推荐
- java_缓冲流(文件内容排序)
/** 案例:诸葛亮出师表文本排序 * 1.使用HashMap集合,k存储每行文本序,v存储文本 * 2.创建字符缓冲输入流,构造方法中绑定字符输入流 * 3.使用字符串缓冲输入流中的方法readLi ...
- java_Collections工具
** * Collections.addAll(List,多个元素): * Collections.shuffle(List):打乱顺序 * sort(List):将集合中元素按照默认规则排序 * s ...
- SQLServer 2008 还原数据库备份版本不兼容的问题
我们准备还原一个数据库备份的时候,经常会弹出这样的错误:System.Data.SqlClient.SqlError: 该数据库是在运行版本 10.50.1600 的服务器上备份的.该版本与此服务器( ...
- bzoj1010: [HNOI2008]玩具装箱toy——斜率优化
方程 $\Large f(i)=min(f(j)+(s(i)-s(j)-1-L)^2)$ 其中$s(i)$为i的前缀和再加上$i$ 对于某个$i$若$j$比$k$优,则 $\large f(j)+(s ...
- Qt : 隐式数据共享(copy on write)
copy on write 意思当内容有变动的时候,才对容器中的数据结构进行复制.否则仅作共享. QT许多类中使用了隐式数据共享技术,来最大化资源利用率和最小化拷贝时的资源消耗. 在数据传递时,其实只 ...
- loj2212 方伯伯的OJ
题意: n<=1e8,m<=1e5. 标程: #include<cstdio> #include<algorithm> #include<cstring> ...
- Codeforces Parking Lot
http://codeforces.com/problemset/problem/630/I 简单的排列组合,推式子技巧:举一个小样例,看着推,别抽象着推,容易错 #include <iostr ...
- windows安装apache系统中无apache2服务解决方案
一直都是用WIN开发PHP,今天有用户反映SHUGUANG CMS在APACHE+PHP中不能正常运行,只好自己机器配置个环境测试(http://xz.8682222.com)遇到点小问题,搜索相关资 ...
- Ubuntu下安装和配置Apache2,小编觉得挺不错的,现在就分享给大家
本篇文章主要介绍了详解Ubuntu下安装和配置Apache2,小编觉得挺不错的,现在就分享给大家,也给大家做个参考.有兴趣的朋友可以了解一下.(http://xz.8682222.com) 在Ubun ...
- ConcurrentHashMap 和 Hashtable 的区别
ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的方式上不同. 1.底层的数据结构: ConcurrentHashMap 在jdk1.7之前采用的是 分段的数组 ...