问题描述
给定一个 VueJS VNode
对象,我如何获取渲染后生成的 HTML 元素?
Given a VueJS VNode
object, how do I get the HTML element that would be generated if it were rendered?
例如:
> 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 包装器.
Goal
I'm attempting to build a small VueJS wrapper around the DataTables.net library.
为了在我的标记中模仿 HTML 表格的行为,我想要如下内容:
To mimic the behavior of HTML tables in my markup, I want something like the following:
<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>
到目前为止我做了什么
我已经开始按如下方式实施:
What I've done so far
I've started to implement this as follows:
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
能够冒泡通过并被
DataTable
元素成功 捕获strong>(规避了 VueJS 中不能在 slot 上监听事件的限制)- When the page loads, the DataTable is initialized. So the column headers are properly formatted and I see "Showing 0 to 0 of 0 entries" in the bottom left
- The
CustomEvent
is able to bubble up past the<tbody>
and be caught by theDataTable
element successfully (circumventing the limitation in VueJS that you can't listen to events on slots) - 实际添加行
What this currently does:
我的事件给了我一组 VNode
对象.在我的行中,每列有一个 VNode
.DataTables API 有一个 addRow
函数,可以这样调用:
My event is giving me an array of VNode
objects. There's one VNode
per column in my row. The DataTables API has an addRow
function which can be called like so:
this.instance.row.add(["col1", "col2", "col3"]);
就我而言,我希望 VNode 渲染的结果元素成为该数组中的元素.
In my case, I want the resultant element from the rendering of the VNode to be the elements in this array.
var elems = [];
for (var i = 0; i < row.length; i++)
elems[i] = compile(row[i]);
this.instance.row.add(elems);
不幸的是,这个 compile
方法避开了我.我尝试浏览 VueJS 文档并尝试谷歌搜索它,但没有骰子.我尝试手动传递 createElement
函数(传递给 render
方法的参数),但这引发了错误.如何在不将结果注入 DOM 的情况下让 VueJS 渲染 VNode?
Unfortunately this compile
method eludes me. I tried skimming the VueJS documentation and I tried Googling it, but no dice. I tried manually passing the createElement
function (the parameter passed to the render
method) but this threw an error. How can I ask VueJS to render a VNode without injecting the result into the DOM?
推荐答案
我遇到了同样的问题,想要对 DataTables.net 的行详细信息模板做基本相同的事情.
I ran into the same issue wanting to do basically the same thing with a row details template for DataTables.net.
一种解决方案可能是创建一个通用组件来呈现 VNode
并以编程方式对其进行实例化.这是我使用数据表的 row.child()
API 插入的动态详细信息行的设置方法.
One solution could be to create a generic component that renders out a VNode
and instantiate that programmatically. Here is how my setup for a dynamic detail row that I insert using datatable's 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
Instantiate and mount the renderer to get the compiled 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()
这篇关于VueJS 渲染 VNode的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!