VueJS Reminder App和独立更新数据数组项

时间:2018-08-02 10:27:02

标签: methods vue.js settimeout reminders

这是我与VueJS有关的第二个问题。我将问题分为两部分。

1。为什么VueJS方法不断被调用或在循环中运行?      我认为startTimer()将在加载时被调用一次。每当我在数组中推送新的提醒时,它就会不断被调用并冻结浏览器。我想我不了解VueJS中的方法,谁能详细阐述?

2。如何更新数据数组(项目)中单个列表项目的计时器/计数器?      为了跟踪计时器和计数器,我在代码笔中看到了在数据数组(项目)中创建的元素。

Codepen

<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();
        }
    }
}); 

2 个答案:

答案 0 :(得分:1)

  1. 我认为当元素安装到dom时,我们不能使用 v-bind:load 来触发。您可以通过删除v-bind:load来解决问题,但可以在addTimer方法内触发 this.startTimer(this.items.length-1)

  2. 您应该使用Vue.set(this.items,index,counter ++);

https://vuejs.org/v2/api/#Vue-set

答案 1 :(得分:1)

因此,我通过按照@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);  
        }
    }
});