英文:
How to re-render parent component on certain event in child component in vue 3 using composition API
问题
我可以实际使用“选项 API”来完成,但现在我正在使用“组合 API”与“可组合项”,而且我卡住了。整天在网上搜索,但没有找到答案。
所以,我有两个组件(members.vue
和memberStore.vue
)。我的目标是当我在memberStore.vue
中发布一个新成员(我在members.vue
中加载它时),该父组件中的成员列表应自动重新渲染。
以下是这些页面的内容:
members.vue
<template>
<div>
<memberStore></memberStore>
<table>
<thead>
<tr>
<th><span>Name</span></th>
<th><span>Address</span></th>
<th></th>
</tr>
</thead>
<tbody>
<template v-for="item in members" :key="item.id">
<tr>
<td>{{ item.name }}</td>
<td>{{ item.address }}</td>
</tr>
</template>
</tbody>
</table>
</div>
</template>
<script>
import useMembers from "../../composables/members";
import { onMounted } from "vue";
import memberStore from "../../components/members/memberStore.vue";
export default {
components: { memberStore },
setup() {
const { members, getMembers } = useMembers();
onMounted(getMembers);
return {
members,
};
},
};
</script>
memberStore.vue
<template>
<div>
<form @submit.prevent="saveMember">
<div>
<div><label for="name">Name</label></div>
<div><input type="text" name="name" id="name" v-model="form.name"></div>
<div><label for="address">Address</label></div>
<div><input type="text" name="address" id="address" v-model="form.address"></div>
</div>
<div>
<button type="submit">Save</button>
</div>
</form>
</div>
</template>
<script>
import { reactive } from "vue";
import useMembers from "../../composables/members";
export default {
setup() {
const form = reactive({
name: "",
address: "",
});
const { errors, storeMember } = useMembers();
const saveMember = async () => {
await storeMember({ ...form });
};
return {
form,
errors,
saveMember,
};
},
};
</script>
src/composables/members.js
import { ref } from "vue";
import axios from "axios";
import { useRouter } from "vue-router";
import axiosClient from "../axios";
export default function useMembers() {
const members = ref([]);
const member = ref([]);
const router = useRouter();
const errors = ref("");
const getMembers = async () => {
let response = await axiosClient.get("/members");
members.value = response.data.data;
};
const getMember = async (id) => {
let response = await axiosClient.get("/members/" + id);
member.value = response.data.data;
};
const storeMember = async (data) => {
errors.value = "";
try {
await axiosClient.post("/members", data);
// 添加以下行以手动重新获取成员列表
await getMembers();
} catch (e) {
if (e.response.status === 422) {
errors.value = e.error.response.data;
}
}
};
return {
members,
getMembers,
router,
member,
getMember,
storeMember,
};
}
所有这些都按照我期望的方式工作。唯一的问题是我找不到自动重新渲染父组件的方法。
英文:
I can do it actually using option API
, but now I'm using composition API
with composables
and I'm stuck. Have searched online all day but got no answer.
So, I have two components
(members.vue
and memberStore.vue
). My goal is when I post a new member in memberStore.vue
(which I load in members.vue
), the member list in that parent component should be automatically re-rendered.
here are those pages:
members.vue
<template>
<div>
<memberStore></memberStore>
<table >
<thead>
<tr>
<th><span>Name</span></th>
<th><span>Address</span></th>
<th ></th>
</tr>
</thead>
<tbody >
<template v-for="item in members" :key="item.id">
<tr>
<td> {{ item.name }} </td>
<td> {{ item.address }} </td>
</tr>
</template>
</tbody>
</table>
</div>
</template>
<script>
import useMembers from "../../composables/members";
import { onMounted } from "vue";
import memberStore from "../../components/members/memberStore.vue";
export default {
components: { memberStore },
setup() {
const { members, getMembers } = useMembers();
onMounted(getMembers);
return {
members,
};
},
};
</script>
memberStore.vue
<template>
<div>
<form @submit.prevent="saveMember">
<div>
<div><label for="name" >Name</label></div>
<div > <input type="text" name="name" id="name" v-model="form.name" > </div>
<div> <label for="address">Address</label > </div>
<div><input type="text" name="address" id="address" v-model="form.address" ></div>
</div>
<div>
<button type="submit" > Save</button>
</div>
</form>
</div>
</template>
<script>
import { reactive } from "vue";
import useMembers from "../../composables/members";
export default {
setup() {
const form = reactive({
name: "",
address: "",
});
const { errors, storeMember } = useMembers();
const saveMember = async () => {
await storeMember({ ...form });
};
return {
form,
errors,
saveMember,
};
},
};
</script>
src/composables/members.js
import { ref } from "vue";
import axios from "axios";
import { useRouter } from "vue-router";
import axiosClient from "../axios";
export default function useMembers() {
const members = ref([]);
const member = ref([]);
const router = useRouter();
const errors = ref("");
const getMembers = async () => {
let response = await axiosClient.get("/members");
members.value = response.data.data;
};
const getMember = async (id) => {
let response = await axiosClient.get("/members/" + id);
member.value = response.data.data;
};
const storeMember = async (data) => {
errors.value = "";
try {
await axiosClient.post("/members", data);
} catch (e) {
if (e.response.status === 422) {
errors.value = e.error.response.data;
}
}
};
return {
members,
getMembers,
router,
member,
getMember,
storeMember,
};
}
All of these are working as I expected. The only problem is I can't find a way to auto re-render the parent component
答案1
得分: 1
在memberStore.vue
中,我添加了以下内容:
script
emits: ["customChange"],
setup(props, context) {
...
const handleChange = () => {
context.emit("customChange");
};
return {
....
handleChange,
};
}
trigger
<form @submit.prevent="saveMember" @submit="handleChange">
members.vue
<memberStore @customChange="getmembers"></memberStore>
英文:
I solved it using emit event
In memberStore.vue
I added the following:
script
emits: ["customChange"],
setup(props, context) {
...
const handleChange = () => {
context.emit("customChange");
};
return {
....
handleChange,
};
}
trigger
<form @submit.prevent="saveMember" @submit="handleChange">
members.vue
<memberStore @customChange="getmembers"></memberStore>
答案2
得分: 0
在两个组件内部调用useMembers()
会创建两个不同的members
数组(以及useMembers
内部创建的所有其他变量的多个实例)。
换句话说,members.vue
中的members
与membersStore.vue
中的members
是独立且不同的。更新其中一个不会影响另一个。
您可以将members
的定义移到useMembers
函数之外,这样无论在哪里调用useMembers()
,它都会引用相同的数组引用。
const members = ref([]); // 移动到useMembers函数之外
export default function useMembers() {
const member = ref([]);
const router = useRouter();
const errors = ref("");
...
return {
members,
...
}
}
英文:
calling useMembers()
inside two components creates two different members
arrays (as well as multiple of all other variables created within useMembers
).
In other words, the members
in members.vue
is unique and different from the members
in membersStore.vue
. Updating one does not affect the other.
You can move your members
definition above your useMembers
function, and then it will be the same array reference wherever useMembers()
is called
const members = ref([]); // moved outside of useMembers()
export default function useMembers() {
const member = ref([]);
const router = useRouter();
const errors = ref("");
...
return {
members,
...
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论