返回

Vue无限级树形选择器:高阶组件的独奏舞曲

前端

你是否曾经在你的 Vue 应用中遇到这样的场景:你需要一个树形选择器来供用户选择多层级的选项,例如一个文件系统或者一个复杂的菜单系统?为了实现这一功能,你可能会求助于第三方库,但是今天我们将向你展示如何自己使用 Vue 来构建一个无限级树形选择器,而无需依赖任何第三方库。

1. 使用递归组件构建树形结构

第一步,我们创建一个名为<tree-selector>的Vue组件,它将成为我们的树形选择器。我们使用递归组件来构建树形结构,这就意味着组件可以包含自己本身,从而形成一个无限深度的树。在<tree-selector>组件中,我们会有一个data()方法来定义组件的数据,以及一个template来渲染组件的HTML。

// tree-selector.vue
export default {
  data() {
    return {
      selected: [], // 选中的选项
      items: [] // 选项列表
    }
  },
  template: `
    <div class="tree-selector">
      <ul>
        <li v-for="item in items" @click="toggle(item)">
          {{ item.label }}
          <tree-selector v-if="item.children" :items="item.children"></tree-selector>
        </li>
      </ul>
    </div>
  `,
  methods: {
    toggle(item) {
      // 切换选项选中状态
      if (this.selected.includes(item)) {
        this.selected.splice(this.selected.indexOf(item), 1)
      } else {
        this.selected.push(item)
      }
    }
  }
}

在这个组件中,我们有一个items数组,用来存储选项列表,selected数组用来存储选中的选项。我们使用v-for循环来渲染每个选项,并使用@click事件监听器来监听选项的点击事件。当选项被点击时,我们使用toggle()方法来切换选项的选中状态。

2. 使用高阶组件管理高阶事件

下一步,我们需要创建一个高阶组件来管理高阶事件。高阶事件是指那些需要在组件树的多个层级上传播的事件。在我们的树形选择器中,我们需要能够在点击子选项时将事件传播给父组件,这样父组件才能知道子选项被选中了。

// event-emitter.js
import Vue from 'vue'

// 创建一个事件总线
const eventBus = new Vue()

export default {
  // 将事件总线挂载到组件的原型上
  beforeCreate() {
    this.$eventBus = eventBus
  },
  // 在组件销毁时,将事件总线从组件的原型上移除
  beforeDestroy() {
    delete this.$eventBus
  }
}

在这个高阶组件中,我们创建了一个eventBus事件总线。我们使用beforeCreate()beforeDestroy()钩子函数将事件总线挂载到组件的原型上。这样,组件就可以使用this.$eventBus来访问事件总线了。

3. 在树形选择器中使用高阶组件

现在,我们可以将高阶组件应用到<tree-selector>组件中,使其能够传播高阶事件。

// tree-selector.vue
import EventBus from './event-emitter.js'

export default {
  // 使用高阶组件
  mixins: [EventBus],

  methods: {
    // 在点击选项时,将事件传播给父组件
    toggle(item) {
      if (this.selected.includes(item)) {
        this.selected.splice(this.selected.indexOf(item), 1)
      } else {
        this.selected.push(item)
      }

      // 将选中状态传播给父组件
      this.$eventBus.$emit('selection-changed', this.selected)
    }
  }
}

我们在<tree-selector>组件中混入了EventBus高阶组件,这样就可以使用this.$eventBus来访问事件总线了。在toggle()方法中,当选项被点击时,我们除了切换选项的选中状态之外,还将选中状态通过事件总线传播给了父组件。

4. 在父组件中监听高阶事件

最后,我们需要在父组件中监听高阶事件,以便能够在子选项被选中时做出响应。

// parent-component.vue
<tree-selector @selection-changed="onSelectionChanged"></tree-selector>

methods: {
  onSelectionChanged(selected) {
    // 处理选中的选项
  }
}

在父组件中,我们使用@selection-changed事件监听器来监听子组件发出的selection-changed事件。当事件被触发时,onSelectionChanged()方法会被调用,我们可以在该方法中处理选中的选项。

结语

通过以上步骤,我们成功地实现了一个无限级树形选择器,它无需依赖任何第三方库,而是利用递归组件和高阶事件监听,充分展示了Vue生态的简洁和强大。希望这篇文章能够为你带来启发,让你在未来的项目中更好地使用Vue。