fix mutation observer in react

pull/580/head
Cory LaViska 2021-11-05 09:22:59 -04:00
rodzic 1dd556d6c8
commit 3eb7d6337a
3 zmienionych plików z 101 dodań i 5 usunięć

Wyświetl plik

@ -8,7 +8,7 @@ The mutation observer will report changes to the content it wraps through the `s
```html preview
<div class="mutation-overview">
<sl-mutation-observer attr>
<sl-mutation-observer attr="type">
<sl-button type="primary">Click to mutate</sl-button>
</sl-mutation-observer>
@ -42,6 +42,47 @@ The mutation observer will report changes to the content it wraps through the `s
</div>
```
```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 rgb(var(--sl-input-border-color));
align-items: center;
justify-content: center;
text-align: center;
padding: 4rem 2rem;
}
`;
const types = ['primary', 'success', 'neutral', 'warning', 'danger'];
let clicks = 0;
const App = () => {
const [type, setType] = useState('primary');
function handleClick() {
clicks++;
setType(types[clicks % types.length]);
}
return (
<>
<SlMutationObserver
attr="*"
onSlMutation={event => console.log(event.detail)}
>
<SlButton type={type} onClick={handleClick}>Click to mutate</SlButton>
</SlMutationObserver>
<style>{css}</style>
</>
);
};
```
?> 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
@ -101,4 +142,55 @@ Use the `child-list` attribute to watch for new child elements that are added or
</div>
```
```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 (
<>
<div class="mutation-child-list">
<SlMutationObserver
child-list
onSlMutation={event => console.log(event.detail)}
>
<div class="buttons">
<SlButton type="primary" onClick={addButton}>Add button</SlButton>
{buttonIds.map(id => (
<SlButton key={id} type="default" onClick={() => removeButton(id)}>
{id}
</SlButton>
))}
</div>
</SlMutationObserver>
</div>
👆 Add and remove buttons and watch the console
<style>{css}</style>
</>
);
};
```
[component-metadata:sl-mutation-observer]

Wyświetl plik

@ -9,6 +9,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
## Next
- Added React examples and CodePen links to all components
- Changed the `attr` in experimental `<sl-mutation-observer>` to require `"*"` instead of `""` to target all attributes
- Fixed a bug in `<sl-progress-bar>` where the `label` attribute didn't set the label
- Fixed a bug in `<sl-rating>` that caused disabled and readonly controls to transition on hover
- The `panel` property of `<sl-tab>` is now reflected

Wyświetl plik

@ -19,8 +19,8 @@ export default class SlMutationObserver extends LitElement {
private mutationObserver: MutationObserver;
/**
* Watches for changes to attributes. If empty, all changes will be reported. To watch only specific attributes,
* separate them by a space.
* Watches for changes to attributes. If set to *, all changes will be reported. To watch only specific attributes,
* separate them by a space, e.g. "class id title".
*/
@property({ reflect: true }) attr: string;
@ -80,12 +80,15 @@ export default class SlMutationObserver extends LitElement {
}
startObserver() {
const observeAttributes = typeof this.attr === 'string' && this.attr.length > 0;
const attributeFilter = observeAttributes && this.attr !== '*' ? this.attr.split(' ') : undefined;
try {
this.mutationObserver.observe(this, {
subtree: true,
childList: this.childList,
attributes: typeof this.attr === 'string',
attributeFilter: typeof this.attr === 'string' && this.attr.length > 0 ? this.attr.split(' ') : undefined,
attributes: observeAttributes,
attributeFilter,
attributeOldValue: this.attrOldValue,
characterData: this.charData,
characterDataOldValue: this.charDataOldValue