我是VueJS的新手,由于我的日常工作,不得不休息几个月。我现在尝试取回我的项目,但是仍然没有解决一个问题:
我已经看过其他的“ DOM未更新”帖子,但是无法找到解决方案。我正在尝试为初学者创建一个任务应用,并且该应用已经可以从Firestore加载,添加一个新应用并删除其中一个。我有两个问题,但我想从第一个开始。当我添加或更新任务时,尽管Vuex存储中的各个数组已正确更新,但DOM并未动态更新。当我重新加载页面时,它正在更新。当我删除帖子时,DOM会更新。
我已经添加了组件和商店的代码,希望在正确的位置查找,但是我有一种感觉。
预先感谢
商店代码:
import Vue from 'vue'
import Vuex from 'vuex'
import router from '@/router'
import db from '@/db'
import firebase from '@/firebase'
Vue.use(Vuex)
export const store = new Vuex.Store({
state: {
appTitle: 'ESNHWR task app',
formMode: 'add',
taskFormVisible: false,
addedTask: false,
loadedTasks: false,
deletedTasks: false,
user: null,
error: null,
loading: false,
datePicker: null,
timePicker: null,
tasks: [],
// tempTask: {},
task: {
taskId: '',
title: '',
description: '',
tags: [],
dueTime: '',
dueDate: '',
reminderFlag: false,
quadrant: '',
userId: '',
urgencyFlag: false,
importanceFlag: false,
dueTimestamp: ''
}
},
// 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
},
DELETE_TASK (state, payload) {
state.tasks = state.tasks.filter(task => {
return task.taskId !== payload
})
},
UPDATE_TASK (state, payload) {
const item = state.tasks.find(task => {
return task.taskId === payload.taskId
})
const index = state.tasks.indexOf(item)
Vue.set(state.tasks, index, payload)
},
ADD_NEW_TASK (state, payload) {
state.tasks.push(payload)
},
GET_TASKS (state, payload) {
state.tasks = payload
},
GET_TASK_DETAILS (state, payload) {
var moment = require('moment')
var date = new Date()
date = this.state.task.dueTimestamp
var s = moment(date).format('YYYY-MM-DD')
var t = moment(date).format('HH:mm')
state.task.dueDate = s
state.datePicker = s
state.task.dueTime = t
state.timePicker = t
state.task = payload
},
CHANGE_TASKFORM_VISIBILITY (state, payload) {
state.taskFormVisible = payload
},
SET_FORMMODE (state, payload) {
state.formMode = payload
},
RESET_TASK_FORM (state) {
state.task.taskId = ''
state.task.title = ''
state.task.description = ''
state.task.tags = []
state.task.dueTime = ''
state.task.dueDate = ''
state.task.reminderFlag = false
state.task.quadrant = ''
state.task.userId = ''
state.task.urgencyFlag = false
state.task.importanceFlag = false
state.task.dueTimestamp = ''
state.datePicker = null
state.timePicker = null
}
},
// 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('/')
},
changeTaskformVisibility ({ commit }) {
if (this.state.taskFormVisible === false) {
commit('CHANGE_TASKFORM_VISIBILITY', true)
commit('SET_FORMMODE', 'add')
} else {
commit('CHANGE_TASKFORM_VISIBILITY', false)
commit('SET_FORMMODE', 'add')
}
},
addNewTask ({ commit }, payload) {
db.collection('tasks').add({
title: payload.title,
userId: firebase.auth().currentUser.uid,
createdOn: firebase.firestore.FieldValue.serverTimestamp(),
testOn: firebase.firestore.Timestamp.fromDate(payload.dueTimestamp),
description: payload.description,
dueDateAndTime: payload.dueTimestamp,
reminderFlag: payload.reminderFlag,
quadrant: payload.quadrant,
tags: payload.tags,
updatedOn: firebase.firestore.FieldValue.serverTimestamp(),
urgencyFlag: payload.urgencyFlag,
importanceFlag: payload.importanceFlag,
isCompleted: false
})
.then(() => {
commit('ADD_NEW_TASK', payload)
commit('SET_FORMMODE', 'add')
commit('CHANGE_TASKFORM_VISIBILITY', false)
})
.catch(error => {
commit('setError', error.message)
})
},
getTasks ({ commit }) {
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
// add due date and time
// add isCompleted Flag
}
this.state.tasks.push(data)
})
commit('GET_TASKS', this.state.tasks)
})
},
getTaskDetails ({ commit }, payload) {
db.collection('tasks').doc(payload).get().then(doc => {
this.state.task.taskId = doc.id
this.state.task.title = doc.data().title
this.state.task.quadrant = doc.data().quadrant
this.state.task.description = doc.data().description
this.state.task.tags = doc.data().tags
this.state.task.dueTimestamp = doc.data().dueDateAndTime
this.state.task.reminderFlag = doc.data().reminderFlag
this.state.task.urgencyFlag = doc.data().urgencyFlag
this.state.task.importanceFlag = doc.data().importanceFlag
// add isCompleted Flag
}).then(() => {
commit('GET_TASK_DETAILS', this.state.task)
commit('SET_FORMMODE', 'update')
commit('CHANGE_TASKFORM_VISIBILITY', true)
}).catch(function (error) {
commit('setError', error.message)
})
},
updateTask ({ commit }, payload) {
db.collection('tasks').doc(payload.taskId).update({
title: payload.title,
description: payload.description,
dueDateAndTime: payload.dueTimestamp,
reminderFlag: payload.reminderFlag,
quadrant: payload.quadrant,
tags: payload.tags,
updatedOn: firebase.firestore.FieldValue.serverTimestamp(),
urgencyFlag: payload.urgencyFlag,
importanceFlag: payload.importanceFlag
// add isCompleted Flag
}).then(() => {
commit('UPDATE_TASK', payload)
commit('CHANGE_TASKFORM_VISIBILITY', false)
commit('SET_FORMMODE', 'add')
}).catch(function (error) {
commit('setError', error.message)
})
},
deleteTask ({ commit }, payload) {
db.collection('tasks').doc(payload).delete().then(() => {
commit('DELETE_TASK', payload)
}).catch(function (error) {
// console.error('Error removing document: ', error)
commit('setError', error.message)
})
},
resetTaskForm ({ commit }) {
commit('RESET_TASK_FORM', 'true')
}
},
// Getters: receive data from the store
getters: {
isAuthenticated (state) {
return state.user !== null && state.user !== undefined
}
}
})
组件代码(用于添加和更新):
<template>
<v-container grid-list-xl>
<v-form ref="form" lazy-validation>
<v-card>
<v-card-text>
<v-text-field v-model="$store.state.task.title" autofocus ref="taskTitle" label="Add a new task" prepend-icon="check_circle_outline" required>
</v-text-field>
<v-layout row wrap>
<v-flex xs12 sm6 md4>
<v-menu ref="datePicker" :first-day-of-week="1" locale="us-US" show-current :close-on-content-click="false" v-model="task.datePicker" :nudge-right="40" :return-value.sync="$store.state.task.dueDate" lazy transition="scale-transition" offset-y full-width min-width="200px">
<v-text-field slot="activator" v-model="$store.state.datePicker" label="Choose due date" prepend-icon="event" readonly></v-text-field>
<v-date-picker v-model="$store.state.datePicker" @input="$refs.datePicker.save($store.state.datePicker)"></v-date-picker>
</v-menu>
</v-flex>
<v-flex xs12 sm6 md4>
<v-menu ref="timePicker" :close-on-content-click="false" v-model="task.timePicker" :nudge-right="40" :return-value.sync="$store.state.task.dueTime" lazy transition="scale-transition" offset-y full-width min-width="290px">
<v-text-field slot="activator" v-model="$store.state.timePicker" label="Choose due time" prepend-icon="access_time" readonly></v-text-field>
<v-time-picker v-model="$store.state.timePicker" @change="$refs.timePicker.save($store.state.timePicker)"></v-time-picker>
</v-menu>
</v-flex>
<v-flex xs12 sm6 md4>
<v-switch v-model="$store.state.task.reminderFlag" label="Add reminder" prepend-icon="access_alarm" color="primary" hide-details></v-switch>
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs12 sm6 md4>
<v-switch v-model="$store.state.task.importanceFlag" label="Important" prepend-icon="error_outline" color="primary" hide-details></v-switch>
</v-flex>
<v-flex xs12 sm6 md4>
<v-switch v-model="$store.state.task.urgencyFlag" label="Urgent" prepend-icon="update" color="primary" hide-details></v-switch>
</v-flex>
<v-flex xs12 sm6 md4>
<p>Quadrant: {{ identifyQuadrant }}</p>
</v-flex>
</v-layout>
<v-textarea name="description" label="Enter description" auto-grow value="" prepend-icon="description" v-model="$store.state.task.description"></v-textarea>
<v-combobox v-model="$store.state.task.tags" :items="items" label="Tags" chips prepend-icon="filter_list" solo multiple>
<template slot="selection" slot-scope="data">
<v-chip :selected="data.selected" close @input="remove(data.item)">
<p>{{ data.item }}</p>
</v-chip>
</template>
</v-combobox>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" flat @click.prevent="changeTaskformVisibility" v-if="$store.state.formMode === 'add'">Cancel</v-btn>
<v-btn color="primary" @click.prevent="addNewTask" v-if="$store.state.formMode === 'add'">Add new task</v-btn>
<v-btn color="primary" flat @click.prevent="cancelUpdateTask" v-if="$store.state.formMode === 'update'">Cancel update</v-btn>
<v-btn color="primary" @click.prevent="updateTask" v-if="$store.state.formMode === 'update'">Update task</v-btn>
</v-card-actions>
</v-card-text>
</v-card>
</v-form>
</v-container>
</template>
<script>
export default {
data () {
return {
// task: {},
items: [], // tags - to be renamed
date: null,
time: null,
datePicker: false,
timePicker: false,
task: {
title: '',
description: '',
tags: [],
dueTime: '',
dueDate: '',
reminderFlag: false,
quadrant: '',
urgencyFlag: false,
importanceFlag: false,
dueTimestamp: ''
}
}
},
methods: {
dateTimeToTimestamp () {
var dateFromPicker = this.$store.state.task.dueDate
var timeFromPicker = this.$store.state.task.dueTime
var dateParts = dateFromPicker.split('-')
var timeParts = timeFromPicker.split(':')
var localDate = new Date(dateParts[0], dateParts[1] - 1, dateParts[2], timeParts[0], timeParts[1])
return localDate
},
addNewTask () {
this.$store.state.task.dueTimestamp = this.dateTimeToTimestamp()
this.$store.dispatch('addNewTask', this.$store.state.task)
this.$store.dispatch('resetTaskForm', 'true')
},
updateTask () {
this.$store.state.task.dueTimestamp = this.dateTimeToTimestamp()
this.$store.dispatch('updateTask', this.$store.state.task)
this.$store.dispatch('resetTaskForm', 'true')
},
cancelUpdateTask () {
this.$store.dispatch('changeTaskformVisibility')
},
cancelAddTask () {
console.log('cancelling ...')
},
changeTaskformVisibility () {
this.$store.dispatch('changeTaskformVisibility')
}
},
computed: {
identifyQuadrant () {
if (this.$store.state.task.importanceFlag === true && this.$store.state.task.urgencyFlag === true) {
this.$store.state.task.quadrant = 'do'
} else if (this.$store.state.task.importanceFlag === true && this.$store.state.task.urgencyFlag === false) {
this.$store.state.task.quadrant = 'plan'
} else if (this.$store.state.task.importanceFlag === false && this.$store.state.task.urgencyFlag === true) {
this.$store.state.task.quadrant = 'delegate'
} else if (this.$store.state.task.importanceFlag === false && this.$store.state.task.urgencyFlag === false) {
this.$store.state.task.quadrant = 'eliminate'
}
return this.$store.state.task.quadrant
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.container {
max-width: 1200px;
}
/* Extras */
a:visited {
color: #888;
}
a {
color: #444;
text-decoration: none;
}
p {
margin-bottom: 0.3em;
}
</style>
组件代码(用于删除(并将任务详细信息加载到上面的组件中)):
<template>
<div>{{task.title}} ({{task.taskId}})<v-spacer></v-spacer> delete: {{deleteConfirmation}}, complete: {{completeConfirmation}}
<v-scroll-x-transition>
<v-btn flat icon color="secondary" v-show="!deleteConfirmation && !completeConfirmation" @click="completeConfirmation = !completeConfirmation">
<v-icon>done</v-icon>
</v-btn>
</v-scroll-x-transition>
<v-scroll-x-transition>
<v-btn flat icon color="primary" v-show="!deleteConfirmation && !completeConfirmation" @click="getTaskDetails(task.taskId)">
<v-icon>edit</v-icon>
</v-btn>
</v-scroll-x-transition>
<v-scroll-x-transition>
<v-btn flat icon color="primary" v-show="!deleteConfirmation && !completeConfirmation" @click="deleteConfirmation = !deleteConfirmation">
<v-icon>delete</v-icon>
</v-btn>
</v-scroll-x-transition>
<!-- Confirm or cancel deletion -->
<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>
<!-- Confirm or cancel completion -->
<v-scroll-x-transition>
<v-btn flat icon color="red" v-show="completeConfirmation" @click="completeConfirmation = !completeConfirmation">
<v-icon>cancel</v-icon>
</v-btn>
</v-scroll-x-transition>
<v-scroll-x-transition>
<v-btn flat icon color="green" v-show="completeConfirmation" @click="completeConfirmation = !completeConfirmation; markTaskAsCompleted(task.taskId)">
<v-icon>check_circle</v-icon>
</v-btn>
</v-scroll-x-transition>
</li>
</div>
</template>
<script>
export default {
data () {
return {
deleteConfirmation: false,
completeConfirmation: false
}
},
props: ['task'],
computed: {
},
methods: {
deleteTask (taskId) {
this.$store.dispatch('deleteTask', taskId)
},
getTaskDetails (taskId) {
this.$store.dispatch('getTaskDetails', taskId)
},
markTaskAsCompleted (taskId) {
this.$store.dispatch('markTaskAsCompleted', taskId)
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
非常感谢帮助初学者!
答案 0 :(得分:0)
我认为我想出了增加的方法-我处理了商店中的所有任务。我现在将其更改为本地任务对象,并且工作正常。现在,我在更新方面遇到了另一个挑战,但是我将把它发布为另一个问题。