You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quasar中通过Vue Props传数组后标签页切换失效问题

问题分析

直接修改Props传入数组中对象的属性(test.status)违反了Vue的单向数据流规则:Props是父组件向子组件传递数据的通道,子组件仅能读取,不能直接修改。这种非法修改无法触发正确的响应式更新,导致Quasar标签页的v-model绑定失效;而使用本地数组时,修改的是组件内部的响应式数据,所以标签切换功能正常。

解决方案

提供两种符合Vue规范的实现方案,可根据业务需求选择:

方案1:将Props数据复制到本地响应式数据

把传入的tests深拷贝到组件内部的data中,后续渲染和修改都基于本地数据,避免直接操作Props。

<template>
  <!-- 循环本地数据,添加唯一key -->
  <div v-for="test in localTests" :key="test.id">
    <q-tabs
      v-model="test.status"
      align="justify"
    >
      <q-tab
        v-for="tab in tabs"
        :key="tab.value" <!-- 用tab的唯一值当key,比index更稳定 -->
        :name="tab.value"
      >
        {{ tab.name }}
      </q-tab>
    </q-tabs>
  </div>
</template>

<script>
export default {
  props: ['tests'],
  data() {
    return {
      localTests: [],
      tabs: [
        { name: 'Required', value: 'required' },
        { name: 'Not Required', value: 'not-required' }
      ]
    }
  },
  created() {
    // 深拷贝Props数据到本地,避免直接修改Props
    this.localTests = JSON.parse(JSON.stringify(this.tests))
  },
  // 监听Props变化,同步更新本地数据(如果父组件会修改tests)
  watch: {
    tests: {
      deep: true,
      handler(newVal) {
        this.localTests = JSON.parse(JSON.stringify(newVal))
      }
    }
  }
}
</script>

方案2:通过事件通知父组件更新源数据

如果需要将标签切换的状态同步回父组件,不能仅修改本地数据,需通过自定义事件让父组件更新源Props:

子组件代码

<template>
  <div v-for="test in tests" :key="test.id">
    <!-- 用model-value和update:model-value替代v-model,手动处理状态变更 -->
    <q-tabs
      :model-value="test.status"
      align="justify"
      @update:model-value="handleTabChange(test, $event)"
    >
      <q-tab
        v-for="tab in tabs"
        :key="tab.value"
        :name="tab.value"
      >
        {{ tab.name }}
      </q-tab>
    </q-tabs>
  </div>
</template>

<script>
export default {
  props: ['tests'],
  data() {
    return {
      tabs: [
        { name: 'Required', value: 'required' },
        { name: 'Not Required', value: 'not-required' }
      ]
    }
  },
  methods: {
    handleTabChange(test, newStatus) {
      // 触发自定义事件,把变更通知给父组件
      this.$emit('update-test-status', test.id, newStatus)
    }
  }
}
</script>

父组件代码

<template>
  <child-component 
    :tests="parentTests" 
    @update-test-status="updateTestStatus" 
  />
</template>

<script>
export default {
  data() {
    return {
      parentTests: [
        { id: "test 1", name: 'TEST 1', status: 'required' },
        { id: "test 2", name: 'TEST 2', status: 'not-required' }
      ]
    }
  },
  methods: {
    updateTestStatus(testId, newStatus) {
      // 找到对应测试项,更新其状态
      const targetTest = this.parentTests.find(t => t.id === testId)
      if (targetTest) {
        targetTest.status = newStatus
      }
    }
  }
}
</script>
注意事项
  • 循环渲染时必须添加唯一的:key,推荐使用数据的唯一标识(如test.id)而非索引,避免组件复用导致的状态异常。
  • 永远不要直接修改Props,否则会导致数据流向混乱,增加后续维护难度。

内容的提问来源于stack exchange,提问作者power-cut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 05:05:25