如何通过Websocket从FastAPI后端向Vue前端返回JSON数据?
修改方案:通过Websocket直接传递JSON数据
核心思路
- 后端取消本地写入JSON文件的逻辑,将自动补全文本和外部接口返回的JSON数据打包成一个对象,通过Websocket发送给前端
- 前端接收后拆分数据:自动补全文本直接展示,JSON数据通过组件间通信传递给展示组件,彻底摆脱本地文件依赖
1. FastAPI后端代码修改
删除文件写入部分,打包两个数据通过JSON格式发送:
@app.websocket("/") async def predict_question(websocket: WebSocket): await websocket.accept() while True: input_text = await websocket.receive_text() # 生成自动补全文本(原有逻辑保留) autocomplete_text = text_gen.generate_text(input_text) autocomplete_text = re.sub(r"[\([{})]]", "", autocomplete_text) autocomplete_text = autocomplete_text.split() autocomplete_str = ' '.join(autocomplete_text[0:2]) # 请求外部接口获取JSON(原有逻辑保留) resp = req.get('www.description_url_search_='+input_text+'') datajson = resp.json() # 打包数据并发送,替换原单独发送文本的逻辑 await websocket.send_json({ "autocomplete": autocomplete_str, "json_data": datajson })
2. 前端Autocomplete.vue组件修改
调整消息接收逻辑,解析后端数据并传递给父组件:
<template> <div class="pad-container"> <div tabindex="1" @focus="setCaret" class="autocomplete-container"> <span @input="sendText" @keypress="preventInput" ref="editbar" class="editable" contenteditable="true"></span> <span class="placeholder" contenteditable="false">{{autoComplete}}</span> </div> </div> </template> <script> export default { name: 'Autocomplete', data: function() { return { autoComplete: "", maxChars: 75, connection: null } }, mounted() { const url = "ws://localhost:8000/" this.connection = new WebSocket(url); this.connection.onopen = () => console.log("connection established"); // 解析WebSocket收到的JSON字符串 this.connection.onmessage = (event) => { const data = JSON.parse(event.data); this.autoComplete = data.autocomplete; // 向父组件发送JSON数据 this.$emit('update-json', data.json_data); }; }, methods: { setCaret() { const range= document.createRange() const sel = window.getSelection(); const parentNode = this.$refs.editbar; if (parentNode.firstChild == undefined) { const emptyNode = document.createTextNode(""); parentNode.appendChild(emptyNode); } range.setStartAfter(this.$refs.editbar.firstChild); range.collapse(true); sel.removeAllRanges(); sel.addRange(range); }, preventInput(event) { let prevent = false; if (event.key == event.key.toUpperCase()) { prevent = true; } if (event.code == "Space") { prevent = false; } const nChars = this.$refs.editbar.textContent.length; if (nChars >= this.maxChars) { prevent = true; } if (prevent == true) { event.preventDefault(); } }, sendText() { const inputText = this.$refs.editbar.textContent; this.connection.send(inputText); } } } </script>
3. 前端App.vue修改
添加数据存储,接收子组件数据并传递给展示组件:
<template> <div class="main-container"> <h1 style="color:#0072c6;">Title</h1> <p style="text-align:center; color:#0072c6;"> Version 0.1 <br> </p> <!-- 监听子组件事件,接收JSON数据 --> <Autocomplete @update-json="handleUpdateJson" /> <br> </div> <div style="color:#0072c6;"> <!-- 通过props传递JSON数据给展示组件 --> <JsonArq :my-json="jsonData" /> </div> <div style="text-align:center;"> <img src="./components/logo-1536.png" width=250 height=200 alt="Logo" > </div> </template> <script> import Autocomplete from './components/Autocomplete.vue' import JsonArq from './components/EstepeJSON.vue' export default { name: 'App', components: { Autocomplete, JsonArq }, data() { return { jsonData: [] // 存储后端传来的JSON数据 } }, methods: { handleUpdateJson(data) { this.jsonData = data; } } } </script> <style> .main-container { display: flex; justify-content: center; align-items: center; flex-direction: column; font-family: 'Fredoka', sans-serif; } h1 { font-size: 3rem; } @import url('https://fonts.googleapis.com/css2?family=Fredoka&display=swap'); </style>
4. 前端EstepeJSON.vue组件修改
移除本地文件导入,通过props接收数据:
<template> <div width="80%" v-for="regList in myJson" :key="regList.Cod" class="container"> <table> <thead> <tr> <th>Documento</th> </tr> </thead> <tbody> <!-- 保持原展示逻辑,对应示例JSON的Description字段 --> <tr> <td style="visibility: visible">{{ regList.Description }}</td> </tr> </tbody> </table> </div> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css" /> </template> <script> // 删除本地JSON导入 export default { name: "EstepeJson", props: { // 定义props接收父组件传递的数据 myJson: { type: Array, default: () => [] } }, data() { return {}; }, }; </script>
注意事项
- 确保外部接口返回的JSON格式稳定,前端展示逻辑与数据结构匹配
- WebSocket通信中,后端
send_json自动序列化,前端需用JSON.parse解析字符串 - 修改了
v-for的key为regList.Cod,避免使用数组元素作为key的控制台警告
内容的提问来源于stack exchange,提问作者CH97
相关产品推荐
相关产品推荐

