Как отобразить доменную сущность в компоненте Vuetify

Делаю свой первый проект на Vue3+TypeScript+Vuetify. В бизнес-логике используется доменная сущность "Человек".

export default interface Human {
    name: string;
    age: number;
    gender: string;

    friends: Human[];
    hobbies: Hobby[];
}

export default interface Hobby {
    name: string;
    expensive: boolean;
}

Для типизированного отображения в шаблоне сделал класс TreeView.

class TreeView {
    private enumerator = 1;
    private _root: TreeViewItem = new TreeViewItem(0, '');
    private map: Map<number, TreeViewItem> = new Map();

    constructor() {
        this.map.set(0, this._root);
    }

    get root(): TreeViewItem {
        return this._root;
    }

    public addChild(item: TreeViewItem, name: string): TreeViewItem {
        const addedItem = item.addChild(this.enumerator++, name);
        this.map.set(addedItem.id, addedItem);
        return addedItem;
    }

    public getParent(item: TreeViewItem): TreeViewItem | undefined {
        return item.parentId ? this.map.get(item.parentId) : undefined;
    }
}

class TreeViewItem {
    public id: number;
    public name: string;
    public children: TreeViewItem[] = [];
    public parentId?: number;

    constructor(id: number, name: string) {
        this.id = id;
        this.name = name;
    }

    public addChild(id: number, name: string): TreeViewItem {
        const item: TreeViewItem = new TreeViewItem(id, name);
        item.parentId = this.id;
        this.children.push(item);
        return item;
    }
}

Сделал механизм преобразования данных из доменной сущности в TreeView.

<template>
    <div>
        <h1>Home page</h1>
        <v-treeview
                open-all
                :items="items"
                activatable
        >
            <template slot="label" slot-scope="{ item }">
                <a
                        @click="handleClick(item)"
                        class="v-card gray"
                >
                    {{ item.name }}
                </a>
            </template>
        </v-treeview>
        <v-btn @click="handleAddItem">Add item</v-btn>
    </div>
</template>

<script lang="ts">

    import {reactive} from "@vue/composition-api";
    import TreeView from "@/task-list/home/TreeView";
    import Hobby from "@/task-list/home/Hobby";
    import Human from "@/task-list/home/Human";

    export default {
        name: "Home",

        setup() {
            const hobby1: Hobby = {name: 'philately', expensive: true};
            const hobby2: Hobby = {name: 'jogging', expensive: false};
            const human1: Human = {name: 'Max', age: 54, gender: 'male', friends: [], hobbies: [hobby1]};
            const human2: Human = {name: 'Tanya', age: 29, gender: 'female', friends: [], hobbies: [hobby2]};
            const human: Human =
                {
                    name: 'Mike',
                    age: 23,
                    gender: 'male',
                    friends: [human1, human2],
                    hobbies: [hobby1, hobby2]
                };

            const treeView = new TreeView();
            {
                treeView.root.name = human.name;
                for (const key in human) {
                    const value = (human as any)[key];
                    if (Array.isArray(value)) {
                        const child = treeView.addChild(treeView.root, key);
                        value.forEach(e => treeView.addChild(child, e.name));
                    }
                }
            }

            const items = reactive([treeView.root]);

            const handleClick = (item: any) => {
                alert(item.name)
            };

            const handleAddItem = (item: any) => {
                treeView.addChild(treeView.root, 'new item');
            };

            return {items, handleClick, handleAddItem}
        }
    }
</script>

При изменении объекта TreeView все прекрасно отображается. Очень бы хотелось иметь механизм отображения изменений исходной доменной сущности. Не через функцию трансформации, а сразу. Не подскажите, в какую сторону рыть? Наблюдатели, прокси, что-то ещё?


Ответы (0 шт):