shoelace/docs/components/mutation-observer.md

194 wiersze
5.2 KiB
Markdown
Czysty Zwykły widok Historia

2021-09-30 22:32:59 +00:00
# Mutation Observer
[component-header:sl-mutation-observer]
The Mutation Observer component offers a thin, declarative interface to the [`MutationObserver API`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
The mutation observer will report changes to the content it wraps through the `sl-mutation` event. When emitted, a collection of [MutationRecord](https://developer.mozilla.org/en-US/docs/Web/API/MutationRecord) objects will be attached to `event.detail` that contains information about how it changed.
```html preview
<div class="mutation-overview">
2021-12-27 19:04:31 +00:00
<sl-mutation-observer attr="variant">
2021-12-13 22:38:40 +00:00
<sl-button variant="primary">Click to mutate</sl-button>
2021-09-30 22:32:59 +00:00
</sl-mutation-observer>
2022-03-02 15:10:41 +00:00
<br />
2021-09-30 22:32:59 +00:00
👆 Click the button and watch the console
<script>
const container = document.querySelector('.mutation-overview');
const mutationObserver = container.querySelector('sl-mutation-observer');
const button = container.querySelector('sl-button');
2022-03-02 15:10:41 +00:00
const variants = ['primary', 'success', 'neutral', 'warning', 'danger'];
2021-09-30 22:32:59 +00:00
let clicks = 0;
2021-12-27 19:04:31 +00:00
// Change the button's variant attribute
2021-09-30 22:32:59 +00:00
button.addEventListener('click', () => {
clicks++;
2021-12-27 19:04:31 +00:00
button.setAttribute('variant', variants[clicks % variants.length]);
2021-09-30 22:32:59 +00:00
});
// Log mutations
mutationObserver.addEventListener('sl-mutation', event => {
console.log(event.detail);
});
</script>
<style>
.mutation-overview sl-button {
margin-bottom: 1rem;
}
</style>
</div>
```
2021-11-05 13:22:59 +00:00
```jsx react
import { useState } from 'react';
import { SlButton, SlMutationObserver } from '@shoelace-style/shoelace/dist/react';
const css = `
.resize-observer-overview div {
display: flex;
border: solid 2px var(--sl-input-border-color);
2021-11-05 13:22:59 +00:00
align-items: center;
justify-content: center;
text-align: center;
padding: 4rem 2rem;
}
`;
2022-03-02 15:10:41 +00:00
const variants = ['primary', 'success', 'neutral', 'warning', 'danger'];
2021-11-05 13:22:59 +00:00
let clicks = 0;
const App = () => {
2021-12-27 19:04:31 +00:00
const [variant, setVariant] = useState('primary');
2021-11-05 13:22:59 +00:00
function handleClick() {
clicks++;
2021-12-27 19:04:31 +00:00
setVariant(variants[clicks % variants.length]);
2021-11-05 13:22:59 +00:00
}
return (
<>
2022-03-02 15:10:41 +00:00
<SlMutationObserver attr="*" onSlMutation={event => console.log(event.detail)}>
<SlButton variant={variant} onClick={handleClick}>
Click to mutate
</SlButton>
2021-11-05 13:22:59 +00:00
</SlMutationObserver>
<style>{css}</style>
</>
);
};
```
2021-09-30 22:32:59 +00:00
?> When you create a mutation observer, you must indicate what changes it should respond to by including at least one of `attr`, `child-list`, or `char-data`. If you don't specify at least one of these attributes, no mutation events will be emitted.
## Examples
### Child List
Use the `child-list` attribute to watch for new child elements that are added or removed.
```html preview
<div class="mutation-child-list">
<sl-mutation-observer child-list>
<div class="buttons">
2021-12-13 22:38:40 +00:00
<sl-button variant="primary">Add button</sl-button>
2021-09-30 22:32:59 +00:00
</div>
</sl-mutation-observer>
👆 Add and remove buttons and watch the console
<script>
const container = document.querySelector('.mutation-child-list');
const mutationObserver = container.querySelector('sl-mutation-observer');
const buttons = container.querySelector('.buttons');
2021-12-13 22:38:40 +00:00
const button = container.querySelector('sl-button[variant="primary"]');
2021-09-30 22:32:59 +00:00
let i = 0;
// Add a button
button.addEventListener('click', () => {
const button = document.createElement('sl-button');
button.textContent = ++i;
buttons.append(button);
});
// Remove a button
buttons.addEventListener('click', event => {
2021-12-13 22:38:40 +00:00
const target = event.target.closest('sl-button:not([variant="primary"])');
2021-09-30 22:32:59 +00:00
event.stopPropagation();
if (target) {
target.remove();
}
});
// Log mutations
mutationObserver.addEventListener('sl-mutation', event => {
console.log(event.detail);
});
</script>
<style>
.mutation-child-list .buttons {
display: flex;
2022-03-02 15:10:41 +00:00
gap: 0.25rem;
2021-09-30 22:32:59 +00:00
flex-wrap: wrap;
margin-bottom: 1rem;
}
</style>
</div>
```
2021-11-05 13:22:59 +00:00
```jsx react
import { useState } from 'react';
import { SlButton, SlMutationObserver } from '@shoelace-style/shoelace/dist/react';
const css = `
.mutation-child-list .buttons {
display: flex;
gap: .25rem;
flex-wrap: wrap;
margin-bottom: 1rem;
}
`;
let buttonCount = 0;
const App = () => {
const [buttonIds, setButtonIds] = useState([]);
function addButton() {
setButtonIds([...buttonIds, ++buttonCount]);
}
function removeButton(id) {
setButtonIds(buttonIds.filter(i => i !== id));
}
return (
<>
2021-11-05 14:06:06 +00:00
<div className="mutation-child-list">
2022-03-02 15:10:41 +00:00
<SlMutationObserver child-list onSlMutation={event => console.log(event.detail)}>
2021-11-05 14:06:06 +00:00
<div className="buttons">
2022-03-02 15:10:41 +00:00
<SlButton variant="primary" onClick={addButton}>
Add button
</SlButton>
2021-11-05 13:22:59 +00:00
{buttonIds.map(id => (
2021-12-13 22:38:40 +00:00
<SlButton key={id} variant="default" onClick={() => removeButton(id)}>
2021-11-05 13:22:59 +00:00
{id}
</SlButton>
))}
</div>
</SlMutationObserver>
</div>
👆 Add and remove buttons and watch the console
<style>{css}</style>
</>
);
};
```
2021-09-30 22:32:59 +00:00
[component-metadata:sl-mutation-observer]