Vue:修复v-for生成元素点击后数据全局显示的问题
解决Vue组件点击后全局更新数据的问题
嘿,这个问题我之前开发Vue项目时也碰到过!核心原因很简单:你现在用了一个全局的strainData变量,所有的strain-description组件都绑定了同一个数据源,所以不管点击哪个图标,所有组件都会跟着更新数据。咱们来一步步修复这个问题:
核心思路
给每个单独的strain条目存储它自己的详情数据,而不是用一个全局变量共享所有数据。我们可以把strainData改成一个对象,用strain的id作为键,这样每个id对应一组专属的详情数据。
修改步骤
1. 调整Strain.vue的data定义
把原来的strainData保留为对象,用来存每个strain的详情:
data(){ return{ strains: [], apiKey: 'removed-for-stack-overflow', strainData: {}, // 用id作为键,存储对应strain的详情 } },
2. 更新getDetails方法,把数据存到对应id下
修改请求成功后的赋值逻辑,把获取到的数据绑定到当前点击的strain的id上:
getDetails: function(id){ const descApi = fetch(`https://strainapi.evanbusse.com/${this.apiKey}/strains/data/desc/${id}`); const effectApi = fetch(`https://strainapi.evanbusse.com/${this.apiKey}/strains/data/effects/${id}`); const flavourApi = fetch(`https://strainapi.evanbusse.com/${this.apiKey}/strains/data/flavors/${id}`); axios.all([descApi, effectApi, flavourApi]) .then((values)=> axios.all(values.map(value => value.json()))) .then((data) => { this.strainData[id] = data; // 把数据存到对应id的键下,实现数据隔离 }); }
3. 修改模板,给每个组件传递对应的数据
在strain-description组件上,只传递当前strain对应的详情数据,并且添加v-if判断,确保有数据时才渲染(避免空数据报错):
<div id="strain-container" v-for="(strain, index) in strains" :key="index" > <h3>{{ strain.name }}</h3> <p>{{ strain.race }}</p> <i class="fas fa-info-circle" @click="getDetails(strain.id)"></i> <!-- 只渲染当前strain有详情数据的组件,并且传递对应的数据 --> <strain-description v-if="strainData[strain.id]" :strainData="strainData[strain.id]"></strain-description> </div>
4. 优化strainDescription.vue,避免空数据报错
给模板里的表达式加上可选链操作符?.,防止数据还没加载时出现报错:
<template> <div id="strain-description"> <p>{{ strainData?.[0]?.desc }}</p> <p>{{ strainData?.[1] }}</p> <p>{{ strainData?.[2] }}</p> </div> </template>
可选优化方案:把详情数据存在strains数组里
如果你觉得用对象存储不够直观,也可以把每个strain的详情直接存在strains数组的对应元素里:
- 点击时传入
index:
<i class="fas fa-info-circle" @click="getDetails(strain.id, index)"></i>
- 修改getDetails方法:
getDetails: function(id, index){ // ... 之前的请求代码 .then((data) => { // 用$set确保响应式更新 this.$set(this.strains, index, {...this.strains[index], details: data}); }); }
- 模板里直接使用strain的details:
<strain-description v-if="strain.details" :strainData="strain.details"></strain-description>
这样修改后,每个strain条目只会显示自己被点击后获取到的详情数据,不会再全局更新啦!
内容的提问来源于stack exchange,提问作者notmynamelastname
相关产品推荐
相关产品推荐

