构建TreeView组件-对选择元素做出反应的最佳方法?

时间:2019-12-15 14:06:19

标签: javascript vue.js

我正在构建自己的Tree View组件,该组件允许选择树的元素(单选)。我正在使用一个递归调用自己的TreeNode子组件。到目前为止,一切都很好,树已经构建好了,我正要对选择(单击)元素做出反应。

我在以下两种方法之间犹豫不决:

  1. 在TreeNode组件上使用selectedKey道具(所选元素的ID),并在每次单击元素时发出'update:selectedKey'事件。由于selectedKey是TreeNode的支持,这会将事件(即所选ID)传播到树的根节点(由于事件在每个树节点中发出),然后传播回所有子节点。最后,每个树节点实例都通过计算属性来确定它是否为选定的树实例。这是TreeNode.vue示例代码(已大大简化):
<template>
  <div>
    <div @click="selectNode">{{ node.label }}</div>
    <TreeNode v-for="node of node.children" :key="node.key"
              :node="node"
              :selectedKey="selectedKey"
              @update:selectedKey="$emit('update:selectedKey', $event)"/>
  </div>
</template>
export default {
  props: ['node', 'selectedKey'],
  computed: {
    isSelected () {
      return this.node.key === this.selectedKey
    }
  },
  methods: {
    selectNode () {
      this.$emit('update:selectedKey', this.node.key)
    }
  }
}
  1. 使用事件总线,所有节点都在事件总线上注册以监听'nodeSelected'事件。每当单击某个元素时,它都会发出该事件,并提供所选元素的ID作为有效负载,然后每个节点都会接收该事件并检查是否应选择该事件。这是示例代码:
<template>
  <div>
    <div @click="selectNode">{{ node.label }}</div>
    <TreeNode v-for="node of node.children" :key="node.key" :node="node"/>
  </div>
</template>
export default {
  props: ['node'],
  data (): {
    selectedKey: null
  },
  computed: {
    isSelected () {
      return this.node.key === this.selectedKey
    }
  },
  created () {
    this.$root.$on('nodeSelected', this.onNodeSelected)
  },
  beforeDestroy () {
    this.$root.$off('nodeSelected', this.onNodeSelected)
  },
  methods: {
    selectNode () {
      this.$root.$emit('nodeSelected', this.node.key)
    },
    onNodeSelected (selectedKey) {
      this.selectedKey = selectedKey
    }
  }
}

现在我的问题-以上哪种方法是首选方法-一种更紧密地遵循Vue最佳实践和准则,并能确保更好的性能和可伸缩性的方法

我必须说,在测试过程中,我注意到第二种方法可能会更快地工作,即有迹象表明,鼠标单击和元素选择之间的延迟(我对选定元素应用了一些背景)小于第一种方法。我将其归因于以下事实:在第一种情况下,有一个事件必须一直传播到根节点,然后再返回到树的所有元素。我的树甚至不大-只有14个节点。但是我可能错了:)

第二种方法的第二个问题-如何将Tree组件(这是包含TreeNode组件的递归树的主要父组件)传递给所有子代,以便他们注册'nodeSelected'事件而不是根Vue组件上?这将使整个Tree View组件更加封装和独立。

谢谢!

0 个答案:

没有答案