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

Vue2中左右面板版本变量更新不同步问题排查与解决

问题排查与解决方案

问题场景

页面分为左右面板:左面板点击「Firmware」选项后,右面板展示对应页面;左面板按钮触发向导流程,关闭向导后左面板的版本值已更新,但右面板基于同一room.uxOneVersion变量的条件渲染未即时生效,必须切换页面再返回才能看到变化。限制:无法使用Composition API


相关代码

右面板-Vue文件

<q-item-label header v-if="!room.uxOneVersion">
  {{ $t('pages+.projects.firmwares.noVersion') }}
  <span class="lt-md">
    <br />
  </span>
  {{ $t('pages.projects.firmwares.connectThermostat') }}
</q-item-label>
<q-item-label
  class="q-mb-md"
  header
  v-if="room.uxOneVersion && room.uxOneVersion >= versionCheck"
>
  {{ $t('pages.projects.firmwares.noUpgradeAvailable') }}
  <span class="lt-md">
    <br />
  </span>
  {{ $t('pages.projects.firmwares.latestCheck', { date: date, hour: hour }) }}
</q-item-label>
<q-item-label
  class="q-mb-md"
  header
  v-if="room.uxOneVersion && room.uxOneVersion < versionCheck && versionCheck"
>
  {{ $t('pages.projects.firmwares.upgradeAvailable') }}
</q-item-label>

右面板Typescript文件

async searchUpdate() {
    localStorage.setItem('date', new Date().toLocaleDateString());
    localStorage.setItem(
      'hour',
      new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
    );
    try {
      this.onSearchFirmware = true;
      if (await Helpers.isHostDeviceOnline()) {
        const firmwareUpdaterResponse = await this.isFirmwareUpToDate(this.firmwareUpdater);
        if (
          firmwareUpdaterResponse &&
          !firmwareUpdaterResponse?.isUpToDate &&
          this.room.uxOneVersion < firmwareUpdaterResponse?.version &&
          this.versionCheck != firmwareUpdaterResponse?.version
        ) {
          localStorage.setItem('version', firmwareUpdaterResponse.version);
          this.versionCheck = localStorage.getItem('version');
          this.notifyAvailabilityOfNewVersionFirmware(firmwareUpdaterResponse);
          this.date = localStorage.getItem('date');
          this.hour = localStorage.getItem('hour');
        } else {
          this.notifyNoVersionFirmwareAvailable();
          this.date = localStorage.getItem('date');
          this.hour = localStorage.getItem('hour');
        }
      } else {
        Notifier.showError(this.$t('general.internetNotConnected').toString());
      }
    } catch (error) {
      const errorMessage = this.$t('pages.projects.firmwares.isUpToDateError', {
        error_message: (error as FirmwareUpdaterError).message,
      }).toString();
      Notifier.showError(errorMessage);
    } finally {
      this.onSearchFirmware = false;
    }
  }

左面板-Vue文件

<q-item-section side>
  <div>
    <q-chip style="background: transparent"></q-chip>
    <q-chip data-cy="firmware-Version" v-if="room.uxOneVersion != ''"
      >{{ $t('general.currentVersionFirmware') }} {{ room.uxOneVersion }}</q-chip
    >
    <q-icon size="xs" color="grey" name="chevron_right" />
  </div>
</q-item-section>

左面板Typescript文件

this.handleConnectionDialogVisibility(false);
await this.getVersionUxOne();
await this.openIdentifyDialog();
}
private async getVersionUxOne() {
  this.firmwareVersionToDisplay = '';
  const controllerUpdater = ControllerFirmwareUpdaterFactory.create(
    this.roomControllerModuleStore.currentController.controllerType,
    this.deviceModuleStore.currentNetworkAddress,
    this.deviceModuleStore.currentPassword
  );
  const currentControllerVersion = await controllerUpdater.getVersion(); //0.2.9
  const room: RoomEntity = this.roomModuleStore.currentRoom;
  room.uxOneVersion = `${currentControllerVersion}`; //0.2.9
  this.firmwareVersionToDisplay = `v ${currentControllerVersion}`; //v 0.2.9
  await this.roomModuleStore.updateRoom(room);
  await this.roomModuleStore.setCurrentRoom(this.roomModuleStore.currentRoom.Id);
}

原因分析

  1. Vue2响应式机制限制:如果room对象原本没有uxOneVersion属性,直接赋值新增属性时,Vue2无法自动为该属性添加响应式监听,修改后不会触发视图更新。
  2. 右面板未实时同步store数据:右面板若仅在初始化时获取room对象,未通过computed或watch监听store中currentRoom的变化,会导致视图一直使用旧的room数据。
  3. store更新不规范:如果roomModuleStore.updateRoom未通过Vuex的mutation修改state,而是直接修改对象,会导致state变化无法被组件感知。

解决方案

1. 确保uxOneVersion是响应式属性

在左面板的getVersionUxOne方法中,使用Vue.set为room添加/修改uxOneVersion,强制开启响应式:

// 替换原直接赋值代码
import Vue from 'vue';
Vue.set(room, 'uxOneVersion', `${currentControllerVersion}`);

2. 右面板通过computed实时获取最新room数据

右面板不要缓存room变量,而是通过computed从store中实时拉取:

// 右面板TS文件添加computed属性
computed: {
  currentRoom() {
    return this.roomModuleStore.currentRoom;
  }
}

然后修改右面板Vue模板,将所有room替换为currentRoom:

<q-item-label header v-if="!currentRoom.uxOneVersion">
  {{ $t('pages+.projects.firmwares.noVersion') }}
  <span class="lt-md">
    <br />
  </span>
  {{ $t('pages.projects.firmwares.connectThermostat') }}
</q-item-label>
<!-- 其余v-if条件中的room均替换为currentRoom -->

3. 规范store更新流程(若使用Vuex)

确保updateRoom通过mutation更新state,而非直接修改:

// store中的action
async updateRoom({ commit }, room) {
  // 执行后端更新等逻辑后
  commit('SET_CURRENT_ROOM', room);
}

// store中的mutation
mutations: {
  SET_CURRENT_ROOM(state, room) {
    // 直接赋值新对象,确保响应式
    state.currentRoom = room;
  }
}

4. 兜底:手动触发右面板刷新

如果以上方案无法快速落地,可通过事件总线通知右面板强制刷新:

  • 左面板更新完room后触发事件:
await this.roomModuleStore.setCurrentRoom(this.roomModuleStore.currentRoom.Id);
// 触发事件总线
this.$bus.$emit('room-updated');
  • 右面板监听事件并刷新:
// 右面板TS文件
mounted() {
  this.$bus.$on('room-updated', () => {
    this.$forceUpdate();
  });
},
beforeDestroy() {
  // 销毁前移除监听,避免内存泄漏
  this.$bus.$off('room-updated');
}

注意:需提前在Vue实例中注册事件总线:Vue.prototype.$bus = new Vue();


内容的提问来源于stack exchange,提问作者Priyanka Rajendran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 15:01:12