Vue实现插槽下渲染dom字符串的使用
作者:何期骤雨降青霄
前言
Vue插槽想必大家都不陌生了,它可以在使用组件的时候决定组件的一部分内容如何渲染。但我最近遇到个需求需要将 dom
字符串插入到插槽下动态渲染插槽的内容,查找了很多资料都没找到相关的内容,后来自己想办法解决了,特此写个文章记录下。
需求
先来简单介绍下需求:这是在开发一个低代码平台的时候所遇到的需求,用户可以自己写一些组件上传到平台,在使用的时候可以对组件的 props
slots
events
进行配置,这就涉及到了动态插槽内容的实现了。对于代码编辑器的实现使用了 code-mirror,感兴趣的可以去看下,这里就不多说了。这里主要讲如何实现动态插槽内容渲染。
先来大致看下代码的上下文:
<template> <Component v-bind="componentProps" > <template v-for="item of componentSlots" #[item[0]] > </template> </Component> </template> <script setup lang="ts"> const Component = defineAsyncComponent({ // ... }) const componentProps = ref({}) const componentSlots = ref<[string, string][]>([]) onMounted(async () => { componentProps.value = await loadProps() componentSlots.value = await loadSlots() }) </script>
v-html
说到渲染 dom
字符串,那 v-html
肯定是首要想到的。但是 template
标签上是无法使用 v-html
的,那么只能在 template
下写一个普通元素来塞 dom
字符串,代码如下:
<template v-for="item of componentSlots" #[item[0]] > <span v-html="item[1]"> </span> </template>
这样的确实现了动态渲染插槽内容的需求,但是多出一个标签总是感觉不太妥当;而且也很难保证这个多出的 span
不会对组件的布局产生影响。这让我又陷入的沉思...
v-outerHTML
既然 innerHTML
不完全满足需求,那么使用 outerHTML
不就完美解决这个问题了吗?于是我去查关于 vue
如何使用 outerHTML
相关资料,发现并没有很好的案例,那就自己实现一个吧。
export const vOuterHTML = { bind(el, binding) { el.outerHTML = binding.value }, update(el, binding) { el.outerHTML = binding.value }, }
<template v-for="item of componentSlots" #[item[0]] > <span v-outerHTML="item[1]"> </span> </template>
代码保存,页面一刷新,这不完美实现了吗?但是等我去编辑 dom
字符串并保存后发现问题了,组件渲染内容并没有改变,控制台也报错了。
什么原因呢?原来是因为在 update
阶段时,span
已不在页面中,因此无法对他执行 outerHTML
赋值。
那怎么办呢?只需要在 bind
阶段记住 span
的父节点,然后在更新阶段手动再创建一个 span
并 append
到父节点下,再进行 outerHTML赋值即可,代码如下:
export const vOuterHTML = (() => { let parentNode = null return { bind(el, binding) { parentNode = el.parentNode el.outerHTML = binding.value }, update(el, binding) { if (parentNode) { const span = document.createElement('span') parentNode.appendChild(span) span.outerHTML = binding.value } }, unbind() { if (parentNode) { parentNode = null } } } })()
到此这篇关于Vue实现插槽下渲染dom字符串的使用的文章就介绍到这了,更多相关Vue 渲染dom字符串内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!