【问题标题】:Using conditional logic in computed properties fails to update在计算属性中使用条件逻辑无法更新
【发布时间】:2017-08-06 04:43:27
【问题描述】:

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

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

期望

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

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

Fiddle A 按预期工作,但 Fiddle B 没有。

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

小提琴之间的唯一区别是计算属性中的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.messageProxy 的那一刻无法再访问this.message

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

computedMessage = this.messageProxy

仅在进行分配时。

【问题讨论】:

  • 控制台语句在哪里?
  • 你应该在fiddle A console.log(messageProxy, this.messageProxy, this.message)找到这个
  • 好的。将来,请在问题本身中包含所有相关代码。 (见minimal reproducible example
  • @evolutionxbox 我按照您的建议进行了编辑。
  • 我不明白你在做什么......

标签: javascript vue.js vuejs2


【解决方案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>

PS:你真的不需要在这里计算一个可设置的。你可以让overrideComputed 直接设置messageProxy

【讨论】:

  • 如果我这样做,我将不再从 getter 中返回 this.message
  • 如果this.messageProxy 为空,您会这样做。
  • 重置this.messageProxy 我有这种特殊的方式,就像在小提琴中一样。如果我在其他任何地方这样做,对this.messageProxy 的依赖不会导致computedMessage 再次运行吗?
  • 除了overrideComputed之外,为什么要重置this.messageProxy
  • 重置是指将值设置为空。如果这也是你的意思,那么我不明白你的评论,你能举个例子吗?
【解决方案2】:

return 语句中对 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 作为参数。

【讨论】:

  • 我也注意到了这一点,我的问题是想知道原因:)
  • @AmreshVenugopal 在文档中找到原因,见编辑
  • 我真的不知道,谢谢!也请编辑您的答案以包含代码的文档部分。
  • @AmreshVenugopal 没问题。但是你是什么意思“代码的记录部分”?
  • 在文档链接中,有一个示例说明仅拥有this.&lt;property&gt; 会将其添加到受监控的依赖项中。您发布的解决方案涉及局部变量,我认为这不是必需的。 (仅供参考)
猜你喜欢
  • 2018-11-25
  • 2018-04-15
  • 2018-09-26
  • 2020-01-25
  • 1970-01-01
  • 2018-01-09
  • 2019-06-18
  • 1970-01-01
  • 2021-09-02
相关资源
最近更新 更多