如何使用 Vue JS 在子组件中保留数字和增量?
Posted
技术标签:
【中文标题】如何使用 Vue JS 在子组件中保留数字和增量?【英文标题】:How can I keep number and increment in child component with Vue JS? 【发布时间】:2020-09-20 13:46:39 【问题描述】:练习用 Vue JS 做一个 todo 应用
输入项保存在localStrage中。
更新
当您添加了一些列表并重新加载页面时,ID 号从 1 开始(默认)。
理想行为:
重新加载页面时,ID 号继续编号递增。 如果删除了一些项目,那么,添加新项目,ID号应该是数组中最大的ID号(如果8)+1(应该是9)。我的代码: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)
,
你知道吗?
【问题讨论】:
问题是this.todos.push(keyObject);
,因为它会创建一个嵌套数组。您需要使用 concat 附加数组,或者改为在 keyObject
的每个元素上调用 push。举例来说,如果您保存了项目 A、B、C,则该行将创建 [[A, B, C]]
并添加您现在拥有的第四个项目 [[A, B, C], D]
。每次重新加载应用程序时,嵌套都会累积。
我不确定你的目标是什么,因为你说了 3 个不同的目标
@Chris G,感谢您的评论。我会尝试使用concat
来更新todos
数组。
@Billal Begueradj,很抱歉造成混乱。我对vue很陌生,我正在练习并试图理解它
【参考方案1】:
你可以避免直接使用.sync
修饰符来修改props:
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
【讨论】:
非常感谢。问题解决了。现在另一个问题发生了。我想在重新加载页面时保持 ID 号递增。现在它从id: 1,
重新启动,这会导致错误。是否可以通过 this.$emit('update:todos', keyObject)
连接 this.todos.id
?代码更新:codesandbox.io/s/boring-meninsky-jywtq 添加 id
增量 Child2.vue
``` if (this.todos.length > 0) ..here.. ``
你可以在获取数组时发出一个事件,我更新我的答案和代码框链接
刚刚看到您的代码。从未见过$set
,但现在我知道如何使用了。非常感谢你的帮助。我很感激。【参考方案2】:
根据我对您的问题的理解,您希望从子组件更新道具的值。
为此,您可能希望将更改从子组件发送回父组件。
以下是这样做的一种方法:
在您的子组件中:
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
我希望它有所帮助。祝你好运!
【讨论】:
非常感谢。我从未使用过concat
,但现在我知道如何使用它了:)【参考方案3】:
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>
【讨论】:
非常感谢。并感谢您的想法。我实际上有麻烦。this.target.id = this.todos.length+1
对我来说还不够。删除某些项目并重新加载页面时,最大的 id
数字和 todos.length
并不总是相同的。在这种情况下,如果添加新项目,则会发生错误。我想根据最大的target.id
递增。有可能吗?
是的,我的代码就是这样做的,请参阅 App.vue 中的 created() 部分,刷新时它总是从 localStorage 获取当前长度并将其增加 1以上是关于如何使用 Vue JS 在子组件中保留数字和增量?的主要内容,如果未能解决你的问题,请参考以下文章
Vue.js 父子组件,为啥我的 prop 在子组件中还没有?