Vue: sometime need force update, eg: use filter with moment.formNow() format time

Created on 15 Jun 2016  路  7Comments  路  Source: vuejs/vue

I have not find the optimal way do it.

It's my solution now:

filter

    Vue.filter('fromNow',function(v){
        return moment(v).fromNow()
    })

data.alarms

function generateData() {
        var re = []
        _.forEach(_.range(10), function (v) {
            re.push({name: '婊ㄦ睙瑗胯矾30' + v, time: new Date(Date.now() - v * 1000*30), flag: v % 2 == 0 ? 1 : 2})
        })
        return re;
}

force update

 ready(){
            var ts=this,flag=true;
            ts.$intervalTime=setInterval(function(){
                _.forEach(ts.alarms,function(v){
                    v.time= moment(v.time).add(flag?-1:1,'ms')
                })
                flag=!!flag
            },30*1000)
        },
        destroy(){
           if(this.$intervalTime)clearInterval(this.$intervalTime)
}

It's so bad implementation

All 7 comments

You could use a directive, instead of filter. Check my gist here:
https://gist.github.com/pespantelis/cdf42a52e5bb8ee095a08abdb58c8edf

Hope it helps!

Please ask these questions on forum or Gitter.

@pespantelis
thanks!

there are better then my solution, but it's Hack solution

if want use another {{...}} in tag, it will not work correct

You could try this:

<span>
  Member Since <span v-moment-ago="timestamp"><span>
</span>

instead of this:

<span>
  Member Since {{ timestamp | momentAgo }}
</span>

http://codepen.io/pespantelis/pen/oLLLMP

@pespantelis
Thank you

I'm worried about if have many data to show, there are many setInterval run, may be lead to performance problems

@pespantelis

I have update you solution, It's only one setInterval now

import Vue from 'vue'
import moment from 'moment'



Vue.directive('moment-ago', {
  update (time) {
    this.el.innerHTML = moment(time).fromNow()

    //only register once
    if(!this.$momentAgoKey){
      this.$momentAgoKey=''+keyGenerate++
      funs[this.$momentAgoKey]= () => {
        this.el.innerHTML = moment(time).fromNow()
      }
      runAutoUpdate()
    }

  },

  unbind () {
    stopAutoUpdate(this.$momentAgoKey)
  }
})

var intervalTimes= 0,keyGenerate=1,funs={}
function runAutoUpdate(){
  if(intervalTimes!=0)return //only run once
  console.info('moment run')
  intervalTimes=setInterval(function(){
    for(var key in funs){
      funs[key]();
    }
  },1000)
}

function stopAutoUpdate(key){
  if(!key)return
  delete funs[key]
  if(isEmptyObj(funs)){
    clearInterval(intervalTimes)
    intervalTimes=0
  }

}

function isEmptyObj(obj){
  for(var key in obj){
    return false;
  }
  return true;
}

@pespantelis

But still have problem, if use vue-router and setting keep-alive mode, inactive component still keep update

Was this page helpful?
0 / 5 - 0 ratings