fix dynamic html bug

pull/11197/head
Dominic Gannaway 2 years ago
parent f3510c8748
commit c2dfda15e0

@ -1,10 +1,31 @@
import { derived } from '../../reactivity/deriveds.js';
import { render_effect } from '../../reactivity/effects.js';
import { current_effect, get } from '../../runtime.js';
import { is_array } from '../../utils.js';
import { hydrate_nodes, hydrating } from '../hydration.js';
import { create_fragment_from_html, remove } from '../reconciler.js';
import { push_template_node } from '../template.js';
/**
* @param {import('#client').Effect} effect
* @param {(Element | Comment | Text)[]} to_remove
* @returns {void}
*/
function remove_from_parent_effect(effect, to_remove) {
const dom = effect.dom;
if (is_array(dom)) {
for (let i = dom.length - 1; i >= 0; i--) {
if (to_remove.includes(dom[i])) {
dom.splice(i, 1);
break;
}
}
} else if (dom !== null && to_remove.includes(dom)) {
effect.dom = null;
}
}
/**
* @param {Element | Text | Comment} anchor
* @param {() => string} get_value
@ -12,15 +33,19 @@ import { push_template_node } from '../template.js';
* @returns {void}
*/
export function html(anchor, get_value, svg) {
var effect = anchor.parentNode !== current_effect?.dom ? current_effect : null;
const parent_effect = anchor.parentNode !== current_effect?.dom ? current_effect : null;
let value = derived(get_value);
render_effect(() => {
var dom = html_to_dom(anchor, effect, get(value), svg);
effect = null;
var dom = html_to_dom(anchor, parent_effect, get(value), svg);
if (dom) {
return () => remove(dom);
return () => {
if (parent_effect !== null) {
remove_from_parent_effect(parent_effect, is_array(dom) ? dom : [dom]);
}
remove(dom);
};
}
});
}

@ -0,0 +1,39 @@
import { flushSync } from '../../../../src/index-client';
import { test } from '../../test';
export default test({
html: `<button>add item</button><button>make span</button><button>reverse</button>`,
async test({ assert, target }) {
const [btn1, btn2, btn3] = target.querySelectorAll('button');
flushSync(() => {
btn1?.click();
btn1?.click();
btn1?.click();
});
assert.htmlEqual(
target.innerHTML,
`<button>add item</button><button>make span</button><button>reverse</button><div>Item 1</div><div>Item 2</div><div>Item 3</div>`
);
flushSync(() => {
btn2?.click();
});
assert.htmlEqual(
target.innerHTML,
`<button>add item</button><button>make span</button><button>reverse</button><span>Item 1</span><span>Item 2</span><span>Item 3</span>`
);
flushSync(() => {
btn3?.click();
});
assert.htmlEqual(
target.innerHTML,
`<button>add item</button><button>make span</button><button>reverse</button><span>Item 3</span><span>Item 2</span><span>Item 1</span>`
);
}
});

@ -0,0 +1,30 @@
<script>
let items = $state([]);
function add_item() {
items.push({
id: items.length,
text: 'Item ' + (items.length + 1),
html: '<div>Item ' + (items.length + 1) + '</div>',
dom: null,
})
}
function make_span() {
items.forEach(item => {
item.html = item.html.replace(/div/g, 'span')
})
}
function reverse() {
items.reverse();
}
</script>
<button on:click={add_item}>add item</button>
<button on:click={make_span}>make span</button>
<button on:click={reverse}>reverse</button>
{#each items as item (item.id)}
{@html item.html}
{/each}
Loading…
Cancel
Save