Как отобразить доменную сущность в компоненте 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 все прекрасно отображается. Очень бы хотелось иметь механизм отображения изменений исходной доменной сущности. Не через функцию трансформации, а сразу. Не подскажите, в какую сторону рыть? Наблюдатели, прокси, что-то ещё?