Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using conditional logic in computed properties fails to update

I have two fiddles: A, B (using Vuejs 2.2.4)

I have a computed property which can be changed programmatically (I am using the get and set methods).

Expectations:

  1. If the default parameter changes (this.message), the computed property (computedMessage) must change (default behaviour).

  2. If the secondary parameter changes (this.messageProxy), only then the computed property must reflect the secondary parameter.

Fiddle A works as expected but Fiddle B doesn't.

Error: The default behaviour (point 1) stops after the secondary parameter changes.

The only difference between the fiddles is a console statement in the computed property.


Background: I was trying to set a computed property programatically. The computed property is set like:

computedMessage: {
  get () {
    let messageProxy = this.messageProxy
    this.messageProxy = null
    console.log(messageProxy, this.messageProxy, this.message)
    return messageProxy || this.message
  },
  set (val) {
    this.messageProxy = val
  }
}

This allows me to set the value of computedMessage like:

this.computedMessage = 'some string'

If these lines:

get () {
  let messageProxy = this.messageProxy
  this.messageProxy = null
  return messageProxy || this.message
}

were to be replaced with:

get () {
  return this.messageProxy || this.message
}

then computedMessage can no longer get access to this.message the moment this.messageProxy is set.

By setting this.messageProxy to null I ensure that the

computedMessage = this.messageProxy

only if an assignment is made.

like image 321
Amresh Venugopal Avatar asked Mar 15 '17 12:03

Amresh Venugopal


1 Answers

The reference to this.message in the return statement isn't triggering computedMessage to update. This is because its location in the logical || statement makes it inaccessible. It's a gotcha documented in the Vue.js Computed Properties Documentation.

From the Docs:

status: function () {
    return this.validated
        ? this.okMsg
        : this.errMsg // errMsg isn't accessible; won't trigger updates to status
}

The workaround is to explicitly access dependencies:

status: function () {
    // access dependencies explicitly
    this.okMsg
    this.errMsg
    return this.validated
        ? this.okMsg
        : this.errMsg
}

So in your example add a reference to this.message:

get() {
  this.message
  let messageProxy = this.messageProxy
  this.messageProxy = null
  return messageProxy || this.message
}

The reason your first fiddle was working as expected was because the console.log call had this.message as a parameter.

like image 76
thanksd Avatar answered Oct 14 '22 13:10

thanksd