BLOG

ブログ

2023/10/24 技術系

【Vue】Vue-3-Treeviewでツリービューを表示する

この記事を書いた人 WD
画像1

Vuetify 3v-treeviewが使えなくなっていたので、代わりにVue-3-Treeviewというライブラリを使ってみました。

動作環境

  • Vue: 3.2.41
  • vue3-treeview: 0.4.1

導入

公式サイトに従ってインストールします。

npm install vue3-treeview

使用例

ツリービューを表示する

今回はチェックボックスを表示したかったのでconfigに設定します。
配列のkeyがidに、textが表示名になります。
childrenに子階層のkeyを指定します。

<script setup>
import 'vue3-treeview/dist/style.css';
import Tree from 'vue3-treeview';
import { ref, reactive } from 'vue';

const config = ref({
    roots: ["id1", "id2"], // 第一階層のkey
    checkboxes: true, // チェックボックスあり
    checkMode: 0, // 親階層をチェックした際に子階層もチェックする
    padding: 22,
});

const nodes = reactive({
    id1: {
        text: "text1",
        children: ["id11", "id12"],
        state: {
            opened: true, // デフォルトで開く
        }
    },
    id11: {
        text: "text1-1",
        children: [],
    },
    id12: {
        text: "text1-2",
        children: [],
    },
    id2: {
        text: "text2",
        children: ["id21"],
    },
    id21: {
        text: "text2-1",
        children: ["id211"],
    },
    id211: {
        text: "text2-1-1",
        children: [],
    },
});
</script>

<template>
    <Tree :config="config" :nodes="nodes"></Tree>
</template>
表示時
チェック時

チェックした値を取得する

残念ながら、v-modelでチェックしたidのリストを取得することはできませんでした。

  • チェックすると元データnodesstate.checkedが変わる
  • 親階層をチェックしても子階層のstate.checkedは変わらない

以上を踏まえて対応し、チェックしたidを取得できるようにしました。

<script setup>
(省略)

const checked = ref([]);

const nodes = reactive({
    id1: {
        text: "text1",
        children: ["id11", "id12"],
        state: {
            opened: true,
            checked: false, // state.checkedのデフォルト値をセットしておく
        }
    },
    (省略)
    id211: {
        text: "text2-1-1",
        children: [],
        state: { checked: false }
    },
});

const getChecked = (node) => {
    // 親階層のcheckedを子階層に反映
    for (const key in node.children) {
        let id = node.children[key];
        nodes[id].state.checked = node.state.checked;
    }

    checked.value = [];
    for (const key in nodes) {
        if (nodes[key].children.length === 0) {
            if (nodes[key].state.checked) {
                checked.value.push(key);
            }
        }
    }
}
</script>

<template>
    <Tree
        :config="config"
        :nodes="nodes"
        @nodeChecked="getChecked"
        @nodeUnchecked="getChecked"
    >
    </Tree>
    {{ checked }}
</template>

文字をクリックしてチェックできるようにする

デフォルトではチェックボックス自体をクリックしなければチェックされないので、文字の部分もクリックできるようにしました。
textを空にして、after-inputスロットでbuttonを表示しています。

<script setup>
(省略)

const nodes = reactive({
    id1: {
        id: "id1", // idを追加
        text: "", // textは空にする
        name: "text1",
        children: ["id11", "id12"],
        state: {
            opened: true,
            checked: false,
        }
    },
    (省略)
    id211: {
        id: "id211",
        text: "",
        name: "text2-1-1",
        children: [],
        state: { checked: false }
    },
});

const getChecked = (node) => {
    (省略)
}

const clickText = (node) => {
    nodes[node.id].state.checked = !node.state.checked;
    getChecked(node);
}
</script>

<template>
    <Tree
        :config="config"
        :nodes="nodes"
        @nodeChecked="getChecked"
        @nodeUnchecked="getChecked"
    >
        <template #after-input="item">
            <button @click="clickText(item.node)">{{ item.node.name }}</button>
        </template>
    </Tree>
</template>

構造を理解するのに少し戸惑いましたが、気軽に使うことができて良かったです。
もしUIフレームワークに頼らずツリービューを実現したいようなケースがあれば、参考になれば幸いです。



株式会社ウイングドアは福岡のシステム開発会社です。
現在、私達と一緒に"楽しく仕事が出来る仲間"として、新卒・中途採用を絶賛募集しています!
ウイングドアの仲間達となら楽しく仕事できるかも?と興味をもった方、
お気軽にお問い合わせ下さい!

アーカイブ