如何使用 Vue JS 在子组件中保留数字和增量?

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

练习使用 Vue JS 制作待办事项应用程序

输入项目保存在localStrage。

已更新

当您添加了一些列表并重新加载页面时,ID 编号从 1(默认)开始。

理想行为:

我的代码:Link

问题就在这里。

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)
    } 
},

看这里:https://codesandbox.io/s/keen-gates-q7efo

根据我对你问题的理解,你想更新子组件的道具值。

为此,您可能希望将更改从子组件发回到父组件。

下面是一种方法:

在您的子组件中:

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
}

希望对您有所帮助。祝你好运!

keyObject 和 this.todos 格式不一致(this.todos 实际上是嵌套的),你不应该改变 props。

另请注意 ID 递增以避免循环中的重复错误

我的建议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
     }

  }

孩子 2:

<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>