VueJS Reminder App 和独立更新数据数组项
VueJS Reminder App and Update data array items independently
这是我关于 VueJS 的第二个问题。我会把我的问题分成两部分。
1.为什么 VueJS 方法不断被调用或 运行 在循环中?
我认为 startTimer() 将在加载时被调用一次。每当我在数组中推送新提醒时,都会不断调用并冻结浏览器。我想我不了解 VueJS 中的方法,谁能详细说明一下?
2。如何为数据数组 (items) 中的单个列表项更新 timer/counter?
为了跟踪计时器和计数器,我在数据数组(项)中创建了元素,如您在代码笔中所见。
<div id="reminders">
<form v-on:submit.prevent="addReminder">
<label for="new-reminder">Reminder</label>
<input v-model="newReminder" type="text" id="new-reminder" placeholder="Feed the cat">
<label for="new-timer">Time</label>
<input v-model="newTimer" type="number" id="new-timer" placeholder="Time in minute">
<button>Add</button>
</form>
<ul>
<li v-for="item,index in items" class="reminder" v-bind:id='"reminder_"+item.id' v-bind:load="startTimer(index)">
{{ item.id }}<span class="title">{{ item.title }}</span>
TIMER: <span class="time">{{ item.time }}</span><br>
COUNTER:<span class="counter">{{ item.counter }}</span><br>
<button class="close" v-on:click="removeReminder(index)"><img src="https://image.flaticon.com/icons/svg/53/53804.svg" alt=""></button>
</li>
</ul>
</div>
var reminder = new Vue({
el: '#reminders',
data: {
newReminder: '',
newTimer: 0,
items: []
},
methods: {
addReminder: function() {
this.items.push({
id: this.items.length,
title: this.newReminder,
time: this.newTimer,
counter:0
})
},
removeReminder: function(index) {
this.items.splice(index, 1);
},
startTimer: function(index) {
if(this.items[index].counter<100)this.items[index].counter++; // if I don't do this. browser will freez and crash after sometime
console.log(this.items[index].counter);
}
}
});
带定时器和计数器的替代代码 -
var reminder = new Vue({
el: '#reminders',
data: {
newReminder: '',
newTimer: 0,
items: []
},
methods: {
addReminder: function() {
this.items.push({
id: this.items.length,
title: this.newReminder,
time: this.newTimer,
counter:0
})
},
removeReminder: function(index) {
this.items.splice(index, 1);
},
startTimer: function(index) {
let item = this.items[index];
let t = 0;
function timeout() {
setTimeout(function() {
if (t == item.time * 60) {
$('#' + index).find('.title').css('text-decoration', 'line-through');
} else {
timeout();
item.counter = t++;
$('#' + index).find('.counter').text(item.time * 60 - item.counter);
}
}, 1000);
}
timeout();
}
}
});
我不认为我们可以使用 v-bind:load 在元素挂载到 dom 时触发。您可以通过删除 v-bind:load 来修复,但会触发 addTimer 方法中的 this.startTimer(this.items.length - 1)。
你应该 Vue.set(this.items, index, counter++);
因此,我根据@Dat Tran 的建议修改代码并稍作修改,从而解决了我的示例,并且成功了。任何正在研究这个问题的人,这个解决方案可能对他们有用。
var reminder = new Vue({
el: '#reminders',
data: {
newReminder: '',
newTime: 0,
items: []
},
methods: {
addReminder: function() {
let reminder = {
id: this.items.length,
title: this.newReminder,
time: this.newTime,
counter:0
};
Vue.set(this.items,this.items.length,reminder);
this.startTimer(this.items.length-1);
},
removeReminder: function(index) {
this.items.splice(index, 1);
},
startTimer: function(index) {
setTimeout(()=> {
console.log(this.items);
if ( this.items[index].counter == parseInt(this.items[index].time)*60) {
$('#reminder_' + index).find('.title').css('text-decoration', 'line-through');
} else {
this.startTimer(index);
this.items[index].counter++;
console.log(this.items[index].counter);
$('#reminder_' + index).find('.counter').text(this.items[index].time * 60 - this.items[index].counter);
}
}, 1000);
}
}
});
这是我关于 VueJS 的第二个问题。我会把我的问题分成两部分。
1.为什么 VueJS 方法不断被调用或 运行 在循环中? 我认为 startTimer() 将在加载时被调用一次。每当我在数组中推送新提醒时,都会不断调用并冻结浏览器。我想我不了解 VueJS 中的方法,谁能详细说明一下?
2。如何为数据数组 (items) 中的单个列表项更新 timer/counter? 为了跟踪计时器和计数器,我在数据数组(项)中创建了元素,如您在代码笔中所见。
<div id="reminders">
<form v-on:submit.prevent="addReminder">
<label for="new-reminder">Reminder</label>
<input v-model="newReminder" type="text" id="new-reminder" placeholder="Feed the cat">
<label for="new-timer">Time</label>
<input v-model="newTimer" type="number" id="new-timer" placeholder="Time in minute">
<button>Add</button>
</form>
<ul>
<li v-for="item,index in items" class="reminder" v-bind:id='"reminder_"+item.id' v-bind:load="startTimer(index)">
{{ item.id }}<span class="title">{{ item.title }}</span>
TIMER: <span class="time">{{ item.time }}</span><br>
COUNTER:<span class="counter">{{ item.counter }}</span><br>
<button class="close" v-on:click="removeReminder(index)"><img src="https://image.flaticon.com/icons/svg/53/53804.svg" alt=""></button>
</li>
</ul>
</div>
var reminder = new Vue({
el: '#reminders',
data: {
newReminder: '',
newTimer: 0,
items: []
},
methods: {
addReminder: function() {
this.items.push({
id: this.items.length,
title: this.newReminder,
time: this.newTimer,
counter:0
})
},
removeReminder: function(index) {
this.items.splice(index, 1);
},
startTimer: function(index) {
if(this.items[index].counter<100)this.items[index].counter++; // if I don't do this. browser will freez and crash after sometime
console.log(this.items[index].counter);
}
}
});
带定时器和计数器的替代代码 -
var reminder = new Vue({
el: '#reminders',
data: {
newReminder: '',
newTimer: 0,
items: []
},
methods: {
addReminder: function() {
this.items.push({
id: this.items.length,
title: this.newReminder,
time: this.newTimer,
counter:0
})
},
removeReminder: function(index) {
this.items.splice(index, 1);
},
startTimer: function(index) {
let item = this.items[index];
let t = 0;
function timeout() {
setTimeout(function() {
if (t == item.time * 60) {
$('#' + index).find('.title').css('text-decoration', 'line-through');
} else {
timeout();
item.counter = t++;
$('#' + index).find('.counter').text(item.time * 60 - item.counter);
}
}, 1000);
}
timeout();
}
}
});
我不认为我们可以使用 v-bind:load 在元素挂载到 dom 时触发。您可以通过删除 v-bind:load 来修复,但会触发 addTimer 方法中的 this.startTimer(this.items.length - 1)。
你应该 Vue.set(this.items, index, counter++);
因此,我根据@Dat Tran 的建议修改代码并稍作修改,从而解决了我的示例,并且成功了。任何正在研究这个问题的人,这个解决方案可能对他们有用。
var reminder = new Vue({
el: '#reminders',
data: {
newReminder: '',
newTime: 0,
items: []
},
methods: {
addReminder: function() {
let reminder = {
id: this.items.length,
title: this.newReminder,
time: this.newTime,
counter:0
};
Vue.set(this.items,this.items.length,reminder);
this.startTimer(this.items.length-1);
},
removeReminder: function(index) {
this.items.splice(index, 1);
},
startTimer: function(index) {
setTimeout(()=> {
console.log(this.items);
if ( this.items[index].counter == parseInt(this.items[index].time)*60) {
$('#reminder_' + index).find('.title').css('text-decoration', 'line-through');
} else {
this.startTimer(index);
this.items[index].counter++;
console.log(this.items[index].counter);
$('#reminder_' + index).find('.counter').text(this.items[index].time * 60 - this.items[index].counter);
}
}, 1000);
}
}
});