vuejs3 - Vue 3 : disable shadow dom while using custom element

标签 vuejs3 shadow-dom custom-element

我想在非 Vue 应用程序中添加 custom element .

为此,我创建了一个经典的 SFC:

//test.ce.vue
<template>
    <div class="text-primary">Test</div>
</template>

<script>
export default {
    name: 'test',
};
</script>

<style>
    .text-primary {
        color: red;
    }

</style>

然后是一个主脚本:

//app.js
import Test from 'test.ce.vue';
const testElement = defineCustomElement(Test);
customElements.define('test-element', testElement);

document.body.appendChild(document.createElement('test-element'));

创建影子 dom 元素后一切正常运行:

<test-component>
    #shadow-root (open)
        <style>
            .text-primary {
                color: red;
            }
        </style>
        <div class="text-primary">Test</div>
</test-component>

我想避免在组件中重新定义 .text-primary 类,因为该类已在主 css 文件中定义。我也不需要只为这个组件定义特定的类,所以换句话说,我想像经典的 custom element 一样删除影子 dom。会做的。

所以基本上,渲染这个:

<test-component>
    <div class="text-primary">Test</div>
</test-component>

在 vue 中是否有任何选项允许这样定义?

最佳答案

较早的问题,但万一有人仍然需要解决方案...

目前没有办法告诉 Vue 不要使用 shadow-dom。在 Vue 2 中有一个官方包,用于创建没有 shadow-root 的 web 组件。还有一个 Vue 3 的社区端口:

https://www.npmjs.com/package/vue3-webcomponent-wrapper

它只是为了帮助刚从 Vue 2 迁移过来的人保持应用程序正常运行。它从未打算取代官方解决方案,只能在官方包可以处理 Vue 3 之前使用。

不幸的是,这从未发生过。

community port还是可以用的,但是包里没有任何源码,用起来有点吓人。

我为我们的项目想出了另一个解决方案。在由一堆嵌套组件组成的更复杂的 vue 组件上使用 defineCustomElement 揭示了另一个问题。子组件的 css 不会被复制到 shadow root。所以只有根组件的 css 可以工作。 您可以在此处找到相关问题和带有完整示例的解决方法:

https://github.com/vuejs/core/issues/4662#issuecomment-1116001438

它基本上从头部抓取 css 并将其附加到影子根。 你只需要扩展它来复制你的 main.css,比如

<template>
    <div id="app" ref="injectionElementRef">
        <img alt="Vue logo" src="./assets/logo.png">
        <HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
    </div>
</template>

<script lang="ts">
    import {defineComponent} from 'vue';
    import HelloWorld from './components/HelloWorld.vue';

    export default defineComponent({
        name: 'App',
        components: {
            HelloWorld
        },
        mounted() {
            const el = this.$refs.injectionElementRef as HTMLElement

            const root = el.getRootNode()

            const linkTag = document.getElementById('main-css-id')

            root.insertBefore(linkTag.cloneNode(), el)
            
        }
    });
</script>

这种方法的缺点是,有一个短暂的闪烁,因为 css 是在挂载之后应用的。在应用 css 解决该问题之前,您可以显示一个空元素。

关于vuejs3 - Vue 3 : disable shadow dom while using custom element,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70703981/

相关文章:

vue.js - 从 Vue 3 组合 api 中的函数内部返回 Apollo useQuery 结果

javascript - 公牛上的槽和奶头 HTML 模板

python - 如何从 Selenium 处理 Shadow DOM 中的元素

html - 如何在自定义元素中制作自定义表格?

javascript - 是否可以创建任何人无需安装即可使用的 Web 组件?

html - Vue 3 砖石布局与 Bootstrap 5 结合

laravel - 获取 _ctx.route 不是一个函数

polymer - polymer 元素内的内容可编辑

javascript - Vue : how to merge two reactive objects without loosing reactivity

javascript - polymer 自动节点查找不起作用