programing

VueJ 렌더링 VNode

goodcopy 2022. 7. 19. 21:25
반응형

VueJ 렌더링 VNode

tl;dr:

VueJ 지정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>

내가 지금까지 한 일

다음과 같이 구현하기 시작했습니다.

데이터 테이블표시하다

<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 to 0 of 0 entries"가 표시됩니다.
  • CustomEvent버블이 되어 버립니다.<tbody>잡히고 말았어요DataTable요소 성공(VueJ에서 슬롯에서 이벤트를 수신할 수 없는 제한 없음)

이것이 할 수 없는 일:

  • 실제로 행을 추가합니다.

내 이벤트는 나에게 다양한 것을 주고 있다.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 문서를 훑어보고 구글을 검색해 보았지만, 그럴 가능성은 없었다.수동으로 전달을 시도했습니다.createElementfunction(에 전달된 파라미터)rendermethod)에서 에러가 발생하였습니다.결과를 DOM에 삽입하지 않고 VueJ에 VNode 렌더링을 의뢰하려면 어떻게 해야 합니까?

DataTables.net용 행 상세 템플릿에서도 기본적으로 동일한 작업을 수행하고자 하는 동일한 문제가 발생했습니다.

한 가지 해결방법은 일반적인 컴포넌트를 렌더링하는 것입니다.VNode프로그래밍 방식으로 인스턴스화 할 수 있습니다.데이터 테이블을 사용하여 삽입하는 동적 상세 행에 대한 설정 방법은 다음과 같습니다.row.child()API.

RenderNode.js

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

데이터 테이블표시하다

위에서 렌더러 컴포넌트 포함

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

언급URL : https://stackoverflow.com/questions/50556294/vuejs-render-vnode

반응형