MST

星途 面试题库

面试题:Vue表单绑定中复杂异步数据加载及联动绑定处理

在一个Vue项目中有一个表单,其中包含两个下拉框。第一个下拉框加载一级分类数据,第二个下拉框根据第一个下拉框选中的值,异步加载对应的二级分类数据并绑定。请详细阐述实现思路,包括如何处理异步加载过程中的加载状态、错误处理以及数据绑定逻辑,并给出关键代码实现。
49.5万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 一级分类数据加载:在Vue组件的created钩子函数中,通过HTTP请求获取一级分类数据,并绑定到组件的data属性上,用于渲染第一个下拉框。
  2. 二级分类数据异步加载:监听第一个下拉框的change事件,获取选中的一级分类ID。根据该ID发送HTTP请求,异步获取对应的二级分类数据,并绑定到组件的另一个data属性上,用于渲染第二个下拉框。
  3. 加载状态处理:在发起异步请求时,设置一个loading标志为true,在请求完成(无论成功或失败)时,将其设置为false。根据这个标志在模板中显示加载指示器。
  4. 错误处理:在异步请求失败时,捕获错误,设置一个error标志为true,并在模板中显示错误提示信息。同时,可以记录错误日志以便排查问题。
  5. 数据绑定逻辑:使用Vue的v-model指令将下拉框的值与组件的data属性进行双向绑定,确保选中值能够正确反映在组件数据中,并在数据变化时更新视图。

关键代码实现

<template>
  <div>
    <select v-model="selectedFirstCategory" @change="loadSecondCategories">
      <option v-for="category in firstCategories" :key="category.id">{{ category.name }}</option>
    </select>

    <select v-if="secondCategories" v-model="selectedSecondCategory">
      <option v-for="category in secondCategories" :key="category.id">{{ category.name }}</option>
    </select>

    <div v-if="loading">加载中...</div>
    <div v-if="error">加载二级分类数据出错</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      firstCategories: [],
      secondCategories: null,
      selectedFirstCategory: null,
      selectedSecondCategory: null,
      loading: false,
      error: false
    };
  },
  created() {
    this.fetchFirstCategories();
  },
  methods: {
    async fetchFirstCategories() {
      try {
        const response = await fetch('/api/first-categories');
        this.firstCategories = await response.json();
      } catch (error) {
        console.error('加载一级分类数据出错', error);
      }
    },
    async loadSecondCategories() {
      this.loading = true;
      this.error = false;
      try {
        const response = await fetch(`/api/second-categories?firstCategoryId=${this.selectedFirstCategory}`);
        this.secondCategories = await response.json();
      } catch (error) {
        this.error = true;
        console.error('加载二级分类数据出错', error);
      } finally {
        this.loading = false;
      }
    }
  }
};
</script>