Vue.js 2组件循环渲染时数据绑定异常问题求助
Vue组件数据绑定异常问题解决
问题场景
我是Vue.js新手,实现了一个包含Bootstrap Modal的scoring-button组件,通过v-for循环渲染多个实例。但仅首个组件能正确接收父组件传递的props数据,其余组件的row.id相关数据存在异常。尝试过重置Bootstrap Modal数据、v-model、$emit等方案均无效,怀疑和Bootstrap Modal有关。
问题根源
- Modal ID重复:每个
scoring-button组件内的Modal都使用固定id="scoringModal",Bootstrap通过ID查找Modal时只会匹配第一个,导致所有按钮都触发首个组件的Modal,表现为其他组件数据异常。 - Radio组冲突:所有组件内的radio使用相同
name="btnScore",不同组件的radio会互相干扰选中状态。 - Props同步问题:组件data中直接赋值props(如
scoredLoadId: this.loadId),当父组件props更新时,data不会自动同步。 - 未定义方法:模板中调用了
clearSelectedCause但组件未实现该方法。
修复步骤
1. 给Modal生成唯一ID
每个组件的Modal使用loadId拼接唯一ID,确保Bootstrap能正确找到对应组件的Modal。
2. 同步按钮的Modal目标ID
按钮的data-bs-target对应修改为唯一的Modal ID。
3. 修复Radio组
给radio的name属性加上loadId,保证每个组件的radio组独立;同时移除冗余的checked属性(v-model已能控制选中状态)。
4. 监听Props变化(可选)
如果需要props更新时同步data,添加watch监听,或者直接在模板中使用props。
5. 补充缺失方法
实现模板中调用的clearSelectedCause方法。
修改后的代码
组件JS代码
let vSelect = Vue.component("v-select", VueSelect.VueSelect); var scoringButton = Vue.component("scoring-button", { props: ["loadId", "causeData"], template: "#scoring-template", components: { "v-select": vSelect, }, data: function () { return { scoring: null, causeId: null, selectedCause: null, }; }, computed: { showCauseList() { return this.scoring === "1" || this.scoring === null; }, modalId() { // 生成唯一Modal ID return `scoringModal-${this.loadId}`; } }, methods: { clearSelectedCause() { this.selectedCause = null; } }, // 监听props变化,同步数据(如果需要) watch: { loadId(newVal) { // 若有依赖loadId的data需要同步,可在此处理 }, causeData(newVal) { // 若causeList需要同步,可在此处理,或者直接在模板中用this.causeData } } });
模板代码
<template v-cloak id="scoring-template"> <div class="scoring-block" :id="loadId"> <div class="scoring"> <button v-if="scoring === '1'" title="Scoring button" type="button" class="btn btn-success scoring-btn" data-bs-toggle="modal" :data-bs-target="`#${modalId}`" > <i class="bi bi-hand-thumbs-up-fill"></i> </button> <button v-else-if="scoring === '2'" title="Scoring button" type="button" class="btn btn-danger scoring-btn" data-bs-toggle="modal" :data-bs-target="`#${modalId}`" > <i class="bi bi-hand-thumbs-down-fill"></i> </button> <button v-else title="Scoring button" type="button" class="btn btn-info scoring-btn" data-bs-toggle="modal" :data-bs-target="`#${modalId}`" > <i class="bi bi-hand-thumbs-up-fill"></i> <i class="bi bi-hand-thumbs-down-fill"></i> </button> </div> <div class="modal fade scoring-modal" :id="modalId" tabindex="-1" role="dialog" aria-hidden="true" > <div class="modal-dialog modal-dialog-centered"> <div class="modal-content"> <div class="modal-header"> <h1 class="modal-title">Load Scoring</h1> <button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="modal" ></button> </div> <div class="modal-body"> <div class="scoring-content"> <input type="radio" class="btn-check" :name="`btnScore-${loadId}`" :id="`btnLike-${loadId}`" autocomplete="off" value="1" v-model="scoring" /> <label class="btn btn-outline-success" :for="`btnLike-${loadId}`" @click="clearSelectedCause" > <i class="bi bi-hand-thumbs-up-fill"></i> Like </label> <input type="radio" class="btn-check" :name="`btnScore-${loadId}`" :id="`btnDislike-${loadId}`" autocomplete="off" value="2" v-model="scoring" /> <label class="btn btn-outline-danger" :for="`btnDislike-${loadId}`"> <i class="bi bi-hand-thumbs-down-fill"></i> Dislike </label> </div> <div class="scoring-cause"> <v-select :disabled="showCauseList" label="name" :options="causeData" v-model="selectedCause" placeholder="Choose a cause option" ></v-select> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" > Close </button> <button type="button" class="btn btn-primary"> Save changes </button> </div> </div> </div> </div> </div> </template>
父组件使用代码(无需修改)
<div v-for="row in tableData" class="row-container" > .... <scoring-button :id="row.LOAD_ID" :key="row.LOAD_ID" :load-id="row.LOAD_ID" :cause-data="scoringCauseList" > </scoring-button> .... </div>
说明
- 移除了data中
scoredLoadId和causeList,直接使用propsloadId和causeData,避免数据不同步问题。 - 所有需要唯一标识的元素(Modal ID、radio的id和name)都通过
loadId拼接,确保每个组件实例独立。 - 补充了
clearSelectedCause方法,实现点击Like时清空选中的原因。
内容的提问来源于stack exchange,提问作者stillnurs
相关产品推荐
相关产品推荐

