Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add new hook useMutationObserver #1751

Merged
merged 39 commits into from
Jul 27, 2022

Conversation

li-jia-nan
Copy link
Collaborator

@li-jia-nan li-jia-nan commented Jul 10, 2022

[中文版模板 / Chinese template]

🤔 This is a ...

  • New feature
  • Bug fix
  • Site / documentation update
  • Demo update
  • TypeScript definition update
  • Bundle size optimization
  • Performance optimization
  • Enhancement feature
  • Internationalization
  • Refactoring
  • Code style optimization
  • Test Case
  • Branch merge
  • Other (about what?)

🔗 Related issue link

💡 Background and solution

close #1542
close #1567

📝 Changelog

新增 hook: useMutationObserver

一个监听指定的 DOM 发生变化的 hook

代码演示

一、基础用法

import { useMutationObserver } from 'ahooks';
import { message } from 'antd';
import React, { useRef, useState } from 'react';

const App: React.FC = () => {
  const [flag, setFlag] = useState<boolean>(false);

  const ref = useRef<HTMLButtonElement>(null);

  const callback: MutationCallback = mutationsList => {
    mutationsList.forEach(mutation => {
      message.info(`The ${mutation.attributeName} was be modified`);
    });
  };

  useMutationObserver(ref, callback, { attributes: true });

  return (
    <button ref={ref} style={{ width: flag ? 200 : 300 }} onClick={() => setFlag(!flag)}>
      change size
    </button>
  );
};

export default App;

二、可传入 DOM 元素

import { useMutationObserver } from 'ahooks';
import { message } from 'antd';
import React, { useState } from 'react';

const App: React.FC = () => {
  const [flag, setFlag] = useState<boolean>(false);

  const callback: MutationCallback = mutationsList => {
    mutationsList.forEach(mutation => {
      message.info(`The ${mutation.attributeName} was be modified`);
    });
  };

  useMutationObserver(
    document.querySelector('#observerRoot'),
    // or () => document.querySelector('#observerRoot')
    callback,
    { attributes: true },
  );

  return (
    <>
      <button onClick={() => setFlag(!flag)}>change color</button>
      <div
        id="observerRoot"
        style={{ width: 200, height: 200, marginTop: 20, backgroundColor: flag ? 'blue' : 'red' }}
      />
    </>
  );
};

export default App;

三、可监听子节点变化

import { useMutationObserver } from 'ahooks';
import { message } from 'antd';
import React, { useEffect, useRef, useState } from 'react';

const App: React.FC = () => {
  const [flag, setFlag] = useState<boolean>(true);

  const ref = useRef<HTMLButtonElement>(null);

  const callback: MutationCallback = mutationsList => {
    mutationsList.forEach(mutation => {
      message.info(`The ${mutation.type} was be modified`);
    });
  };

  useMutationObserver(ref, callback, { attributes: true, childList: true });

  useEffect(() => {
    if (ref.current) {
      ref.current.textContent = flag ? 'aaaaa' : 'bbbbb';
    }
  }, [flag]);

  return (
    <button ref={ref} style={{ width: 100 }} onClick={() => setFlag(!flag)}>
      click
    </button>
  );
};

export default App;

API

useMutationObserver(
  target: Target,
  callback: MutationCallback,
  options?: MutationObserverInit,
);

Params

参数 说明 类型 默认值
target DOM 节点或者 Ref Element | () => Element | MutableRefObject<Element>
callback 触发的回调函数 (mutations: MutationRecord[], observer: MutationObserver) => void
options 设置项 MutationObserverInit

options

参数 说明 类型 默认值
attributeFilter 要监视的特定属性名称的数组。如果未包含此属性,则对所有属性的更改都会触发变动通知 string[]
attributeOldValue 当监视节点的属性改动时,将此属性设为 true 将记录任何有改动的属性的上一个值 boolean
attributes 设为 true 以观察受监视元素的属性值变更 boolean false
characterData 设为 true 以监视指定目标节点或子节点树中节点所包含的字符数据的变化 boolean
characterDataOldValue 设为 true 以在文本在受监视节点上发生更改时记录节点文本的先前值 boolean
childList 设为 true 以监视目标节点添加或删除新的子节点(如果 subtree 为 true,则也包含子孙节点) boolean false
subtree 设为 true 以将监视范围扩展至目标节点整个节点树中的所有节点 boolean false

notice

注意,以下任一情况都会抛出异常:

  • options 配置项对象中,必须至少将 attributescharacterDatachildList 中的一个属性设置为 true,否则会报错

  • attributes 选项为 false(表示不监视属性更改),但是 attributeOldValue 选项为 true 并且/或者 attributeFilter 配置存在

  • characterDataOldValue 选项为 true,但是 characterData 选项为 false(表示不跟踪字符更改)

Language Changelog
🇺🇸 English add new hook: useMutationObserver
🇨🇳 Chinese 新增 hook: useMutationObserver

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • TypeScript definition is updated/provided or not needed
  • Changelog is provided or not needed

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ li-jia-nan
❌ crazylxr
You have signed the CLA already but the status is still pending? Let us recheck it.

@li-jia-nan li-jia-nan requested a review from hchlq July 12, 2022 07:57
@hchlq
Copy link
Collaborator

hchlq commented Jul 12, 2022

我没啥问题了,等 crazylxr 再看下哈

@li-jia-nan
Copy link
Collaborator Author

我没啥问题了,等 crazylxr 再看下哈

OK,辛苦

@miracles1919
Copy link
Collaborator

test 的问题可以先放一放 ~ 后面我看看怎么改

@li-jia-nan li-jia-nan requested a review from crazylxr July 27, 2022 02:17
@li-jia-nan li-jia-nan requested a review from crazylxr July 27, 2022 08:01
@crazylxr crazylxr merged commit 90c73ba into alibaba:master Jul 27, 2022
@li-jia-nan li-jia-nan deleted the useMutationObserver branch July 27, 2022 09:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[RFC] useMutationObserver
5 participants