Vue.js笔记组件修改编辑状态函数失效问题求助
问题:Vue3笔记组件编辑按钮点击后视图不更新
我正在开发一款简易笔记应用,当前处理NoteItem组件时遇到问题:组件的删除按钮功能正常,但点击编辑按钮调用startRedacting()后,redacting变量修改后视图没有变化,导致v-else区块无法渲染。
原组件代码
<script setup lang="ts"> import axios from "axios"; const props = defineProps(['title', 'content', 'note_id']); let redacting = undefined; let redTitle = props.title; let redContent = props.content; const deleteNote = async () => { await axios.delete(`http://localhost:3000/notes/${props.note_id}`) .then((res) => { if (res.status === 204) { location.reload() } else { console.log(`HTTP STATUS ${res.status}`) } }) } const startRedacting = () => { redacting = true } const redactNote = async () => { await axios.put(`http://localhost:3000/notes/${props.note_id}`, { Title: redTitle, Content: redContent }) .then((res) => { if (res.status === 200) { redacting = false location.reload() } else { console.log(`HTTP STATUS ${res.status}`) } }) } </script> <template> <div class="flex flex-row justify-between border-2 border-r-6 border-gray-200 p-3 rounded-md"> <div class="flex w-2.5 h-full bg-red-500 rounded-3xl resize-none flex-none" id="strip"> <!--Poloska--> </div> <div v-if="!redacting" class="flex flex-col ml-8 text-wrap justify-self-start justify-start"> <div id="title" class="text-xl justify-self-center text-left"> {{ title }} </div> <div id="content" class="pt-4 text-pretty h-max truncate justify-self-start text-left"> {{ content }} </div> </div> <div v-else> <div class="flex flex-col ml-8 text-wrap justify-self-start justify-start pr-2"> <div class="text-xl justify-self-center text-left"> <input type="text" v-model="redTitle" class="border-2 border-gray-200 rounded-md p-2 w-full"> </div> <div id="content" class="pt-4 text-pretty h-max truncate justify-self-start text-left"> <textarea v-model="redContent" class=" border-2 border-gray-200 rounded-md p-2 w-full"></textarea> </div> <button class="size-8 hover:shadow-neutral-300 hover:bg-green-700 rounded-lg justify-center w-full bg-green-600" @click="redactNote"> <div class="text-white">Done</div> </button> </div> </div> <div class="flex flex-col"> <button class="size-8 hover:shadow-neutral-300 hover:bg-neutral-200 rounded-lg" @click="startRedacting"> <img src="../assets/pencil.svg" alt="" class="justify-self-center"> </button> <button class="size-8 hover:shadow-neutral-300 hover:bg-red-400 rounded-lg mt-2" @click="deleteNote"> <img src="../assets/trash-svgrepo-com.svg" alt="" class="pt-1"> </button> </div> </div> </template> <style scoped> </style>
原因分析
在Vue3的<script setup>中,直接声明的普通变量(如let redacting = undefined;)不具备响应式特性,修改变量值不会触发视图更新。Vue3要求使用ref或reactive来创建可触发视图更新的响应式状态。
修复方案
- 从
vue库导入ref函数,用于创建响应式变量 - 将
redacting、redTitle、redContent改为ref包裹的响应式变量 - 在脚本中修改或访问
ref变量时,必须通过.value属性操作;模板中使用时Vue会自动解包,无需添加.value
修改后的完整代码
<script setup lang="ts"> import axios from "axios"; import { ref } from "vue"; // 导入ref函数 const props = defineProps(['title', 'content', 'note_id']); // 转为响应式ref变量,初始值设为false更符合逻辑 const redacting = ref(false); const redTitle = ref(props.title); const redContent = ref(props.content); const deleteNote = async () => { await axios.delete(`http://localhost:3000/notes/${props.note_id}`) .then((res) => { if (res.status === 204) { location.reload() } else { console.log(`HTTP STATUS ${res.status}`) } }) .catch(err => console.error('删除笔记失败:', err)) // 新增错误捕获 } const startRedacting = () => { redacting.value = true; // 修改ref变量需使用.value } const redactNote = async () => { await axios.put(`http://localhost:3000/notes/${props.note_id}`, { Title: redTitle.value, // 访问ref变量值需使用.value Content: redContent.value }) .then((res) => { if (res.status === 200) { redacting.value = false; location.reload() } else { console.log(`HTTP STATUS ${res.status}`) } }) .catch(err => console.error('编辑笔记失败:', err)) // 新增错误捕获 } </script> <template> <div class="flex flex-row justify-between border-2 border-r-6 border-gray-200 p-3 rounded-md"> <div class="flex w-2.5 h-full bg-red-500 rounded-3xl resize-none flex-none" id="strip"> <!--Poloska--> </div> <div v-if="!redacting" class="flex flex-col ml-8 text-wrap justify-self-start justify-start"> <div id="title" class="text-xl justify-self-center text-left"> {{ title }} </div> <div id="content" class="pt-4 text-pretty h-max truncate justify-self-start text-left"> {{ content }} </div> </div> <div v-else> <div class="flex flex-col ml-8 text-wrap justify-self-start justify-start pr-2"> <div class="text-xl justify-self-center text-left"> <input type="text" v-model="redTitle" class="border-2 border-gray-200 rounded-md p-2 w-full"> </div> <div id="content" class="pt-4 text-pretty h-max truncate justify-self-start text-left"> <textarea v-model="redContent" class=" border-2 border-gray-200 rounded-md p-2 w-full"></textarea> </div> <button class="size-8 hover:shadow-neutral-300 hover:bg-green-700 rounded-lg justify-center w-full bg-green-600" @click="redactNote"> <div class="text-white">Done</div> </button> </div> </div> <div class="flex flex-col"> <button class="size-8 hover:shadow-neutral-300 hover:bg-neutral-200 rounded-lg" @click="startRedacting"> <img src="../assets/pencil.svg" alt="" class="justify-self-center"> </button> <button class="size-8 hover:shadow-neutral-300 hover:bg-red-400 rounded-lg mt-2" @click="deleteNote"> <img src="../assets/trash-svgrepo-com.svg" alt="" class="pt-1"> </button> </div> </div> </template> <style scoped> </style>
额外优化建议
- 避免使用
location.reload()刷新页面,可通过父组件状态更新或状态管理工具(如Pinia)同步数据,提升用户体验 - 为axios请求添加
catch块捕获网络异常,增强代码健壮性
内容的提问来源于stack exchange,提问作者Sanyokk
相关产品推荐
相关产品推荐

