【问题标题】:VueJS Render VNodeVueJS 渲染 VNode
【发布时间】:2018-05-27 20:37:34
【问题描述】:

tl;博士:

给定一个 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 个条目”
  • CustomEvent 能够冒泡越过&lt;tbody&gt; 并被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 在不将结果注入 DOM 的情况下渲染 VNode?​​p>

【问题讨论】:

    标签: javascript vue.js datatables vuejs2


    【解决方案1】:

    我遇到了同样的问题,想用 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() 
    

    【讨论】:

      【解决方案2】:

      你应该像这样定义你的组件:

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

      【讨论】:

        猜你喜欢
        • 2018-01-09
        • 2022-01-09
        • 1970-01-01
        • 2021-01-20
        • 2018-08-27
        • 1970-01-01
        • 2019-01-05
        • 2018-12-25
        • 1970-01-01
        相关资源
        最近更新 更多