在计算属性中使用条件逻辑无法更新

时间:2017-03-15 12:31:53

标签: javascript vue.js vuejs2

我有两个小提琴:AB(使用Vuejs 2.2.4)

我有一个可以通过编程方式更改的计算属性(我使用getset方法)。

期望

  1. 如果默认参数更改(this.message),则必须更改计算属性(computedMessage)(默认行为)。

  2. 如果辅助参数发生更改(this.messageProxy),则只有计算属性必须反映辅助参数。

  3. 小提琴A按预期工作,但小提琴B没有。

    错误:辅助参数更改后,默认行为(第1点)停止。

    fiddles之间的唯一区别是计算属性中的console语句。

    背景:我试图以编程方式设置computed属性。 computed属性设置如下:

    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
      }
    }
    

    这允许我设置computedMessage的值,如:

    this.computedMessage = 'some string'
    

    如果这些行:

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

    将替换为:

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

    然后computedMessage在设置this.message时无法再访问this.messageProxy

    通过将this.messageProxy设置为null,我确保

    computedMessage = this.messageProxy
    

    仅在进行作业时才会进行。

2 个答案:

答案 0 :(得分:2)

返回语句中对this.message的引用不会触发computedMessage更新。这是因为它在逻辑||语句中的位置使其无法访问。它是Vue.js Computed Properties Documentation中记录的问题。

来自文档:

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

解决方法是显式访问依赖项:

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

因此,在您的示例中添加对this.message的引用:

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

您的第一个小提琴按预期工作的原因是因为console.log调用this.message作为参数。

答案 1 :(得分:1)

您的代码的实际问题是您正在更改get函数中的数据值,它们是触发重新计算get函数的数据值。不要这样做。 get应该只根据其他值计算一个值。在这种情况下,它应该是

    get () {
      console.log(this.messageProxy, this.message);
      return this.messageProxy || this.message;
    },

无论有没有console消息,它都会按预期执行。

重新检查了您的期望后,我发现只要默认消息发生更改,您就希望清除覆盖。您可以使用其他watch

执行此操作



var demo = new Vue({
  el: '#demo',
  data() {
    return {
      message: 'I am a great guy',
      messageProxy: null,
      someText: ''
    }
  },
  computed: {
    computedMessage: {
      get() {
        return this.messageProxy || this.message
      },
      set(val) {
        this.messageProxy = val
      }
    }
  },
  methods: {
    overrideComputed() {
      this.computedMessage = this.someText
    }
  },
  watch: {
    message: function() {
      this.messageProxy = null;
    }
  }
})

div {
  margin: 5px;
}

<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.min.js"></script>
<div id="demo">
  <p>This message must reflect value of input1</p>
  <div>
    {{ computedMessage }}
  </div>

  input1: <input type="text" v-model='message'>

  <div>
    <p>This will cause computed message to reflect input2</p>
    input2: <input type="text" v-model='someText'>
    <button @click='overrideComputed'>Override</button>
  </div>
</div>
&#13;
&#13;
&#13;

PS:你真的不需要这里计算的可设置表。您可以overrideComputed直接设置messageProxy