返回信息流凭我后端的经验vue要重新渲染可以给组件用:key=‘a’,每次a++就行了,不知道有没有用
这是一条镜像帖。来源:北邮人论坛 / iwhisper / #6763952同步于 2024/1/21
该镜像源已超过 30 天没有更新,可能在源站已被删除。
IWhisper机器人发帖
【求助】【vue3】来个佬救救孩子
IWhisper#705
2024/1/21镜像同步3 回复
订阅后,新回复会通过你的通知中心匿名送达。
3 条回复
<pre class="markdown"># issue
**ts对象的属性更新后没能触发组件重新渲染以及watch/watchEffect**
前端通过websocket接收到后端发送的消息后,自动分配给对应的函数处理,控制台打印出来game对象已经更新了,但是没有重新渲染,也没触发watch。主要代码为
```typescript
public websocket: WebSocketService | undefined; // 自动管理websocket消息
this.websocket.on('match',async (data:any) => await this.match_response_handler(data)); // 绑定处理函数
```
其中websocket为一个自动管理websocket协议通信的对象, match_response_handler是对应的响应函数,会修改game对象的属性。
gpt4提到:如果 `match_response_handler` 方法是在 Vue 的作用域之外被调用的(例如,通过一个非 Vue 的回调函数),那么 Vue 可能无法追踪到这些变化。我尝试使用它建议的箭头函数或match_response_handler.bind(this)均未解决问题。
以及,我在Game类的其它方法类通过setTimeOut修改属性(而不是通过webSocketService自动调用的)会正确触发watch、重新渲染。
部分相关源码如下:
main.vue
```vue
<template>
<div v-if="!isLoaded">
// some code
</div>
<div v-if="isLoaded">
// some code
<el-col v-for="(card, index) in game.getSelfCards()" :key="card.name">
{{ card.name }}
</el-col>
</div>
</template>
<script setup lang="ts">
// some import
let game = ref(new Game())
let { cards } = toRefs(game.value)
let isLoaded = ref(false)
watchEffect(()=>{
isLoaded.value = game.value.isLoaded
})
watch(cards, (newV, oldV) => {
console.log("update cards", newV)
}, { immediate: true, deep: true })
watch(()=>game.value.isLoaded, ()=>{
console.log("update game.value.isLoaded", game.value.isLoaded)
}, { immediate: true, deep: true })
onMounted(() => {
// 渲染完成后再初始化,不然不会更新
game.value.finiteStateAutomata() // 迭代
})
</script>
```
Game.ts
```typescript
//some import
class Game {
public isLoaded: boolean = false;
public cards: Card[];
public websocket: WebSocketService | undefined; // 自动管理websocket消息
public async match_response_handler(data: any) {
this.selfIndex = data.idx;
for (var name in data.decks)this.cards.push(new Card(name));
for (var name in data.cards)this.getSelfCards().push(new Card(name));
this.isLoaded = true;
await nextTick() //
console.log("Receive response match", data,this);
}
// note this
private initWebsocketService() { // will be called
if(!this.websocket)return
this.websocket.on('match',async (data:any) => await this.match_response_handler(data));
}
}
export { Game };
```
webSocketService.ts
```typescript
// some import
class WebSocketService {
private socket: WebSocket;
private handlers: { [key: string] : (ret: any) => void };
constructor(url: string) {
this.socket = new WebSocket(url);
this.handlers = {};
this.socket.onmessage = async (event) => {
const response: ApiResponse =await JSON.parse(event.data);
console.log(`收到来自服务器的数据:`, response);
await this.handleMessage(response);
};
}
private async handleMessage(response: ApiResponse) {
const handler = this.handlers[response.api];
if (handler) {
await handler(response.ret);
}
}
// note this
public on(api: string, handler: (ret: any) => void) {
this.handlers[api] = handler;
}
}
export {WebSocketService};
```</pre>