Обтекание DOM-элемента при создании внешней библиотеки с компонентом Vue со слотами - PullRequest
0 голосов
/ 15 октября 2019

Я интегрирую мощную стороннюю библиотеку, управляющую DOM, в мое большое приложение Vue. Эта библиотека предоставляет элемент SVG, который она создает, и подключает к внутренним событиям преобразования, к которым я затем могу добавить элементы SVG. Я хочу обернуть эту библиотеку в компонент таким образом, чтобы я мог предоставить ей компоненты SVG vue со слотами как дочерние элементы

Я нахожу множество простых примеров того, как обернуть сторонний компонент с помощью vueкомпонента, но я не нашел абсолютно ничего о смешивании существующего HTML с возвращаемым значением функции рендеринга.

Я хочу иметь возможность использовать эту структуру сортировки, хотя и более сложным образом:

parent

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

Wrapper Component


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
        );
    }
}

Идеальным результатом было бы создание элемента SVG, как и ожидалось ThirdPartySVGTool, который затем реактивно отображал бы слоты, помещенные в компонент svg. это сгенерировано.

Возможно ли это? Если это так, каков наилучший способ сделать это?

1 Ответ

0 голосов
/ 15 октября 2019

Оказывается, я лаял не на то дерево. Лучший способ сделать это - просто переместить элементы компонента в правильное место после их монтирования. 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>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...