typescript - Vue 3 Render-funktioner - Lägg till ett underordnat element till VNode vid klickhändelse
Jag försöker dynamiskt lägga till en VNode till en behållare vid ett klickhändelse från användaren.
Jag förväntade mig att koden nedan skulle lägga till ett nytt barn till container-diven varje gång knappen klickas, men det som händer är att vid varje klick ersätts det tidigare barnet med det nya inuti div:en, som följande gif illustrerar.
Hur skulle jag, genom att följa samma koncept att dynamiskt skapa VNodes, uppnå resultatet att lägga till en nod utan att ersätta den tidigare?
import {defineComponent, h, createVNode, render} from "vue";
export default defineComponent({
setup() {
return () => {
const container = h('div', []);
const button = h('button', {
onClick: () => {
const node = createVNode('div', null,[`Time: ${new Date().toISOString()}`]);
node.appContext = container.appContext;
render(node, container.el as any);
}
}, ['Add New'])
container.children?.push(button);
return container;
};
}
})
(Som referens har jag följt denna handledning)
Tack för din tid
Svar #1
Med render(node, container.el as any); ersätter du innehållet i din div-behållare varje gång med den nyss skapade noden. Denna metod ifrågasätts. Eftersom:
Detta tillvägagångssätt förlitar sig på interna metoder (
createVNodeochrender), som kan omstruktureras eller tas bort i en framtida version.
Jag skulle bara använda Vue-reaktivitet istället för att rendera nya vnodes.
const { createApp, defineComponent, h, createVNode, render, ref } = Vue;
const MyComponent = {
setup() {
const children = ref([]);
return () => {
const button = h('button', {
onClick: () => {
children.value.push(`Time: ${new Date().toISOString()}`);
}
}, ['Add New']);
const list = h('ul',
children.value.map((text) => {
return h('li', null, text)
})
);
return h('div', [button, list]);
};
}
}
const App = {}
const app = createApp(App)
app.component('MyComponent', MyComponent)
app.mount('#app')<div id="app">
<my-component />
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>Eller gör det ännu enklare, så här
const { createApp, ref } = Vue;
const MyComponent = {
setup() {
const items = ref([]);
const addNew = () => items.value.push(`Time: ${new Date().toISOString()}`);
return {items, addNew}
},
template: `
<div>
<button @click="addNew()">Add New</button>
<ul><li v-for="text in items">{{ text }}</li></ul>
</div>`
}
const App = {
components: {MyComponent}
}
const app = createApp(App)
app.mount('#app')<div id="app">
<my-component />
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>