VueJS渲染VNode [英] VueJS Render VNode

查看:628
本文介绍了VueJS渲染VNode的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出一个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 是能够冒泡通过< tbody> 并被 DataTable 元素成功(绕过VueJS中的限制,即您无法收听插槽上的事件)

  • What this currently does:

    • 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 the DataTable element successfully (circumventing the limitation in VueJS that you can't listen to events on slots)

      • 实际上添加行

      我的活动是给我一个 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文档,并尝试使用Google搜索,但是没有骰子。我尝试手动传递 createElement 函数(传递给 render 方法的参数),但这引发了错误。

      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?

      推荐答案

      我如何遇到VueJS渲染VNode而不将结果注入DOM的问题?

      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 : ''
          }
      }
      

      数据表。 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆