解决Vue中el-select第二次选择选项时才会显示上一个选项的响应结果

发布时间 2023-08-23 16:58:55作者: 星眼小橘

今天在写一个选择器的时候出现一个问题

这个功能需求是:通过选择器选择不同的选项,点击查询按钮发送请求,并将响应结果放到一个div中用v-if控制是否显示。

看似简单的一个功能,却出现一个很搞笑的bug。在我选择一个选项点击查询,本应该显示结果的div没有显示出来,而在选择一个其他选项,不需要点击查询按钮,这个div就自动显示出来了

附上我的代码,这里使用Vue3的组合式API

<template>
    <span>班级:</span>
    <el-select v-model="classId" class="m-2" placeholder="Select" size="large">
        <el-option v-for="item in options" :key="item.id" :label="item.className" :value="item.id" />
    </el-select>
    <span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <el-button type="primary" round @click="search">查询</el-button>
    <br>
    <div v-if="isDisplay">
        <el-link v-for="item in checkNames" :key="item" @click="download(item)">
            {{ item }}
        </el-link>
    </div>
</template>
<script setup>
import { ref } from 'vue';
import { getServerUrl } from '../../config/url';
import axios from 'axios';
    
let isDisplay = ref(false);
function search() {
    isDisplay.value = true;
    //发送请求,获得响应
    axios.get(getServerUrl() + "/getCheckByClass/" + classId.value)
        .then((response) => {
            const respData = response.data;
            console.log(respData.data);
            checkNames = respData.data;
        })
}

那么该如何解决呢?

第一步:首先判断你的变量有没有使用Vue的响应式状态,选项式API只需要把变量放到data()中并且return就好了

let isDisplay = ref(false);或者let isDisplay = reactive(false);

第二步:在请求结束的.then中改变isDisplay的值。因为异步操作和响应式数据更新的时机不同步,在查询函数 search() 中将 isDisplay 设置为 true,但由于涉及异步操作(axios 请求),在数据还没有返回之前,页面就已经渲染完毕了。

问题看似解决了,但是依然会发现另外一个bug,只有第一次正常,到后面又出现刚刚的问题了。

这是什么原因呢,这是由于Vue的响应性机制造成的。所以需要在查询时先重置变量内容,下面是完整的代码。

function search() {
    //重置变量内容
    checkNames = [];
    isDisplay.value = false;
    //发送请求,获得响应
    axios.get(getServerUrl() + "/getCheckByClass/" + classId.value)
        .then((response) => {
            const respData = response.data;
            console.log(respData.data);
            checkNames = respData.data;
        //响应后更改状态
            isDisplay.value = true;
        })
}

问题到这里就解决了