【问题标题】:Wrapping a DOM-Element creating external library with a Vue Component with Slots使用带有插槽的 Vue 组件包装 DOM-Element 创建外部库
【发布时间】:2019-10-14 21:41:29
【问题描述】:

我正在将一个重型第三方 DOM 操作库集成到我的大型 Vue 应用程序中。该库提供了一个 SVG 元素,它创建并挂钩到内部转换事件,然后我可以将 svg 元素添加到其中。我想将该库包装在一个组件中,以便我可以将开槽的 SVG vue 组件作为子组件提供给它

我找到了很多关于如何用 vue 组件包装第三方组件的简单示例,但我完全没有发现将现有 HTML 与渲染函数的返回值混合在一起。

我希望能够使用这种排序结构,尽管以更复杂的方式:

父母

<template lang="pug">
    div
        third-party-svg-wrapper(:props="props")
            g
                custom-svg-rect(:v-for="rect of rects")
</template>

包装组件


export default {
    name: 'third-party-svg-wrapper',
    created(){
        this.$options.wrapper = Document.createElement('div') 
        this.$options.nonReactiveThirdPartySVGTool = thirdPartySVGTool({
            element:this.$options.wrapper,
        });
    },
    render(createElement) {
        let locationForSlot = this.$options.wrapper.querySelector(`svg`);
        // this obviously doesn't work, because this.$slots.default is 
        // not a DOM Node. However, it's a representation 
        // of what I want to do, appending the slot 
        // to the correct location in the third party html
        locationForSlot.appendChild(this.$slots.default)
        return createElement(
            'svg',
            this.$options.wrapper
        );
    }
}

理想的结果是由 thirdPartySVGTool 按预期创建 SVG 元素,然后反应性地呈现放置在它生成的 svg 组件中的插槽。

这可能吗?如果是这样,最好的方法是什么?

【问题讨论】:

    标签: vue.js vuejs2


    【解决方案1】:

    原来是我找错树了。最好的方法是在安装后将组件元素移动到正确的位置。 Vue 关心组件之间的数据依赖关系,但它只关心单个组件如何处理自己的模板的 HTML 结构。因此,更改该组件的基础级别引用的位置不会妨碍该组件的操作或渲染。

    这是工作组件的代码

    <template lang="pug">
        div.svg-overlay-wrapper
            svg.temp-slotted-svg(:v-show='false')
                slot
    </template>
    <script>
    export default {
        name: 'third-party-svg-overlay',
        props:{
            thirdPartyModuleInstance:{
                required: true,
            },
            overlayConfig:{
                required: false,
            }
        },
        data(){
            return { _svg_overlay:{} };
        },
        created(){
            this.$options._svg_overlay = this.thirdPartyModuleInstance.svgOverlay(this.overlayConfig);
        },
        mounted(){
            for(let slot of this.$slots.default){
                let targetElement = slot.$el || slot.elm;
                this.$options._svg_overlay._node.appendChild(targetElement);
            }
        },
        watch:{
            '$slots.default'(newVal, oldVal){
                if(newVal.length > oldVal.length){
                    for(let i = oldVal.length; i < newVal.length; i++){
                        let targetElement = slot.$el || slot.elm;
                        this.$options._svg_overlay._node.appendChild(targetElement);
                    }
                }
            }
        },
    }
    </script>
    
    

    【讨论】:

    • 谢谢,这对我来说非常有用,因为我正在尝试将现有的 DOM 元素(使用本机 javascript 对象/类管理)包装到 vue 包装器中。基本上我现在需要做的就是在 JS 对象和新的 vue 对象之间编写接口。
    猜你喜欢
    • 2021-02-06
    • 2022-01-06
    • 1970-01-01
    • 2021-01-20
    • 2018-11-26
    • 2016-09-16
    • 2020-02-14
    • 2020-08-22
    • 2017-12-20
    相关资源
    最近更新 更多