【问题标题】:Computed prop in VueJS not updated until input lost focus在输入失去焦点之前,VueJS 中的计算道具不会更新
【发布时间】:2020-04-18 03:39:12
【问题描述】:

和标题一样。对象的计算属性在输入框失去焦点之前不会反应。

但如果对象在数据中,则值在输入中更改后立即更改。

我用示例创建了一个代码笔:https://codepen.io/Albvadi/pen/QWwMOQV

<div id="container">
  <div class="row justify-content-center">
    <div class="col-md-8">
      <div class="card">
        <div class="card-header">Match Component</div>

        <div class="card-body">
          <div class="container">
            <div class="row align-items-center">
              <div class="col-4 text-right">{{homeTeam.desc}}</div>
              <div class="col-2">
                <input class="form-control text-center" type="number" min="0" v-model.number="homeTeam.score" />
              </div>
              <div class="col-2">
                <input class="form-control text-center" type="number" min="0" v-model.number="awayTeam.score" />
              </div>
              <div class="col-4">{{ awayTeam.desc }}</div>
              <div class="row">
                <div class="col">
                  DATA:
                  <b>{{ homeTeam.score }}</b>
                </div>
                <div class="row">
                  <div class="col">
                    COMPUTED:
                    <b>{{ awayTeam.score }}</b>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
new Vue({
  el: "#container",
  data: {
    homeTeam: {
      name: "SPA",
      desc: "Spain",
      score: 0
    }
  },
  computed: {
    awayTeam: function() {
      return {
        name: "GER",
        desc: "Germany",
        score: 0
      };
    },
  },
  mounted() {
    console.log("Component mounted.");
  }
});

如果您更改第一个输入,则数据值会立即更改。 如果更改第二个输入,则计算值仅在输入失去焦点时才更改。

我该如何解决这个问题?

== 编辑 ==

感谢您的回答! 我知道将team放在数据部分可以解决问题,这只是简化我的问题的一个例子。

我的问题是,除了这两个结果之外,我还希望有一个计算属性能够发布到另一个组件。 我用最终结果编辑了 codepen:https://codepen.io/Albvadi/pen/jOELYwN,它工作正常。

但是@Sami Kuhmonen cmets 计算的属性只是读取属性,但在我的checkFinalResult 中,我正在设置computedMatch.. 这是正确的方法吗??

【问题讨论】:

  • 不应更改计算值。它们是根据其他数据计算的,因此是只读的。
  • 谢谢!你能检查我的编辑吗?
  • 你永远不会在计算属性中设置任何东西。这是正确的做法。所以你仍然在做错事。如果您确实需要修改计算数据,那么其中的每个字段都引用data 中的字段,然后您可以根据需要进行修改。就像你已经对其中一些做的那样。
  • 再次感谢您。如果您愿意,请将您的评论作为答案发布,我会检查它是否为正确答案。我认为这是对我的问题最有帮助的评论...我会尝试重构我的数据以不在计算属性中设置任何内容...再次感谢!

标签: javascript vuejs2 computed-properties vue-reactivity


【解决方案1】:

计算属性应被视为只读。每次他们引用的属性发生变化时,它们的值都是从其他值计算出来的,并且所有变化都会丢失(或者至少应该这样认为,可能存在一些值保留的情况)。尽管有时更改它们的属性似乎有效,但这并不能保证,它们可能随时更改。

在 codepen 中,您已经拥有引用对象中其他属性的计算属性,因此您必须添加所有您想要更改的类似内容,然后更改该值。这将导致计算值被重新评估,并且更改将可见并持久化。

请注意,从许多单独的事物中构建计算对象可能不是最高效的方式,它取决于应如何处理它的情况。如果这些值仅在组件中使用,那么直接使用它们很容易,但是如果您需要特定形式的对象并需要它的反应性,那么计算属性可能是要走的路。

【讨论】:

    【解决方案2】:

    在你的情况下,为什么这个计算属性不会立即更新 DOM 元素,因为它没有 data 引用 Vue 实例。在这里,它只返回一些 static 值,这不是 @ 987654325@物业的用途。当您需要根据您的data propertyvue 实例来计算或计算某些决策时,computed property 就派上用场了。

    new Vue({
      el: "#container",
      data: {
        homeTeam: {
          name: "SPA",
          desc: "Spain",
          score: 0
        },
        awayTeam: {
          name: "GER",
          desc: "Spain",
          score: 0
        },
      },
      mounted() {
        console.log("Component mounted.");
      }
    });
    <div id="container">
      <div class="row justify-content-center">
        <div class="col-md-8">
          <div class="card">
            <div class="card-header">Match Component</div>
    
            <div class="card-body">
              <div class="container">
                <div class="row align-items-center">
                  <div class="col-4 text-right">{{homeTeam.desc}}</div>
                  <div class="col-2">
                    <input class="form-control text-center" type="number" min="0" v-model.number="homeTeam.score" />
                  </div>
                  <div class="col-2">
                    <input class="form-control text-center" type="number" min="0" v-model.number="awayTeam.score" />
                  </div>
                  <div class="col-4">{{ awayTeam.desc }}</div>
                  <div class="row">
                    <div class="col">
                      DATA:
                      <b>{{ homeTeam.score }}</b>
                    </div>
                    <div class="row">
                      <div class="col">
                        COMPUTED:
                        <b>{{ awayTeam.score }}</b>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

    【讨论】:

      【解决方案3】:

      为什么你在这个任务中使用计算属性?我会这样做。

        new Vue({
           el: "#container",
           data: {
              homeTeam: {
              name: "SPA",
             desc: "Spain",
             score: 0
           },
          awayTeam:  {
             name: "GER",
             desc: "Germany",
             score: 0
           },
         },
         mounted() {
            console.log("Component mounted.");
         }
       });
      

      【讨论】:

      • 谢谢!您可以检查编辑以推荐最佳方法吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-29
      • 1970-01-01
      • 1970-01-01
      • 2017-09-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多