问题
Practicing to make a todo application with Vue JS
Input items save in the localStrage.
UPDATED
When you have some added list and reload a page, ID number start from 1(defalut).
Ideal behaviour:
- when reload a page, ID number continues number increment.
- if some items removed, then, add new item, ID number should be the biggest ID number in array(if 8) +1 (should be 9).
My code: Link
Problem is around here.
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)
}
},
Do you know how?
回答1:
You can avoid modify props directly using .sync modifier:
App.vue:
<Child2 :todos.sync="todos" :keyName="keyName"/>
Child2.vue:
if (keyObject) {
this.$emit('update:todos', keyObject);
}
For get the next id, you can emit this value when you get the array from local storage:
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)
}
},
See here: https://codesandbox.io/s/keen-gates-q7efo
回答2:
There is inconsistent formatting in keyObject and this.todos( this.todos is actually nested), and you are not suppose to mutate props.
ALSO NOTICE THE ID INCREMENTATION TO AVOID DUPLICATE ERROR IN LOOPS
My suggestion 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>
回答3:
From my understanding of your problem, you want to update the value of the props from a child component.
To do that you might want to emit the change from a child component back to the parent.
Below is one way of doing that:
In your child component:
this.todosArray = this.todosArray.concat(keyObject); //concat with an existing array
this.$emit("updateTodos", this.todosArray); //emit new array back to parent
In your parent component, where u register your child component:
<Child2 :todos="todos" :keyName="keyName" @updateTodos="updateTodos"/>
and then add a method to update the original array with the value that will come from the child component.
updateTodos(value) {
this.todos = value
}
I hope it helps. Good luck!
来源:https://stackoverflow.com/questions/62146116/how-can-i-keep-number-and-increment-in-child-component-with-vue-js