Vue3:修改filteredData为何会改动原始Store的countriesData?如何解决
问题:修改filteredData时意外改动了countriesData
在Vue项目中,我们期望countriesData仅通过异步请求初始化一次后不再变动,filteredData用于存储搜索筛选后的结果。但执行搜索逻辑后,发现countriesData也被修改成了筛选后的单个数据,只有注释掉filteredData.value = [countriesData.value[i]]这行代码,countriesData才会保持原样。
Store代码
import { ref } from "vue"; // Store for all data export const countriesData = ref(); export const isLoading = ref(true); async function getData() { try { isLoading.value = true; const response = await fetch("https://restcountries.com/v3.1/all"); const data = await response.json(); countriesData.value = data; } catch (error) { console.error("error", error); } finally { isLoading.value = false; } } getData(); // Store for filtered data export const filteredData = ref(countriesData);
搜索组件代码
<script setup> import { ref } from "vue"; import { countriesData, filteredData } from "../../store/store"; const searchValue = ref(""); function handleSubmit(e) { e.preventDefault(); console.log(countriesData.value.length); for (let i = 0; i < countriesData.value.length; i++) { console.log(countriesData.value.length); if ( countriesData.value[i].name.common.toLowerCase() === searchValue.value.toLowerCase().trim() ) { filteredData.value = [countriesData.value[i]]; // setError(false); searchValue.value = ""; return; } else { // setError(true); } } } </script>
问题原因
核心问题出在Store里的filteredData初始化代码:
export const filteredData = ref(countriesData);
这里直接把countriesData这个ref对象传给了filteredData的ref构造函数,导致两个ref指向了同一个引用值。当你修改filteredData.value时,本质上是在修改countriesData.value的内容,因为它们共享同一个数组引用。
解决方案
1. 修正Store中filteredData的初始化逻辑
将filteredData初始化为独立的空数组,在异步请求完成后复制一份countriesData的数据进去:
import { ref } from "vue"; // Store for all data export const countriesData = ref(); export const isLoading = ref(true); export const filteredData = ref([]); // 初始化为空数组 async function getData() { try { isLoading.value = true; const response = await fetch("https://restcountries.com/v3.1/all"); const data = await response.json(); countriesData.value = data; filteredData.value = [...data]; // 浅拷贝数据,创建新数组 // 如果数据存在嵌套对象,需要深拷贝的话用下面这行: // filteredData.value = JSON.parse(JSON.stringify(data)); } catch (error) { console.error("error", error); } finally { isLoading.value = false; } } getData();
2. 优化搜索逻辑(可选)
用数组的find方法替代for循环,代码更简洁:
<script setup> import { ref } from "vue"; import { countriesData, filteredData } from "../../store/store"; const searchValue = ref(""); function handleSubmit(e) { e.preventDefault(); const searchTerm = searchValue.value.toLowerCase().trim(); // 查找匹配的国家 const matchedCountry = countriesData.value.find(country => country.name.common.toLowerCase() === searchTerm ); if (matchedCountry) { // 如果需要避免后续修改filteredData中的对象影响原数据,可深拷贝 filteredData.value = [matchedCountry]; // filteredData.value = [JSON.parse(JSON.stringify(matchedCountry))]; searchValue.value = ""; // setError(false); } else { // setError(true); // 无匹配时可清空筛选结果或保留原数据 // filteredData.value = []; } } </script>
内容的提问来源于stack exchange,提问作者Ninety9Balloons
相关产品推荐
相关产品推荐

