vue-router - Vue3 - 在组件内提供/注入对象后丢失数据
问题描述
我在我的项目中提供/注入有小问题。
在 App.vue 中,我从数据库中提取数据并将其推送到对象中。使用控制台日志,我检查了所有数据,所有数据都在那里。
<template>
<router-view />
</template>
<script>
export default {
provide() {
return {
user: this.user,
};
},
data() {
return {
user: '',
};
},
methods: {
///pulling data from DB
func() {
fetch("url")
.then((response) => {
if (response.ok) {
return response.json();
}
})
.then((data) => {
const user = [];
for (const id in data) {
user.push({
id: data[id].user_id,
firstName: data[id].user_firstname,
lastName: data[id].user_lastname,
email: data[id].user_email,
phone: data[id].user_phone,
address1: data[id].user_address_1,
address2: data[id].user_address_2,
address3: data[id].user_address_3,
address4: data[id].user_address_4,
group: data[id].user_group,
});
}
this.user = user;
})
.catch((error) => {
console.log(error);
});
},
},
created() {
this.func();
},
};
</script>
对象用户 App.vue 的控制台日志
Object { id: "3", firstName: "test", lastName: "test", … }
接下来我将它注入到组件中。组件内的对象存在,但为空 - 所有数据不复存在。
<script>
export default {
inject: ["user"],
};
</script>
组件中对象用户的控制台日志
<empty string>
虽然在 App.vue 中数据仍然存在,但在任何组件对象中似乎都是空的,但它确实存在。知道为什么吗?感谢帮助。
解决方案
简而言之,这是因为您正在重新分配用户而不是更改用户。
假设您有一个 Child 组件,它使用您的inject
数据并将用户呈现在列表中:
<template>
<div> Child </div>
<ul>
<li v-for="user in users" :key="user.id"> {{user.name}} </li>
</ul>
</template>
<script>
import {inject} from "vue";
export default {
name: "Child",
setup() {
const users = inject("users");
return {users};
}
}
</script>
要提供users
from parent 组件,您需要确保它users
本身是一个响应式对象,并且您不断地从父级更改它而不是重新分配它。
我将使用组合 API 来说明我的意思。与 options api 相比,composition api 中的所有内容都只是普通的 javascript,因此幕后的魔力要少得多。最后我会告诉你options api是如何与composition api相关的。
<template>
<button @click=generateUsers>
Generate Users
</button>
<Child/>
</template>
<script>
import {reactive, provide, toRefs} from "vue";
import Child from "./Child.vue";
export default {
name: "App",
components: {
Child
},
setup() {
const data = reactive({users: ""});
const generateUsers = () => {
// notice here you are REASSIGNING the users
data.users = [
{id: 1, name: "Alice"}, {id: 2, name: "Bob"}
];
console.log(data.users);
}
// this way of provide will NOT work
provide("users", data.users);
// this way works because of toRefs
const {users} = toRefs(data);
provide("users", users);
return {generateUsers};
}
}
</script>
需要注意的几点:
data
options api 中的选项与const data = reactive({users: ""})
. Vue 将运行你的 data() 方法,你必须从那里返回一个普通的 object。然后 Vue 会自动调用reactive
来为其添加响应性。provide
另一方面,它并没有做任何魔术 - 无论是在选项 api 中,还是在组合 api 中。它只是将提供给消耗组件的任何内容传递给消耗组件,而无需任何按摩。- 原因
provide("users", data.users)
不像您预期的那样起作用,因为您填充用户的方式不是对同一data.users
对象的更改(实际上是响应式的),而是一起重新分配。 - 之所以
toRefs
有效是因为 toRefs链接到原始父级。
考虑到这种理解,要修复您的原始代码,您只需要确保您更改而不是重新分配用户。最简单的方法是将 user 定义为一个数组,并在加载数据时将其推入其中。(与最初将其定义为字符串并稍后重新分配它相反)
PS 也适用于组合 api,并且更简单的是:
<template>
<button @click=generateUsers>
Generate Users
</button>
<Child/>
</template>
<script>
import {ref, provide} from "vue";
import Child from "./Child.vue";
export default {
name: "App",
components: {
Child
},
setup() {
const users = ref();
const generateUsers = () => {
// notice here you are not reassigning the users
// but CHANGING its value
users.value = [
{id: 1, name: "Alice"}, {id: 2, name: "Bob"}
];
console.log(users.value);
}
provide("users", users);
return {generateUsers};
}
}
</script>
推荐阅读
- python - PATH="/custom/dir:$PATH" 前置而不是附加 - Conda vs Pyenv
- yaml - 单转义的yaml输出?
- javascript - 在 vue.js 中访问 javascript 对象
- c++ - 如何解决此重载错误 (c1) 情况?
- geopandas - 上下文制作奇怪的背景图
- linux - 如何阻止 kuberenetes pod 内的 postgres 进程响应
- django - 使用 as_crispy_form 模板标签更改 help_text 位置
- json - 前端/后端之间的新 Date() 时间戳差异
- windows - 从 Git bash 脚本中发送击键(Windows)
- nginx - 使用 nginx 代理获取 404 的静态文件