-
Notifications
You must be signed in to change notification settings - Fork 17
Periodically update computed property #214
Comments
How about this way in the future?
|
A function return value is not observable, so directly observing You can include a dummy data property in you computed attribute, that you start changing every minute (or more fine grained) in your ready hook. The computed gets updated because a depending variable has changed:
|
Thanks @nirazul . Is there an easy way to use this mechanism on a v-repeat component? data: {
messages: []
},
components: {
message: {
timestamp: function () {
...
}
}
} |
I suggest approaching this problem by thinking about what is the "data" that actually changes. In this case, the If you want to use it inside a repeat component, put the "now" on the parent and pass it down as a prop. Or, if your components are tightly coupled, you can directly access it as |
thanks @yyx990803. Your suggestion helped me a lot - never used props before. If it is actually tightly coupled, can I still pass the property? I tried it (see example below) and it didn't work. new Vue({
el: '#ts',
data: {
messages: [
{ created_at: Date.now() }
],
now: Date.now()
},
ready: function () {
var self = this;
setInterval(function () {
console.log('updating ticker')
self.$data.now = Date.now()
}, 1000)
},
components: {
message: {
props: [
'now'
],
computed: {
timestamp: function () {
//var now = this.$parent.now // works - although I don't like having an unused variable.
console.log(this.now) // undefined
var zone = window.moment().utcOffset()
var time = window.moment.utc(this.created_at).utcOffset(zone)
var formatted = time.format('HH:mm MMM Do') + ', ' + time.fromNow()
return formatted;
}
}
}
}
}); <div id="ts">
<message v-repeat="messages" inline-template>
{{ timestamp }}
</message>
</div> |
You need to pass the props in the template: <message v-repeat="messages" now="{{now}}" inline-template>
{{ timestamp }}
</message> |
It does pass the property down to the child now, but the child computed property isn't called when the parent is updated - what am I doing wrong? |
Ahh, you found a bug! |
Btw, make sure to clear the interval in your component's |
Awesome, thanks! I decided to integrate your commit into my local vue.js - using an alias vor the v-repeat would break my current structure (the provided example was a minimalistic one). |
If you don't access the variable, the computed prop is not called. Is this the expected behaviour? If so, there would be no benefit passing the prop to the component rather than accessing the parent directly (in this example at least). |
That is the point of a "computed property": it updates when one of its dependency properties has changed. If you don't depend on anything, it never updates. Passing in the prop makes it less "coupled" - that's why I said if your components are coupled by design then it's ok to just directly access |
So what is the best way (in this scenario) to updated the computed property. Assigning it to a variable seems to be the first choice (although I'd rather not have an unused variable lying around). |
Instead of |
Thank a lot master. |
Is there any good way to avoid setting interval in each component for making reactive timer displayed? |
@shtse8 You could use a separate Vue instance as a global event bus and broadcast the time update as a global event, or use VueX's reactive properties and have your Vue components subscribe to the global "now" update with a VueX getter within a computed property. |
@SirLamer I am using VueX as my global reactive properties now, but it's not much perform well once there are no component using the |
I've used the following method described by @yyx990803 Instead of Code <div id="app">
<timer :created="timeCreated"></timer>
</div> Vue.component('timer', {
props: ['created'],
template: '<span>{{ timeFromNow }}</span>',
data () {
return {
timeFromNow: null
}
},
created () {
this.getTimeFromNow()
setInterval(this.getTimeFromNow, 1000)
},
destroyed () {
clearInterval(this.getTimeFromNow)
},
methods: {
getTimeFromNow () {
this.timeFromNow = moment(this.created).fromNow()
}
}
})
new Vue({
el: "#app",
data: {
timeCreated: Date.now()
}
}) Working JSFiddle : https://jsfiddle.net/kasvith/eywraw8t/18473/ @johannes-z hope this helps you and others |
I have a computed property, which formats the timestamp.
time.fromNow()
results in "a few seconds ago", "a minute ago", etc.I want this computed property to update itself every minute (so that you actually have life feedback of the
fromNow
function. Ideas?Computed Property:
The text was updated successfully, but these errors were encountered: