Vue.jsの再帰コンポーネントの投稿では、再帰ツリーコンポーネントを構築する方法を見てきましたが、ツリー全体でアクションを伝達する必要はありませんでした。 この投稿でその問題に取り組みましょう。

コミュニケーションとはどういう意味ですか?

前の記事のNodeTreeがクリックされたときに確認し、それを外部コンポーネント( Tree コンポーネントを使用しているコンポーネント)に伝達するとします。

Vue.jsでは、カスタムイベントを使用して上向きの通信が行われます。 しかし、Vue.js1.xまたはAngular1.xから、複数のレベルにまたがるイベントを持つことは悪い習慣であり、推論するのが難しいコードベースになることを学びました。 そのため、Vue.js 2以降、カスタムイベントは1つの子から親へのレベルでのみ許可されます。

それを知って、次のようなツリーを想像してください。

+ Folder 1
  + Folder 2
    + Folder 3
      + Folder 4
        + Folder 5

カスタムイベントを使用してFolder 5からクリックイベントを伝達する場合は、イベントを5回発行する必要があります。

木がいくつあるかは事前にわからないので、木には無限の深さがあると言えます。 そのため、カスタムイベントを使用すると、実行不可能で非効率的で複雑になります。

小道具を使用した再帰的コミュニケーションの解決

はVue.jsでpropsとして関数を使用できることを忘れないでください。 Reactとは異なり、Vue.jsには子から親への通信用のカスタムイベントがあるため、これは一般的なパターンではありません。 しかし、このような場合には、それは本当に便利です。

各レベルでイベントを発行するのとは異なり、関数への同じ参照を渡すだけでよいため、これははるかに単純でパフォーマンスが高くなります。

handleClickプロパティをNodeTree.vueコンポーネントに追加し、クリックイベントに使用してみましょう。

NodeTree.vue
<template>
  <li class="node-tree">
    <span class="label" @click="handleClick(node)">{{ node.label }}</span>

    <ul v-if="node.children && node.children.length">
      <node
        v-for="child in node.children"
        :node="child"
        :handle-click="handleClick">
      </node>
    </ul>
  </li>
</template>

<script>
export default {
  name: "node",
  props: {
    node: Object,
    handleClick: Function
  }
};
</script>

タイプをFunctionとして設定し、ラベル@clickイベントで使用して、子ノード:handle-click="handleClick"に再度渡すことに注意してください。

アウターコミュニケーション

Tree.vue コンポーネントから、その関数をルートノードに渡す必要があります。

さらに、外部( Tree を使用するコンポーネント)からのクリックを処理する方法を提供する必要があります。これには、1つ上のレベルであるため、実際にカスタムイベントを使用できます。

Tree.vue
<template>
  <div class="tree">
    <ul class="tree-list">
      <node-tree :node="treeData" :handle-click="handleClick"></node-tree>
    </ul>
  </div>
</template>

<script>
import NodeTree from "./NodeTree";

export default {
  props: {
    treeData: Object
  },
  methods: {
    handleClick (node) {
      this.$emit('node-click', node);
    }
  }
  components: {
    NodeTree
  }
};
</script>

ご覧のとおり、TreeコンポーネントにローカルなhandleClickメソッドを追加しました。このメソッドは、node-treeに渡されます。 このメソッドは、$emit Vueインスタンスメソッドを使用して、データのノードでイベントを発行します。

これにより、テンプレートで@node-clickを使用することで、優れたAPI構文を維持しながら、App.vueまたはその他の外部コンポーネントからのクリックを処理できます。

App.vue
<template>
  <div>
    <tree :tree-data="tree" @node-click="logClick"></tree>
  </div>
</template>

<script>
import Tree from "./Tree";

export default {
  data: () => ({
    // ...
  }),
  methods: {
    logClick(node) {
      console.log("Clicked: ", node);
    }
  },
  components: {
    Tree
  }
};
</script>

まとめ

ご覧のとおり、「無限レベル」の通信の問題を修正するために、Reactコミュニティで非常に一般的なパターン、つまり関数をプロパティとして渡すパターンを利用しました。 これにより、再帰コンポーネントのパフォーマンスと推論を容易に保ちながら、再帰コンポーネントのクリックアクションを簡単に処理できるようになりました。

涼しくしてください🦄