cqwcns 发表于 2023-1-19 16:19

vue3,动态渲染dom的问题

以下是一个简单的demo,来模拟vue3通过h()和render()创建dom元素。
说明,由于事件情景中,父元素.content是动态创建的,所以我不能直接在template中写我要的元素,才通过h()和render()创建。


问题:我希望h()和render()创建的元素,可以响应变量isMyBtn,从而实现样式上的变化。
例如当isMyBtn为true时,类和内容分别为mybtn、我的按钮,反之是yourbtn、你的按钮。


注意,isMyBtn变量在元素创建后仍会有变化,元素要响应isMyBtn后续变化。


这种需求如果是自己在template中写元素,通过三元表达式或v-if可以轻松实现,但通过h()和render()创建的元素我不知道应该怎么实现。


请各位大佬指教,感谢。

<template>
<div class="content">
</div>
</template>

<script setup>

import { onMounted, ref, h, render } from 'vue';

const isMyBtn = ref(true)

onMounted(() => {
console.log('do render');
const domParent = document.getElementsByClassName('content');
const domSon = h('button', { class: isMyBtn ? 'mybtn' : 'yourbtn' }, isMyBtn ? '我的按钮' : '你的按钮');
render(domSon, domParent);
})

</script>

坏人。丶 发表于 2023-1-19 16:42

15行用错了isMyBtn.value

坏人。丶 发表于 2023-1-19 16:44

<template>
<div class="content">
</div>
</template>

<script setup>

import { onMounted, ref, h, render } from 'vue';

const isMyBtn = ref(true)

onMounted(() => {
console.log('do render');
const domParent = document.getElementsByClassName('content');
const domSon = h('button', { class: isMyBtn.value ? 'mybtn' : 'yourbtn' }, isMyBtn.value ? '我的按钮' : '你的按钮');
render(domSon, domParent);
})

</script>

cqwcns 发表于 2023-1-19 21:15

坏人。丶 发表于 2023-1-19 16:44





你好,谢谢指教。

但以上代码,经过测试,后续isMyBtn改变后,元素不会随之改变。

只会认isMyBtn的初始值。

cqwcns 发表于 2023-1-19 21:17

按照二楼大佬的指导,加上了.value。
但经过测试,这样只是会认初始值,isMyBtn后续改变,渲染的元素无法响应。

<template>
<div class="content">
</div>
<button @click="doChange" style="background-color: blue;">切换({{ isMyBtn }})</button>
</template>

<script setup>

import { onMounted, ref, h, render } from 'vue';

const isMyBtn = ref(true)

onMounted(() => {
console.log('do render');
const domParent = document.getElementsByClassName('content');
const domSon = h('button', { class: isMyBtn.value ? 'mybtn' : 'yourbtn' }, isMyBtn.value ? '我的按钮' : '你的按钮');
render(domSon, domParent);
})

const doChange = () => {
isMyBtn.value = !isMyBtn.value;
}
</script>

坏人。丶 发表于 2023-1-19 23:41

cqwcns 发表于 2023-1-19 21:17
按照二楼大佬的指导,加上了.value。
但经过测试,这样只是会认初始值,isMyBtn后续改变,渲染的元素无法 ...

注意:setup语法糖是不可以使用render的,所以只有用setup选项才可以。
<script>
import { h, reactive } from 'vue'
export default {
setup(props, { slots, attrs, emit }) {
    const state = reactive({
      count: 0
    })

    function increment() {
      state.count++
    }
    // 返回render函数
    return () =>
      h(
      'button',
      {
          onClick: increment //这里绑定事件
      },
      state.count
      )
}
}
</script>

npc404 发表于 2023-1-20 00:18

本帖最后由 npc404 于 2023-1-20 01:26 编辑

你这样写的话,vue生成的vnode里并没有你后来插进去的元素,这也就是为什么你变量变动了插进去的元素也不会更新。你这种写法的话,可以用watch监听isMyBtn变量,回调就是重新执行你onMounted里的操作,再次render会比较新旧两个vnode(这个vnode是指你用h函数生成的那个),视图也就会更新了。不过话说你这么写好另类啊,换我的话,只有两种状态,我选择给要插入元素的父节点根据变量设置动态class,按钮文本用伪元素实现
页: [1]
查看完整版本: vue3,动态渲染dom的问题