Vue中Ref值变更时HTML无法持续更新问题排查
解决Vue中WebSocket状态无法实时更新的问题
问题描述
用类封装WebSocket连接,通过Ref<number>存储连接的readyState,并在模板中展示该状态。WebSocket的open和close事件会触发Ref值变更,控制台能看到状态确实变化,但HTML仅在首次加载时更新,后续状态变更无法同步到页面。
问题根源
每次调用doConnect()方法时,都会创建新的WebSocket实例,同时重新执行this.wsState = ref(ws.readyState)——这相当于生成了一个全新的Ref对象。而模板绑定的是初始化阶段从ws实例解构出来的旧Ref对象,后续更新的是新Ref的value,模板没有关联到新的Ref,因此页面不会同步更新。
之前测试this.wsState.value++能生效,是因为那时候没有重新创建Ref,更新的还是模板绑定的旧Ref的value,所以能触发响应式更新。
修复方案
只初始化一次Ref对象,后续仅更新Ref的value,不重新赋值Ref:
<script setup> import { ref } from 'vue'; class Ws { ws; // WebSocket实例 wsState; // 唯一的Ref对象 constructor() { // 先初始化Ref,避免后续重复创建 this.wsState = ref(0); this.doConnect(); } doConnect() { const ws = new WebSocket('wss://ws.ifelse.io/'); this.ws = ws; // 直接更新已有Ref的value,不创建新Ref this.wsState.value = ws.readyState; ws.onopen = () => this.updateWsState(); ws.onclose = () => this.updateWsState(); ws.onerror = (e) => console.error(`ws err:`, e); } updateWsState() { this.wsState.value = this.ws.readyState; console.log(`ws state ${this.wsState.value}`); } toggleConnect() { if ( this.ws.readyState === this.ws.CLOSED || this.ws.readyState === this.ws.CLOSING ) { this.doConnect(); } else { this.ws.close(); } } } const ws = new Ws(); const { wsState } = ws; </script> <template> <ul> <li>0 CONNECTING</li> <li>1 OPEN</li> <li>2 CLOSING</li> <li>3 CLOSED</li> </ul> <p>ws state: {{ wsState }}</p> <button @click="ws.toggleConnect">toggle connect</button> </template>
这样模板始终绑定同一个Ref对象,后续所有状态变更都会通过更新该Ref的value触发页面响应式更新。
内容的提问来源于stack exchange,提问作者Jackoo
相关产品推荐
相关产品推荐

