导读:本期聚焦于小伙伴创作的《Vue.js实现通用多级联动下拉选择框完整教程与代码详解》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Vue.js实现通用多级联动下拉选择框完整教程与代码详解》有用,将其分享出去将是对创作者最好的鼓励。

Vue.js 实现多级联动下拉选择框

多级联动下拉选择框是前端开发中常见的交互组件,比如省市区选择、商品分类筛选等场景都会用到。它的核心逻辑是上级选项发生变化时,下级选项要根据上级选中的值动态更新,同时清空已经选中的下级内容。本文将介绍如何使用 Vue.js 实现一套通用的多级联动下拉选择框,支持任意层级的联动配置。

实现思路

要实现多级联动,首先需要明确几个核心点:

  • 联动的层级和每一层的数据源需要可配置,避免硬编码导致组件无法复用
  • 每一级的选中值需要实时响应,当上级值变化时,自动触发下级数据的更新
  • 需要维护一个选中值的数组,数组长度和联动层级一致,方便后续获取完整的选中结果
  • 初始化时需要加载第一级的数据,后续层级的数据根据上级选中值动态请求或读取本地数据

基础数据准备

这里以省市区三级联动为例,我们先准备基础的模拟数据。实际开发中可以将数据替换为接口请求返回的内容,本文为了方便演示,使用本地静态数据。

// 模拟省市区数据
const regionData = [
  {
    id: 1,
    name: '北京市',
    children: [
      {
        id: 11,
        name: '北京市',
        children: [
          { id: 111, name: '东城区' },
          { id: 112, name: '西城区' },
          { id: 113, name: '朝阳区' }
        ]
      }
    ]
  },
  {
    id: 2,
    name: '广东省',
    children: [
      {
        id: 21,
        name: '广州市',
        children: [
          { id: 211, name: '天河区' },
          { id: 212, name: '越秀区' },
          { id: 213, name: '白云区' }
        ]
      },
      {
        id: 22,
        name: '深圳市',
        children: [
          { id: 221, name: '福田区' },
          { id: 222, name: '南山区' },
          { id: 223, name: '宝安区' }
        ]
      }
    ]
  }
];

// 联动配置项,每一级对应一个配置,label为下拉框的提示文本,data为当前层级的数据源
const levelConfig = [
  { label: '请选择省份', data: regionData },
  { label: '请选择城市', data: [] },
  { label: '请选择区域', data: [] }
];

组件实现

接下来我们基于 Vue 3 的 Composition API 实现联动组件,组件支持传入自定义的数据和配置,能够适配不同的联动场景。

<template>
  <div class="multi-level-linkage">
    <div class="level-item" v-for="(level, index) in levelList" :key="index">
      <label class="level-label">{{ level.label }}</label>
      <select 
        class="level-select"
        v-model="selectedValues[index]"
        @change="handleLevelChange(index)"
        :disabled="index > 0 && !selectedValues[index - 1]"
      >
        <option value="">{{ level.label }}</option>
        <option 
          v-for="item in level.data" 
          :key="item.id" 
          :value="item.id"
        >
          {{ item.name }}
        </option>
      </select>
    </div>
    <div class="result-area" v-if="selectedValues.filter(v => v).length === levelList.length">
      当前选中结果:{{ selectedLabels.join(' / ') }}
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, watch, onMounted } from 'vue';

// 定义组件入参,支持自定义层级配置和初始数据
const props = defineProps({
  // 层级配置,格式为[{label: '提示文本', data: []}]
  levelConfig: {
    type: Array,
    required: true
  }
});

// 选中的值数组,长度和层级一致,初始为空
const selectedValues = ref(props.levelConfig.map(() => ''));
// 选中的文本标签数组,用于展示结果
const selectedLabels = ref([]);
// 处理后的层级列表,包含每一层的数据和配置
const levelList = reactive(props.levelConfig.map(item => ({ ...item })));

// 根据父级选中值获取下一级的数据
const getNextLevelData = (parentId, currentLevelIndex) => {
  // 如果是第一级,直接返回初始配置的第一级数据
  if (currentLevelIndex === 0) {
    return props.levelConfig[0].data;
  }
  // 查找父级对应的数据项
  let parentData = props.levelConfig[0].data;
  for (let i = 1; i <= currentLevelIndex - 1; i++) {
    const parentId = selectedValues.value[i - 1];
    const target = parentData.find(item => item.id === parentId);
    if (!target || !target.children) return [];
    parentData = target.children;
  }
  const currentParent = parentData.find(item => item.id === parentId);
  return currentParent ? (currentParent.children || []) : [];
};

// 处理层级变化事件
const handleLevelChange = (changedIndex) => {
  // 清空当前变化层级之后的所有选中值
  for (let i = changedIndex + 1; i < selectedValues.value.length; i++) {
    selectedValues.value[i] = '';
    levelList[i].data = [];
  }
  // 如果当前层级选中了值,加载下一级的数据
  if (selectedValues.value[changedIndex]) {
    const nextIndex = changedIndex + 1;
    if (nextIndex < levelList.length) {
      levelList[nextIndex].data = getNextLevelData(selectedValues.value[changedIndex], changedIndex);
    }
  }
  // 更新选中的文本标签
  updateSelectedLabels();
};

// 更新选中的文本标签
const updateSelectedLabels = () => {
  selectedLabels.value = selectedValues.value.map((val, index) => {
    if (!val) return '';
    const target = levelList[index].data.find(item => item.id === val);
    return target ? target.name : '';
  }).filter(v => v);
};

// 初始化第一级数据
onMounted(() => {
  levelList[0].data = props.levelConfig[0].data;
});
</script>

<style scoped>
.multi-level-linkage {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 400px;
  padding: 20px;
  border: 1px solid #e5e6eb;
  border-radius: 8px;
}
.level-item {
  display: flex;
  align-items: center;
  gap: 10px;
}
.level-label {
  width: 100px;
  text-align: right;
  color: #333;
  font-size: 14px;
}
.level-select {
  flex: 1;
  height: 36px;
  padding: 0 10px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  font-size: 14px;
  color: #606266;
  outline: none;
}
.level-select:disabled {
  background-color: #f5f7fa;
  cursor: not-allowed;
}
.level-select:focus {
  border-color: #409eff;
}
.result-area {
  margin-top: 16px;
  padding: 12px;
  background-color: #f0f9eb;
  border-radius: 4px;
  color: #67c23a;
  font-size: 14px;
}
</style>

组件使用

完成组件开发后,使用方式非常简单,只需要传入对应的层级配置即可,以下是使用示例:

<template>
  <div class="app-container">
    <h3>省市区三级联动示例</h3>
    <MultiLevelLinkage :level-config="levelConfig" />
  </div>
</template>

<script setup>
import MultiLevelLinkage from './MultiLevelLinkage.vue';
import { reactive } from 'vue';

// 联动配置,和之前准备的数据对应
const levelConfig = reactive([
  { label: '请选择省份', data: regionData },
  { label: '请选择城市', data: [] },
  { label: '请选择区域', data: [] }
]);

// 引入之前定义的regionData
import { regionData } from './data.js';
</script>

功能扩展

上述实现是基础版本,实际使用中可以根据需求扩展更多功能:

  • 支持异步加载数据:将 getNextLevelData 方法改为接口请求,在请求完成后再赋值给下一级的 data,加载时可以添加 loading 状态提示
  • 支持设置默认值:在组件初始化时,传入默认的选中值数组,自动触发各级数据加载,回显选中状态
  • 支持任意层级:目前的实现支持任意长度的 levelConfig,不需要修改组件逻辑,只需要配置对应的层级即可
  • 添加事件回调:当选中值变化时,通过 emit 向外抛出选中结果,方便父组件处理后续业务逻辑

通过 Vue 的响应式特性,我们只需要维护好选中值数组和每一级的数据源,就能很方便地实现多级联动效果,组件的可复用性也很高,适用于大部分需要联动选择的业务场景。

Vue.js多级联动下拉选择框前端组件Composition_API

免责声明:已尽一切努力确保本网站所含信息的准确性。网站部分内容来源于网络或由用户自行发表,内容观点不代表本站立场。本站是个人网站免费分享,内容仅供个人学习、研究或参考使用,如内容中引用了第三方作品,其版权归原作者所有。若内容触犯了您的权益,请联系我们进行处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。前端、网络、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握网站开发与运维所需的核心技术栈。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端逻辑,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。