我按照本教程尝试学习 Vue,我已经完成并且它可以工作,但我正在尝试做出我正在努力的改变。
https://savvyapps.com/blog/definitive-guide-building-web-app-vuejs-firebase
所以有一个“设置”页面,其中包含用户个人资料(他们可以编辑他们的名字等)。当“设置”/“配置文件”页面加载时,我希望表单加载他们现有的数据,以便他们可以修改它并按保存。
它当前作为占位符加载 :placeholder="userProfile.name"
- 我希望它只用实际值填写表格,而不是将其作为占位符。
感觉这样做应该非常简单,但不能让它优雅地工作。
设置.vue
<template>
<section id="settings">
<div class="col1">
<h3>Settings</h3>
<p>Update your profile</p>
<transition name="fade">
<p v-if="showSuccess" class="success">profile updated</p>
</transition>
<form @submit.prevent>
<label for="name">Name</label>
<input v-model.trim="name" type="text" id="name" />
<label for="title">Job Title</label>
<input v-model.trim="title" type="text" id="title" />
<button @click="updateProfile()" class="button">Update Profile</button>
</form>
</div>
</section>
</template>
<script>
import { mapState } from "vuex";
export default {
data() {
return {
name: "",
title: "",
showSuccess: false,
};
},
computed: {
...mapState(["userProfile"]),
},
methods: {
updateProfile() {
this.$store.dispatch("updateProfile", {
name: this.name !== "" ? this.name : this.userProfile.name,
title: this.title !== "" ? this.title : this.userProfile.title,
});
this.name = "";
this.title = "";
this.showSuccess = true;
setTimeout(() => {
this.showSuccess = false;
}, 2000);
},
},
};
</script>
<style lang="scss" scoped>
</style>
我尝试将数据部分更改为此,当我离开页面并返回它时它可以工作,但是如果我刷新页面(F5),这些字段是空白的,直到我离开页面并再次返回。data() {
return {
name: this.$store.state.userProfile.name,
title: this.$store.state.userProfile.title,
showSuccess: false,
};
},
如果您需要查看,这是我的商店:存储/index.js
import Vue from "vue";
import Vuex from "vuex";
import * as fb from "../firebase";
import router from "../router/index";
Vue.use(Vuex);
// realtime firebase connection
fb.postsCollection.orderBy("createdOn", "desc").onSnapshot((snapshot) => {
let postsArray = [];
snapshot.forEach((doc) => {
let post = doc.data();
post.id = doc.id;
postsArray.push(post);
});
store.commit("setPosts", postsArray);
});
const store = new Vuex.Store({
state: {
userProfile: {},
posts: [],
},
mutations: {
setUserProfile(state, val) {
state.userProfile = val;
},
setPosts(state, val) {
state.posts = val;
},
},
actions: {
async signup({ dispatch }, form) {
// sign user up
const { user } = await fb.auth.createUserWithEmailAndPassword(
form.email,
form.password
);
// create user profile object in userCollections
await fb.usersCollection.doc(user.uid).set({
name: form.name,
title: form.title,
});
// fetch user profile and set in state
dispatch("fetchUserProfile", user);
},
async login({ dispatch }, form) {
// sign user in
const { user } = await fb.auth.signInWithEmailAndPassword(
form.email,
form.password
);
// fetch user profile and set in state
dispatch("fetchUserProfile", user);
},
async logout({ commit }) {
await fb.auth.signOut();
// clear userProfile and redirect to /login
commit("setUserProfile", {});
router.push("/login");
},
async fetchUserProfile({ commit }, user) {
// fetch user profile
const userProfile = await fb.usersCollection.doc(user.uid).get();
// set user profile in state
commit("setUserProfile", userProfile.data());
// change route to dashboard
if (router.currentRoute.path === "/login") {
router.push("/");
}
},
async createPost({ state }, post) {
await fb.postsCollection.add({
createdOn: new Date(),
content: post.content,
userId: fb.auth.currentUser.uid,
userName: state.userProfile.name,
comments: 0,
likes: 0,
});
},
async likePost(context, { id, likesCount }) {
const userId = fb.auth.currentUser.uid;
const docId = `${userId}_${id}`;
// check if user has liked post
const doc = await fb.likesCollection.doc(docId).get();
if (doc.exists) {
return;
}
// create post
await fb.likesCollection.doc(docId).set({
postId: id,
userId: userId,
});
// update post likes count
fb.postsCollection.doc(id).update({
likes: likesCount + 1,
});
},
async updateProfile({ dispatch }, user) {
const userId = fb.auth.currentUser.uid;
// update user object
/*const userRef = */await fb.usersCollection.doc(userId).update({
name: user.name,
title: user.title,
});
dispatch("fetchUserProfile", { uid: userId });
// update all posts by user
const postDocs = await fb.postsCollection
.where("userId", "==", userId)
.get();
postDocs.forEach((doc) => {
fb.postsCollection.doc(doc.id).update({
userName: user.name,
});
});
// update all comments by user
const commentDocs = await fb.commentsCollection
.where("userId", "==", userId)
.get();
commentDocs.forEach((doc) => {
fb.commentsCollection.doc(doc.id).update({
userName: user.name,
});
});
},
},
modules: {},
});
export default store;
编辑我应该提到这些数据正在从 Firebase Firestore 加载到状态中。看起来这只是一个时间问题,当它在组件上设置 data() 时,数据还没有完全加载——我添加了一些控制台日志。
Fetching user profile.. Settings.vue?e12e:29
Setting Data... index.js?4360:75
Performing setUserProfile commit.. index.js?4360:29
Setting user profile in state, last step..
再次只是对 Vue 的了解还不够,还不知道如何最好地更改该顺序..
最佳答案
v-model
获取 和 套你传递给它的任何东西的值(value)。由于您要编辑状态属性,因此只要修改 <input>
的值,它将尝试更改(又名变异)状态属性的值。这将打破不变性原则 [1] .
这里的解决方案是将计算属性传递给 v-model
它使用 getter 和 setter,您可以在其中告诉组件从哪里获取值以及如何更新它。
默认 computed
properties 是一种简写形式,仅包含 getter。基本上,
computed: {
name() {
return this.$store.state.userProfile.name
}
}
...可以写成:computed: {
name: {
get() {
return this.$store.state.userProfile.name
}
}
}
您需要添加一个提交适当突变的 setter ,以便更新状态:computed: {
...mapState(["userProfile"]),
name: {
get() {
return this.userProfile.name
},
set(val) {
this.$store.commit('setUserProfile', {
...this.userProfile,
name: val
});
}
},
title: {
get() {
return this.userProfile.title
},
set(val) {
this.$store.commit('setUserProfile', {
...this.userProfile,
title: val
});
}
}
}
计算的 setter 记录在 here .[1] - 你使用Vuex的原因是你不想让任何组件直接modify your data .相反,您希望他们将更改提交到状态,以便使用该数据的每个组件都收到更改通知。如果您允许
v-model
要直接更改您的数据,您将违反不变性原则,因此您的状态将不再是唯一的事实来源。
关于javascript - Vuex 从状态加载现有表单数据以进行编辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64018053/