- 做者:陈大鱼头
- github: KRISACHAN
不知道各位童鞋有木有看过 《等待戈多》 这部出名的荒诞戏剧 。其剧情大概就是 戈戈 与 狄狄 等待 戈多 的过程当中发生的一些杂事,一共两幕。等了这么多年,也不知道 戈多 如今在哪,赴约了没有。javascript
若是 戈戈 与 狄狄 像咱们监听页面元素变化那样监听戈多的动态,是否是就不会出现空欢喜的状态?是否是就不用等得那么辛苦?是否是甚至能够主动去寻找戈多?css
提及监听页面元素变化,那么你可知道有哪些方法能够实现这个功能?html
关于 Object.defineProperty
这个属性你们应该很熟(毕竟是各种面经中的常客),但仍是要简单介绍下~java
Object.defineProperty
容许精确添加或修改对象的属性。经过赋值操做添加的普通属性是可枚举的,可以在属性枚举期间呈现出来。git
描述符可同时具备的键值:github
configurable | enumerable | value | writable | get | set | |
---|---|---|---|---|---|---|
数据描述符 | Yes | Yes | Yes | Yes | No | No |
存取描述符 | Yes | Yes | No | No | Yes | Yes |
因此咱们有如下这种效果:数组
代码以下:微信
'use strict'
Object.defineProperty(godot, 'style', {
get() {
return this.getAttribute('style')
},
set(data) {
this.setAttribute('style', data)
const distance = (noLeftTree.offsetLeft - this.offsetLeft)
console.log(distance >= 51 ? '戈多没来,咱们先各自干各自的活吧' : '戈多快到了,走,咱们集合去')
}
})
const whereIsGodot = start => {
if (start) {
let d = 0
const godotRun = () => {
if (noLeftTree.offsetLeft - 51 >= d) {
setTimeout(() => {
d++
godot.style = `left: ${d}px`
godotRun()
}, 16)
}
}
godotRun()
}
}
复制代码
简单来讲就是使用 Object.defineProperty
监听戈多的位置变化,而后当戈多移动到集合地点附近时,等待戈多的俩哥们就能够去赴约了。经过上述的代码,咱们能够知道 whereIsGodot
函数只负责戈多的位置移动,可是监听权在等待戈多的两我的那里,这样保证了代码语义化的同时,耦合度也尽量地小。dom
Mmmmm,我一直觉得 MutationObserver
是个新属性,直到我膝盖中了一箭看了can i use 。函数
原本鱼头我也不知道有这属性,可是最近在工做上遇到了须要监听页面元素变更的场景,而后就了解到了这个API。
因而鱼头便看了文档,发现是个好牛逼的API。
简单来讲就是一个能够监听 DOM Tree 变更的API,名字直译就是 “突变观察者” 。
按WHATWG的定义,它的执行逻辑以下:
突变观察者 是个构造器,它接受一个回调并返回一个 节点记录列表(sequence <MutationRecord>
) 以及 构造的参数对象(MutationObersver)。
它有如下三个方法:
options选项可选参数(如下属性可设置为true):
下面咱们就经过实际的代码来监听戈多的位置变化。
效果仍是如同上图。
代码以下:
const godot = document.querySelector('#godot')
const config = {
childList: true,
attributes: true,
characterData: true,
subtree: true,
attributeOldValue: true,
characterDataOldValue: true
}
const mutationCallback = mutationsList => {
const [
{
target: {
offsetLeft: godotPos
}
}
] = mutationsList
const distance = (noLeftTree.offsetLeft - godotPos)
console.log(distance >= 51 ? '戈多没来,咱们先各自干各自的活吧' : '戈多快到了,走,咱们集合去')
}
const observer = new MutationObserver(mutationCallback)
observer.observe(godot, config)
const whereIsGodot = start => {
if (start) {
let d = 0
const godotRun = () => {
if (noLeftTree.offsetLeft - 51 >= d) {
setTimeout(() => {
d++
godot.style = `left: ${d}px`
godotRun()
}, 16)
} else {
observer.disconnect()
}
}
godotRun()
}
}
复制代码
由于鱼头在业务须要对某个已经完善的功能在部分操做监听数据变更,若是对原来的代码进行改动,也不是一件轻松的事,并且这样子代码太冗长,耦合度也会较高,因此就选择了用 突变观察者 来实现,效果仍是不错的。
除了监听元素的变更,还有什么方式能够知道戈多的位置呢?
若是有那就是 Intersection Observer 了。
戈多心想:“又来一个Observer ?别监听了,我去找大家就是了,嘤嘤嘤。 ”
IntersectionObserver
直译是 “交叉观察者” ,这个API使开发人员可以监听目标元素与根(祖先或视口)元素交叉状态的方法。
它的用法跟 MutationObserver
类似,一样是个构造器,它接受一个 回调函数(callback(entries)) 以及 可选参数对象(options) 。
首先 callback 会返回一个 监听属性对象(IntersectionObserverEntry) ,其具体属性以下:
getBoundingClientRect()
的值,没有则返回 null
;intersectionRect / boundingClientRect
彻底可见时为1,彻底不可见时小于等于0;options 可选参数以下:
margin
同样,发生交叉的偏移量;可选择方法以下:
IntersectionObserver
中止监听特定目标元素。因此怎么用这个API来监听戈多的位置呢?
先看效果(真特么简陋)
代码以下:
<style> * { margin: 0; padding: 0; box-sizing: border-box; } html, body { width: 100%; height: 200%; } noLeftTree { position: fixed; left: 0; top: 0; width: 100%; height: 100px; background: #FFF; } godot, estragon, vladimir { position: absolute; width: 50px; height: 50px; border-radius: 50%; border: 1px solid; text-align: center; } estragon { top: 0; left: 0; } vladimir { top: 0; right: 0; } godot { left: calc(50% - 25px); top: 1000px; } </style>
<noLeftTree id="noLeftTree">
<estragon id="estragon">戈戈</estragon>
<vladimir id="vladimir">狄狄</vladimir>
</noLeftTree>
<godot id="godot">戈多</godot>
<script> 'use strict' const godot = document.querySelector('#godot') const noLeftTree = document.querySelector('#noLeftTree') const ioCallback = entries => { console.log(entries[0].intersectionRatio <= 0 ? '戈多没来,咱们先各自干各自的活吧' : '戈多快到了,走,咱们集合去') } const ioConfig = { threshold: [0, 0.25, 0.5, 0.75, 1] } const io = new IntersectionObserver(ioCallback, ioConfig) io.observe(godot) </script>
复制代码
其实若是肯花时间去研究,利用好上述三个API,是能够实现不少颇有趣的效果的,上面的只是一个初尝的DEMO,真正在项目里是能够实现不少很重要的功能。
不过戈戈 与 狄狄也等待戈多快70年了,就像痴情的女生等待远走的渣男同样,就是不来好歹也给个音信啊。
戈多心想:“我不过是迷路了么,嘤嘤嘤”
若是你、喜欢探讨技术,或者对本文有任何的意见或建议,你能够扫描下方二维码,关注微信公众号“ 鱼头的Web海洋 ”,随时与鱼头互动。欢迎!衷心但愿能够碰见你。