VueJS Render VNode

tl; dr:

Учитывая объект VueJS VNode, как мне получить элемент HTML, который был бы сгенерирован, если бы он был отрисован?

например.:

> temp1
VNode {tag: "h1", data: undefined, children: Array(1), text: undefined, elm: undefined, …}
> temp1.children[0]
VNode {tag: undefined, data: undefined, children: undefined, text: "Test", elm: undefined, …}
> doSomething(temp1)
<h1>Test</h1>

Цель

Я пытаюсь создать небольшую оболочку VueJS вокруг библиотеки DataTables.net.

Чтобы имитировать поведение HTML-таблиц в моей разметке, мне нужно что-то вроде следующего:

<datatable>
    <thead>
        <tr>
            <th>Name</th>
            <th>Age</th>
            <th>Salary</th>
        </tr>
    </thead>
    <tbody>
        <datatable-row v-for = "person in people">
            <td>{{ person.name }}</td>
            <td>{{ person.age }}</td>
            <td>{{ person.salary }}</td>
        </datatable-row>
    </tbody>
</datatable>

Что я сделал до сих пор

Я начал реализовывать это следующим образом:

DataTable.vue

<template>
    <table ref = "table" class = "display table table-striped" cellspacing = "0" width = "100%">
        <slot></slot>
    </table>
</template>

<script>
/* global $ */
export default {
    data: () => ({
        instance: null
    }),
    mounted() {
        this.instance = $(this.$refs.table).dataTable();
        this.$el.addEventListener("dt.row_added", function(e) {
            this.addRow(e.detail);
        });
    },
    methods: {
        addRow(row) {
            // TODO <-----
            console.info(row);
        }
    }
};
</script>

DataTableRow.vue

<script>
/* global CustomEvent */
export default {
    mounted() {
        this.$nextTick(() => {
            this.$el.dispatchEvent(new CustomEvent("dt.row_added", {
                bubbles: true,
                detail: this.$slots.default.filter(col => col.tag === "td")
            }));
        });
    },
    render() { return ""; }
};

Что это в настоящее время делает:

  • Когда страница загружается, DataTable инициализируется. Таким образом, заголовки столбцов правильно отформатированы, и я вижу «Отображение от 0 до 0 из 0 записей» в левом нижнем углу.
  • CustomEvent может всплывать мимо <tbody> и быть пойманным элементом DataTableуспешно (обход ограничения VueJS, что вы не можете прослушивать события в слотах)

Что это делает нет:

  • Собственно добавить строку

Мое событие дает мне массив объектов VNode. В моем ряду по одному VNode на столбец. В DataTables API есть функция addRow, которую можно вызвать так:

this.instance.row.add(["col1", "col2", "col3"]);

В моем случае я хочу, чтобы результирующий элемент от рендеринга VNode был элементами в этом массиве.

var elems = [];
for (var i = 0; i < row.length; i++)
    elems[i] = compile(row[i]);
this.instance.row.add(elems);

К сожалению, этот метод compile ускользает от меня. Я пробовал бегло просмотреть документацию VueJS, и я попробовал погуглить, но без кубиков. Я попытался вручную передать функцию createElement (параметр, переданный методу render), но это вызвало ошибку. Как я могу попросить VueJS отобразить VNode, не вставляя результат в DOM?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
5
0
5 404
2

Ответы 2

Я столкнулся с той же проблемой, желая сделать в основном то же самое с шаблоном деталей строки для DataTables.net.

Одним из решений может быть создание универсального компонента, отображающего VNode, и его программная реализация. Вот как я настраиваю динамическую строку деталей, которую я вставляю с помощью API-интерфейса datatable row.child().

RenderNode.js

export default {
    props: ['node'],
    render(h, context) {
        return this.node ? this.node : ''
    }
}

Datatables.vue

Включите компонент рендерера сверху

import Vue from 'vue'
import nodeRenderer from './RenderNode'

Создайте экземпляр и смонтируйте средство визуализации, чтобы получить скомпилированный HTML

// Assume we have `myVNode` and want its compiled HTML

const DetailConstructor = Vue.extend(nodeRenderer)

const detailRenderer = new DetailConstructor({
    propsData: {
        node: myVNode
    }
})

detailRenderer.$mount()    
// detailRenderer.$el is now a compiled DOM element 
row.child(detailRenderer.$el).show() 

Вы должны определить свои компоненты следующим образом:

import {createApp} from 'vue';
import {defineAsyncComponent} from "vue";

createApp({
    components: {
        'top-bar': defineAsyncComponent(() => import('@Partials/top-bar'))
    }
}).mount("#app")

Другие вопросы по теме