TreeViewコンポーネント(Vuetify)の「Async items」機能について
背景
Vuetifyの公式サイトを見ていて、treeviewコンポーネントに「Async items」という機能があるのを見つけたので試してみた。
https://vuetifyjs.com/ja/components/treeview/
簡単に説明すると、ツリーのノードを開いた瞬間に子要素のデータを取得しに行く機能。
まぁ、ツリーのコンポーネントなら普通は持ってるよねって感じの機能ですが、使ってみると色々見えてきたりするので。。。
あと、今回はローカルファイルからのデータ読み込みをやるので、ついでに、VS CodeのLive Serverを試してみようと思う(実はこっちが本当の目的だったりする)。
ツリーコンポーネントへの「Async items」の適用
以前作成したWebComponents用ツリーコンポーネントのサンプルは、コード内にデータをべた書きしていたので、これを他からデータを取得してくるように変えてみる。
準備
以前作成したWebComponents用ツリーコンポーネントのコードを落としてくる。
> git clone https://github.com/yusuke-ka/sample-vce-vuetify.git
インストール。
> cd sample-vce-vuetify
> yarn install
元のコードは下のようになっていて、データ(items)は固定になっている。
<template>
<div id="app">
<v-app id="inspire">
<v-treeview selectable :items="items"></v-treeview>
</v-app>
</div>
</template>
<script>
...
export default {
el: "#app",
vuetify: new Vuetify({
icons: {
iconfont: "md",
},
}),
data: () => ({
items: [
{
id: 1,
name: "Applications :",
children: [
{ id: 2, name: "Calendar : app" },
{ id: 3, name: "Chrome : app" },
{ id: 4, name: "Webstorm : app" },
],
},
....
],
}),
};
</script>
yarn buildでビルドすると、ツリーコンポーネントがWebComponents化されてbundle.jsが生成されて、他から呼び出せるようになる。
プロジェクト直下に下記のようなindex.htmlを置くと、ローカルでの動作確認ができる。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Custom Element By Vue + Vuetify</title>
<script src="dist/bundle.js"></script>
</head>
<body>
<vce-tree></vce-tree>
</body>
</html>
こんな感じ↓
これを、ノードを開くタイミングで子要素を取得してくるように変更してみる。
コード修正
まず、template部分に:load-childrenを追加。メソッド(算出プロパティ)名は「fetchData」にしておく。
また、メソッド名が紛らわしいので、「:items="items"」は「:items="itemList"」に変更しておく。
<template>
<div id="app">
<v-app id="inspire">
<v-treeview
selectable
:items="itemList"
:load-children="fetchData"
></v-treeview>
</v-app>
</div>
</template>
script部分は、dataのitemsは空にしておき、computedでitemList()を定義する。
さらに、methodsでfetchData()を定義。ここでデータを取得する。
普通はバックエンドのサーバーからデータを取得するんだけど、今回はローカルファイルを指定。
あと、外部からデータを取得しているのを分かりやすくするために、最初にpauseを定義して、意図的に待ち時間を入れている。
<script>
...
const pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export default {
...
data: () => ({
items: [],
}),
computed: {
itemList() {
return [
{
name: "ItemList",
children: this.items,
},
];
},
},
methods: {
async fetchData(item) {
await pause(1000); // 意図的に待ち時間を発生させる
return fetch("./data.json")
.then((res) => res.json())
.then((json) => item.children.push(...json))
.catch((err) => console.warn(err));
},
},
};
</script>
ローカルに置いたデータファイル(data.json)はこちら。
[
{
"id": 1,
"name": "ChildA :",
"children": [
{
"id": 4,
"name": "ChildA-1 :"
}
]
},
{
"id": 2,
"name": "ChildB :",
"children": []
},
{
"id": 3,
"name": "ChildC :"
}
]
vuetifyのtreeviewでは、「children」を空にしてやると、そのノードを開いた際に「:load-children」に定義したメソッドが実行されるらしいので、上のデータでは「ChildB」だけその状態にしている。
動作確認
このままビルドして、index.htmlを再表示してみる。
ローカルファイルを読み込んでいるので、最近のブラウザだとCORSのエラーが発生する。
ということで、予定通りVS CodeにLive Serverを入れて対応する。
Live Serverの導入
VS CodeのExtensions(MARKETPLACE)で、「Live Server」で検索
Live ServerのExtensionが表示されるので、「Install」ボタンからインストールする。
導入完了。
実行も簡単。
index.htmlをVS Code上で開いた状態で、右下にある「Go Live」を押す。
自動的にブラウザが立ち上がり、index.htmlが表示される。
動作確認(再)
初期表示では、「itemList()」の実行結果として、ルートノードが表示される。
ノードを開くと、fetchData(item)が実行されて、「data.json」に書いたデータが表示される。
続いて取得したデータの子要素を開いてみる。
ChildAの子要素「ChildA-1」は「data.json」に定義されているので、最初のデータ取得で一緒に取得され、即座に展開される。
ChildBの子要素は「data.json」には空で定義されているので、展開しようとした際にfetchData(item)が実行されて再度取得される。
(※本来は引数のitemで指定したノードの子要素を取りに行くべきだが、今回はitemを無視して「data.json」を読むので最初と全く同じデータが展開される。)
ChildCは「data.json」で「children」を指定していないので、そもそもノードが展開できない。
ということで、treeviewコンポーネントで動的に子要素を取得するように変更できました。
さいごに
ローカルで色々書いていると、CORSのエラーにはよく遭遇する。
今までは、わざわざS3でホスティングして確認していたので結構面倒だったが、Live Serverを使うことでだいぶ楽になることが分かった。
treeviewコンポーネントへの「Async items」導入については、「順次ロードさせるためにはchildrenを空にして返してやる必要がある」ってのが分かったことが収穫かな。(※まぁ公式サイトに書いてあるんですが。)
Author And Source
この問題について(TreeViewコンポーネント(Vuetify)の「Async items」機能について), 我々は、より多くの情報をここで見つけました https://qiita.com/yusuke-ka/items/c14deb472613accccc8a著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .