Vue script setup+axios实现提交数据后无页面重载获取最新数据
实现方案
你当前的组件层级为Greeting.vue(父组件,提交数据)嵌套GreetingList.vue(子组件,渲染列表),改动最小的实现方式是利用<script setup>的defineExpose能力,让父组件可以调用子组件的数据拉取方法,步骤如下:
- 修改
GreetingList.vue,将内部的getMessages方法暴露给父组件
<!-- GreetingList.vue --> <div class="p-2" v-for="(message, index) in messages" :key="message.id"> <div> <h3>{{ message.name }}<span>{{message.date}}</span></h3> <p class="text-slate-300 text-lg">{{ message.greeting }}</p> </div> <hr/> </div> <script setup> import {ref, onMounted } from 'vue' import axios from 'axios' const messages = ref([]); function getMessages() { axios.get('http://127.0.0.1:8000/api/messages') .then((result) => { messages.value = result.data }).catch((err) => { console.log(err.response.data) }) } onMounted(() => { getMessages() }); // 暴露方法供父组件调用 defineExpose({ getMessages }) </script>
注:原代码v-for绑定key用index会存在DOM渲染复用问题,建议替换为接口返回的每条数据唯一id字段
- 修改
Greeting.vue,给子组件绑定ref,在post提交成功后调用子组件的刷新方法
<!-- Greeting.vue --> <template> <form @submit.prevent="store()"> <div class=""> <input type="text" placeholder="" v-model="messages.name"> <textarea name="" id="" cols="28" rows="10" placeholder="" v-model="messages.greeting"></textarea> </div> <button>Submit</button> </form> <div> <GreetingList ref="listRef"/> </div> </template> <script setup> import { reactive, ref } from 'vue' import axios from 'axios' import GreetingList from './GreetingList.vue' // 子组件实例引用 const listRef = ref(null) const messages = reactive({ name: '', greeting: '', }); function store() { axios.post('http://127.0.0.1:8000/api/messages', messages) .then((result) => { messages.name = '' messages.greeting = '' // 提交成功后触发列表刷新 listRef.value?.getMessages() }) .catch((err) => { console.log(err.response?.data) }) } </script>
其他可选方案
- 状态提升:把列表数据、拉取列表的逻辑统一放到父组件维护,通过prop把列表数据传给子组件渲染,提交成功后直接在父组件调用拉取方法即可,不需要ref调用子组件方法,适合逻辑需要集中管理的场景。
- 全局状态管理:如果两个组件层级差比较大、没有直接父子关系,可以用Pinia存储列表数据,提交成功后直接触发全局状态里的拉取方法,所有用到列表的组件都会自动更新。
- 事件总线:小型项目可以用mitt实现跨组件事件通知,提交成功后发送刷新事件,列表组件监听事件触发数据拉取。
内容的提问来源于stack exchange,提问作者Fransiskus Willy
相关产品推荐
相关产品推荐

