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>

目标

我正在尝试围绕DataTables.net库构建一个小的VueJS包装器。

为了模仿标记中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.log(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文档,并尝试使用Google搜索,但是没有骰子。我尝试手动传递createElement函数(传递给render方法的参数),但这引发了错误。如何要求VueJS渲染VNode而不将结果注入(inject)DOM?

    最佳答案

    我遇到了一个相同的问题,希望使用DataTables.net的行详细信息模板进行基本相同的操作。

    一种解决方案是创建一个通用组件,该组件呈现出VNode并以编程方式实例化该组件。这是我使用数据表的row.child() API插入动态明细行的设置方式。

    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()
    

    09-28 07:53