练习用Vue JS做一个todo应用。
输入的项目保存在localStrage中。
已更新
当您添加了一些列表并重新加载页面时,ID号从1开始(defalut)。
理想的行为。
我的代码。链接
问题就在这附近。
Child2.vue
created() {
let keyObject = JSON.parse(localStorage.getItem(this.keyName));
if (keyObject) {
this.$emit("update:todos", keyObject);
} else {
return;
}
if (this.todos.length > 0) {
console.log(this.todos.id);
const setId = this.todos.reduce(function(a,b){ return a > b.id ? a : b.id} ,0)
this.todos.id = setId + 1
console.log(this.todos.id);
this.$emit('update:todos', keyObject)
// this.$emit('update:todos', this.todos.id)
}
},
你知道怎么做吗?
你可以避免直接使用修改道具 .sync
修改器。
App.vue:
<Child2 :todos.sync="todos" :keyName="keyName"/>
Child2. vue:
if (keyObject) {
this.$emit('update:todos', keyObject);
}
对于获取下一个id,你可以在从本地存储中获取数组时发出这个值。
App. vue:
<Child2 :todos.sync="todos" @setTargetId="setTargetId" :keyName="keyName"/>
methods: {
// ...
setTargetId(newTargetId){
this.$set(this.target, 'id', newTargetId );
}
}
Child2.vue:
// ...
created() {
let keyObject = JSON.parse(localStorage.getItem(this.keyName));
// Check keyObject
if (keyObject) {
// update todo on App.vue
this.$emit("update:todos", keyObject);
// set target.id
const setId = keyObject.reduce(function(a,b){ return a > b.id ? a : b.id} ,0)
this.$emit('setTargetId', setId + 1)
}
},
在keyObject和this.todos中的格式不一致(this.todos实际上是嵌套的),而且你不应该突变道具。
同时注意ID的增量,以避免在LOOPS中出现重复错误。
我的建议是App.vue。
methods: {
addBtn() {
const todo = { id: this.target.id, name: this.target.name, done: false };
this.todos.push(todo);
localStorage.setItem(this.keyName, JSON.stringify(this.todos));
this.target.name = "";
//it is important to increment the id based on current length
this.target.id = this.todos.length + 1;
},
onInputChange(val) {
this.target.name = val;
}
},
created() {
let todosObject = JSON.parse(localStorage.getItem(this.keyName));
if(todosObject){
this.todos = todosObject
//again base the id on the current length, to avoid duplicate error in loops later
this.target.id = this.todos.length+1
}
}
Child2:
<template>
<div>
<ul>
<li v-for="todo in todos" :key="todo.id">
ID: {{ todo.id }} / Name: {{ todo.name }}
<input
type="checkbox"
v-model="todo.done"
@click="status(todo)"
>
<button @click="removeBtn(todo)">Remove item</button>
</li>
</ul>
</div>
</template>
<script>
export default {
props: {
todos: {
type: Array,
required: true
},
keyName: {
type: String,
required: true
}
},
methods: {
removeBtn(item) {
const index = this.todos.indexOf(item);
this.todos.splice(index, 1);
localStorage.setItem(this.keyName, JSON.stringify(this.todos));
if (this.todos.length === 0) {
console.log("no item");
}
},
status(todo) {
todo.done = !todo.done;
localStorage.setItem(this.keyName, JSON.stringify(this.todos));
}
}
};
</script>
根据我对你的问题的理解,你想更新子组件中道具的值。
要做到这一点,你可能想把子组件的变化发射回父组件。
下面是一种方法。
在你的子组件中,
this.todosArray = this.todosArray.concat(keyObject); //concat with an existing array
this.$emit("updateTodos", this.todosArray); //emit new array back to parent
在你的父组件中,在你注册你的子组件的地方,
<Child2 :todos="todos" :keyName="keyName" @updateTodos="updateTodos"/>
然后添加一个方法来更新原来的数组 用来自于子组件的值。
updateTodos(value) {
this.todos = value
}
希望能帮到你。祝大家好运!