Web API —— Observer(观察者)

2024-09-08 星期日

Observer API 是一种观察者模式,允许你监听元素的变化,并在变化时执行一些操作。

IntersectionObserver(交叉观察者)

IntersectionObserver 是一个用于检测元素是否可见(进入或离开视口)的 JavaScript API。它能有效地观察目标元素与其父元素或视口的交叉状态,当交叉状态发生变化时触发回调函数。这使得它特别适用于懒加载图片、无限滚动、统计页面元素的可见性等场景。

基本用法

这个API接收一个回调函数和一个选项,当目标元素进入或离开交叉区域时,会触发回调函数,回调函数接收两个参数:

  • entries:目标元素的交叉区域信息的数组。
  • observer:被调用的观察者实例。

交叉区域信息是一个IntersectionObserverEntry对象,它包含以下属性:

  • target:目标元素。
  • isIntersecting:目标元素是否在交叉区域内。
  • intersectionRatio:目标元素与交叉区域的交叉比例。
  • boundingClientRect:目标元素的边界矩形。
  • intersectionRect:目标元素与根元素的交叉区域。
  • rootBounds:根元素的边界矩形。
  • time: 交叉区域发生变化的时间。
😈
😈
😭
😭
😭
😭
😭
😭
😭
ts
const const observer: IntersectionObserverobserver = new var IntersectionObserver: new (callback: IntersectionObserverCallback, options?: IntersectionObserverInit) => IntersectionObserver
provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport. [MDN Reference](https://developer.mozilla.org/docs/Web/API/IntersectionObserver)
IntersectionObserver
((entries: IntersectionObserverEntry[]entries) => {
entries: IntersectionObserverEntry[]entries.Array<IntersectionObserverEntry>.forEach(callbackfn: (value: IntersectionObserverEntry, index: number, array: IntersectionObserverEntry[]) => void, thisArg?: any): void
Performs the specified action for each element in an array.
@paramcallbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
forEach
((entry: IntersectionObserverEntryentry) => {
if (entry: IntersectionObserverEntryentry.IntersectionObserverEntry.isIntersecting: boolean
[MDN Reference](https://developer.mozilla.org/docs/Web/API/IntersectionObserverEntry/isIntersecting)
isIntersecting
) {
entry: IntersectionObserverEntryentry.IntersectionObserverEntry.target: Element
[MDN Reference](https://developer.mozilla.org/docs/Web/API/IntersectionObserverEntry/target)
target
.Element.classList: DOMTokenList
Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/classList)
classList
.DOMTokenList.add(...tokens: string[]): void
Adds all arguments passed, except those already present. Throws a "SyntaxError" DOMException if one of the arguments is the empty string. Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMTokenList/add)
add
('show')
} else { entry: IntersectionObserverEntryentry.IntersectionObserverEntry.target: Element
[MDN Reference](https://developer.mozilla.org/docs/Web/API/IntersectionObserverEntry/target)
target
.Element.classList: DOMTokenList
Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/classList)
classList
.DOMTokenList.remove(...tokens: string[]): void
Removes arguments passed, if they are present. Throws a "SyntaxError" DOMException if one of the arguments is the empty string. Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMTokenList/remove)
remove
('show')
} }) }, { IntersectionObserverInit.root?: Element | Document | null | undefinedroot: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
, // 祖先元素
IntersectionObserverInit.rootMargin?: string | undefinedrootMargin: '0px', // 交叉区域的边距,值和 CSS margin 相同 IntersectionObserverInit.threshold?: number | number[] | undefinedthreshold: 0.5 // 交叉区域的比例 0-1, 0表示完全不在交叉区域,1表示完全在交叉区域 }) const const targetEl: HTMLElementtargetEl = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.ParentNode.querySelector<HTMLElement>(selectors: string): HTMLElement | null (+4 overloads)
Returns the first element that is a descendant of node that matches selectors. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/querySelector)
querySelector
('.target') as HTMLElement
// 监听目标元素 const observer: IntersectionObserverobserver.IntersectionObserver.observe(target: Element): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/IntersectionObserver/observe)
observe
(const targetEl: HTMLElementtargetEl)
// 取消监听 const observer: IntersectionObserverobserver.IntersectionObserver.unobserve(target: Element): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/IntersectionObserver/unobserve)
unobserve
(const targetEl: HTMLElementtargetEl)
// 清除所有监听 const observer: IntersectionObserverobserver.IntersectionObserver.disconnect(): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/IntersectionObserver/disconnect)
disconnect
()
// 手动同步获取交叉区域信息(不会触发回调),但是会清空之前的交叉区域信息队列 const observer: IntersectionObserverobserver.IntersectionObserver.takeRecords(): IntersectionObserverEntry[]
[MDN Reference](https://developer.mozilla.org/docs/Web/API/IntersectionObserver/takeRecords)
takeRecords
()

MutationObserver(变更观察者)

MutationObserver 是一个用于监听 DOM 变化的 API,能够检测 DOM 树的更改,例如元素的属性、子元素或文本内容发生变化时触发回调函数。它适用于场景需要实时监控 DOM 的变化,且性能优于传统的 MutationEvent 事件。

基本用法

它的用法和 IntersectionObserver 类似,只接收一个回调函数,回调函数接收两个参数:

  • mutations:目标元素的变更信息的数组。
  • observer:被调用的观察者实例。

mutations 中的每个都是元素一个MutationRecord对象,它包含以下属性:

  • target:目标元素。
  • type:变更类型, 有 attributes(属性变更)、childList(子节点树变更) 和 characterData(节点变更) 三种。
  • addedNodes:新增的节点。
  • removedNodes:被删除的节点。
  • previousSibling:前一个兄弟节点。
  • nextSibling:后一个兄弟节点。
  • attributeName:变更的属性名。
  • attributeNamespace:变更的属性名空间。
  • oldValue:变更前的属性值。
MutationRecord type:
被监听的元素,你可以通过 f12 修改
ts
const const observer: MutationObserverobserver = new var MutationObserver: new (callback: MutationCallback) => MutationObserver
Provides the ability to watch for changes being made to the DOM tree. It is designed as a replacement for the older Mutation Events feature which was part of the DOM3 Events specification. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MutationObserver)
MutationObserver
((mutations: MutationRecord[]mutations) => {
mutations: MutationRecord[]mutations.Array<MutationRecord>.forEach(callbackfn: (value: MutationRecord, index: number, array: MutationRecord[]) => void, thisArg?: any): void
Performs the specified action for each element in an array.
@paramcallbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
forEach
((mutation: MutationRecordmutation) => {
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
(mutation: MutationRecordmutation.MutationRecord.type: MutationRecordType
Returns "attributes" if it was an attribute mutation. "characterData" if it was a mutation to a CharacterData node. And "childList" if it was a mutation to the tree of nodes. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MutationRecord/type)
type
)
}) }) const const targetEl: HTMLElementtargetEl = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.ParentNode.querySelector<HTMLElement>(selectors: string): HTMLElement | null (+4 overloads)
Returns the first element that is a descendant of node that matches selectors. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/querySelector)
querySelector
('.target') as HTMLElement
// 监听目标元素 const observer: MutationObserverobserver.MutationObserver.observe(target: Node, options?: MutationObserverInit): void
Instructs the user agent to observe a given target (a node) and report any mutations based on the criteria given by options (an object). The options argument allows for setting mutation observation options via object members. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MutationObserver/observe)
observe
(const targetEl: HTMLElementtargetEl, {
MutationObserverInit.subtree?: boolean | undefined
Set to true if mutations to not just target, but also target's descendants are to be observed.
subtree
: true, // 监听子树变更
MutationObserverInit.attributes?: boolean | undefined
Set to true if mutations to target's attributes are to be observed. Can be omitted if attributeOldValue or attributeFilter is specified.
attributes
: true, // 监听属性变更
MutationObserverInit.attributeFilter?: string[] | undefined
Set to a list of attribute local names (without namespace) if not all attribute mutations need to be observed and attributes is true or omitted.
attributeFilter
: ['class', 'id'], // 指定监听的属性,默认为所有的属性
MutationObserverInit.attributeOldValue?: boolean | undefined
Set to true if attributes is true or omitted and target's attribute value before the mutation needs to be recorded.
attributeOldValue
: true, // 记录属性变更的旧值
MutationObserverInit.childList?: boolean | undefined
Set to true if mutations to target's children are to be observed.
childList
: true, // 监听子节点变更
MutationObserverInit.characterData?: boolean | undefined
Set to true if mutations to target's data are to be observed. Can be omitted if characterDataOldValue is specified.
characterData
: true, // 监听字符变更
MutationObserverInit.characterDataOldValue?: boolean | undefined
Set to true if characterData is set to true or omitted and target's data before the mutation needs to be recorded.
characterDataOldValue
: true // 记录字符变更的旧值
}) // 清除所有监听 const observer: MutationObserverobserver.MutationObserver.disconnect(): void
Stops observer from observing any mutations. Until the observe() method is used again, observer's callback will not be invoked. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MutationObserver/disconnect)
disconnect
()
// 手动同步获取变更信息(不会触发回调)和清空之前的变更信息队列 const observer: MutationObserverobserver.MutationObserver.takeRecords(): MutationRecord[]
Empties the record queue and returns what was in there. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MutationObserver/takeRecords)
takeRecords
()

ResizeObserver(尺寸观察者)

ResizeObserver 是一种浏览器提供的 API,用于监听元素的尺寸变化。当元素的大小(宽度或高度)发生变化时,ResizeObserver 会触发回调,允许开发者动态地处理这些变化。

基本用法

参数和MutationObserver一样,只接收一个回调函数,回调函数接收一个参数:

  • entries:目标元素的变更信息的数组。
  • observer:被调用的观察者实例。

entries中的元素为ResizeObserverEntry对象,它包含以下属性:

  • target:目标元素。
  • borderBoxSize:目标元素的边框盒尺寸数组。
    • inlineSize:目标元素的水平尺寸。
    • blockSize:目标元素的垂直尺寸。
  • contentBoxSize:目标元素的内容盒尺寸数组。
  • devicePixelContentBoxSize:目标元素的内容盒尺寸(以设备像素为单位)。
  • contentRect:目标元素的内容区域。
width: 704px,height: 59px
被监听的元素,你可以通过 f12 修改
ts
const const observer: ResizeObserverobserver = new var ResizeObserver: new (callback: ResizeObserverCallback) => ResizeObserver
[MDN Reference](https://developer.mozilla.org/docs/Web/API/ResizeObserver)
ResizeObserver
((entries: ResizeObserverEntry[]entries) => {
entries: ResizeObserverEntry[]entries.Array<ResizeObserverEntry>.forEach(callbackfn: (value: ResizeObserverEntry, index: number, array: ResizeObserverEntry[]) => void, thisArg?: any): void
Performs the specified action for each element in an array.
@paramcallbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
forEach
((entry: ResizeObserverEntryentry) => {
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
(entry: ResizeObserverEntryentry.ResizeObserverEntry.target: Element
[MDN Reference](https://developer.mozilla.org/docs/Web/API/ResizeObserverEntry/target)
target
)
}) }) const const targetEl: HTMLElementtargetEl = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.ParentNode.querySelector<HTMLElement>(selectors: string): HTMLElement | null (+4 overloads)
Returns the first element that is a descendant of node that matches selectors. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/querySelector)
querySelector
('.target') as HTMLElement
// 监听目标元素 const observer: ResizeObserverobserver.ResizeObserver.observe(target: Element, options?: ResizeObserverOptions): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/ResizeObserver/observe)
observe
(const targetEl: HTMLElementtargetEl, {
ResizeObserverOptions.box?: ResizeObserverBoxOptions | undefinedbox: 'border-box', // 需要监听的盒模型,值为 'content-box'(默认) | 'border-box' | 'device-pixel-content-box' }) // 取消监听 const observer: ResizeObserverobserver.ResizeObserver.unobserve(target: Element): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/ResizeObserver/unobserve)
unobserve
(const targetEl: HTMLElementtargetEl)
// 清除所有监听 const observer: ResizeObserverobserver.ResizeObserver.disconnect(): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/ResizeObserver/disconnect)
disconnect
()
~ cd ../

Comment / 留言区