javascript - VueJS DOM 未在组件中更新
问题描述
我浏览了其他“DOM 未更新”的帖子,但还没有找到解决方案。我正在尝试为初学者创建一个任务应用程序,该应用程序已经可以从 Firestore 加载,添加一个新的并删除一个。我有两个问题,但我想从第一个开始。当我添加、删除数据时,DOM 不会动态更新,尽管 Vuex 存储中的相应数组已正确更新。当我重新加载页面时,它也在更新。
我已经添加了组件和商店的代码,我希望我在正确的地方寻找,但我感觉我不是。
提前致谢
店铺代码:
import Vue from 'vue'
import Vuex from 'vuex'
// import firebase from 'firebase'
import router from '@/router'
import db from '@/db'
import firebase from '@/firebase'
Vue.use(Vuex)
export const store = new Vuex.Store({
state: {
appTitle: 'My Awesome App',
addedTask: false,
loadedTasks: false,
deletedTasks: false,
user: null,
error: null,
loading: false,
tasks: [],
task: {
title: '',
description: '',
tags: [],
dueTime: '',
dueDate: '',
reminderFlag: Boolean,
quadrant: '',
userId: '',
timestamp: ''
}
},
// Mutations (synchronous): change data in the store
mutations: {
setUser (state, payload) {
state.user = payload
state.task.userId = firebase.auth().currentUser.uid
},
setError (state, payload) {
state.error = payload
},
setLoading (state, payload) {
state.loading = payload
},
addedTask (state, payload) {
state.addedTask = payload
},
loadedTasks (state, payload) {
state.loadedTasks = true
},
deletedTask (state, payload) {
state.deletedTask = payload
}
},
// Actions (asynchronous/synchronous): change data in the store
actions: {
autoSignIn ({ commit }, payload) {
commit('setUser', { email: payload.email })
},
userSignUp ({ commit }, payload) {
commit('setLoading', true)
firebase.auth().createUserWithEmailAndPassword(payload.email, payload.password)
.then(firebaseUser => {
commit('setUser', { email: firebaseUser.user.email })
commit('setLoading', false)
router.push('/home')
commit('setError', null)
})
.catch(error => {
commit('setError', error.message)
commit('setLoading', false)
})
},
userSignIn ({ commit }, payload) {
commit('setLoading', true)
firebase.auth().signInWithEmailAndPassword(payload.email, payload.password)
.then(firebaseUser => {
commit('setUser', { email: firebaseUser.user.email })
commit('setLoading', false)
commit('setError', null)
router.push('/home')
})
.catch(error => {
commit('setError', error.message)
commit('setLoading', false)
})
},
userSignOut ({ commit }) {
firebase.auth().signOut()
commit('setUser', null)
router.push('/')
},
addNewTask ({ commit }, payload) {
commit('addedTask', false)
db.collection('tasks').add({
title: payload.title,
userId: firebase.auth().currentUser.uid,
createdOn: firebase.firestore.FieldValue.serverTimestamp(),
description: payload.description,
dueDateAndTime: new Date(payload.dueDate & ' ' & payload.dueTime),
reminderFlag: payload.reminderFlag,
quadrant: payload.quadrant,
tags: payload.tags
})
.then(() => {
commit('addedTask', true)
this.state.tasks.push(payload)
commit('loadedTasks', true)
})
.catch(error => {
commit('setError', error.message)
})
},
getTasks ({ commit }) {
commit('loadedTasks', false)
db.collection('tasks').orderBy('createdOn', 'desc').get().then(querySnapshot => {
querySnapshot.forEach(doc => {
const data = {
'taskId': doc.id,
'title': doc.data().title,
'quadrant': doc.data().quadrant
}
this.state.tasks.push(data)
})
commit('loadedTasks', true)
})
},
deleteTask ({ commit }, payload) {
db.collection('tasks').doc(payload).delete().then(() => {
this.state.tasks.pop(payload)
commit('deletedTask', true)
commit('loadedTasks', true)
}).catch(function (error) {
console.error('Error removing document: ', error)
commit('deletedTask', false)
})
}
},
// Getters: receive data from the store
getters: {
isAuthenticated (state) {
return state.user !== null && state.user !== undefined
}
}
})
这是组件(Vue 应用程序 -> 主页 -> 网格 -> 任务列表(this):
<template>
<v-card>
<v-card-title primary class="title">{{title}}</v-card-title>
<v-flex v-if="tasks.length > 0">
<v-slide-y-transition class="py-0" group tag="v-list">
<template v-for="(task, i) in tasks" v-if="task.quadrant === Id">
<v-divider v-if="i !== 0" :key="`${i}-divider`"></v-divider>
<v-list-tile :key="`${i}-${task.text}`">
<v-list-tile-action>
<v-checkbox v-model="task.done" color="info darken-3">
<div slot="label" :class="task.done && 'grey--text' || 'text--primary'" class="text-xs-right" v-text="task.title +' ('+ task.taskId +')'"></div>
</v-checkbox>
</v-list-tile-action>
<v-spacer></v-spacer>
<v-scroll-x-transition>
<v-btn flat icon color="primary" v-show="!deleteConfirmation" @click="deleteConfirmation = !deleteConfirmation">
<v-icon>delete</v-icon>
</v-btn>
</v-scroll-x-transition>
<v-scroll-x-transition>
<v-btn flat icon color="green" v-show="deleteConfirmation" @click="deleteConfirmation = !deleteConfirmation">
<v-icon>cancel</v-icon>
</v-btn>
</v-scroll-x-transition>
<v-scroll-x-transition>
<v-btn flat icon color="red" v-show="deleteConfirmation" @click="deleteConfirmation = !deleteConfirmation; deleteTask(task.taskId)">
<v-icon>check_circle</v-icon>
</v-btn>
</v-scroll-x-transition>
</v-list-tile>
</template>
</v-slide-y-transition>
</v-flex>
</v-card>
</template>
<script>
export default {
data () {
return {
deleteConfirmation: false
}
},
props: ['Id', 'title'],
computed: {
tasks () {
return this.$store.state.tasks
}
},
methods: {
deleteTask (taskId) {
console.log(taskId)
this.$store.dispatch('deleteTask', taskId)
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.container {
max-width: 1200px;
}
</style>
解决方案
您没有实际更改tasks
数组的突变,例如this.state.tasks.pop(payload)
发生在deleteTask
动作中,而不是突变。
在 Vuex 存储中真正改变状态的唯一方法是提交一个突变。 https://vuex.vuejs.org/guide/mutations.html
这也是您在重新加载后看到正确结果的原因:Firestore 实现很好并且更新了它的值。它将在重新加载后显示更新和新获取的数组tasks
,但 Vuex 状态在重新加载之前永远不会改变,因此 Vue 对数组的显示保持不变。tasks
解决方案非常简单:
创建一个新的突变:
REMOVE_FROM_TASKS (state, payload) {
// algorithm to remove, e. g. by id
state.tasks = state.tasks.filter(e => {
return e.id !== payload;
});
},
在您的操作中使用此突变:
deleteTask ({ commit }, payload) {
db.collection('tasks').doc(payload).delete().then(() => {
commit('REMOVE_FROM_TASKS', payload)
commit('deletedTask', true)
commit('loadedTasks', true)
}).catch(function (error) {
console.error('Error removing document: ', error)
commit('deletedTask', false)
})
}
推荐阅读
- ruby-on-rails - 在 Rails 中定义枚举值时出错
- angular6 - 安装 Angular 的 CDK 后在编译过程中出错
- segment - 为什么 Druid 段在数据摄取后变得不可用
- websocket - 如何为 Hanami 测试 WebSockets?
- symfony - Symfony:从未调用过自定义验证器
- r - 通过逐元素向量比较找到最小差异和对应值的最佳方法是什么?
- java - 日志写入方法中的 Sonarlint 投诉
- c# - 如何从用户属性中获取 RouteData.Values["action"].ToString()
- arrays - 在keras中实现切片层
- django - TinyMCE 没有出现在 Django 管理员中