target
组件能显示隐藏,其展示内容可通过slot
或content
属性定义,如果都定义了则优先content
,content
支持html
片段字符串和VNode
节点对象;测试发现onMounted
中的setVNode
没有效果,当target组件显示后,再重新setVNode
才有效果,但当再次隐藏target
,再显示,发现内容变为空,刚set
的VNode
不见了;setHtml
则没问题,这是为啥呢?
test.vue组件代码
<template>
<div>
<div>
<button @click="toggleTarget">
{{show ? "hide target" : "show target"}}
</button>
<button @click="setHtml">
set html content
</button>
<button @click="setVNode">
set vnode content
</button>
</div>
<target v-model="show" :content="content"></target>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, h, VNode, onMounted } from 'vue';
import Target from './target.vue';
export default defineComponent({
components: {
Target
},
setup() {
const show = ref(false);
const content = ref<string | VNode>('');
const toggleTarget = () => {
show.value = !show.value;
};
const setHtml = () => {
content.value = "<h2>html content</h2>";
};
const setVNode = () => {
content.value = h(
"h2",
{},
"vnode content"
);
};
onMounted(() => {
//这里没有效果
setVNode();
});
return {
show,
toggleTarget,
content,
setHtml,
setVNode
};
}
});
</script>
target.vue组件
<template>
<div style="border:1px solid red;width:200px;height:200px" v-show="visible">
<div v-html="innerContent" v-if="innerContent">
</div>
<div v-else>
<slot></slot>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, getCurrentInstance, isVNode, nextTick, ref, VNode, watch, h } from 'vue';
export default defineComponent({
props: {
content: [String,Object],
modelValue: {
type: Boolean,default: false
}
},
setup(props: any) {
const visible = ref(false);
const innerContent = ref<string | VNode>('');
watch(() => props.modelValue,(v) => {
visible.value = v;
});
const internalInstance = getCurrentInstance();
// if(internalInstance && internalInstance.slots.default === undefined){
// internalInstance.slots.default = () => [h('div',{},'w')];
// }
// internalInstance && console.log('internalInstance',internalInstance.slots.default);
watch(() => props.content , (newVal, oldVal) => {
if(!internalInstance) return;
if (isVNode(newVal)) {
internalInstance.slots.default = () => [newVal];
innerContent.value = '';
} else {
if(isVNode(oldVal) && !isVNode(newVal)){
delete internalInstance.slots.default;
}
innerContent.value = newVal;
}
});
return {
visible,
innerContent
};
}
});
</script>
已解决
下面是修改后的代码: