How can I keep number and increment in child component with Vue JS?

孤街醉人 提交于 2020-07-10 01:55:52

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!