在输入失去焦点之前,VueJS 中的计算道具不会更新

Posted

技术标签:

【中文标题】在输入失去焦点之前,VueJS 中的计算道具不会更新【英文标题】:Computed prop in VueJS not updated until input lost focus 【发布时间】: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 中的字段,然后您可以根据需要进行修改。就像你已经对其中一些做的那样。 再次感谢您。如果您愿意,请将您的评论作为答案发布,我会检查它是否为正确答案。我认为这是对我的问题最有帮助的评论...我会尝试重构我的数据以不在计算属性中设置任何内容...再次感谢! 【参考方案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.");
   
 );

【讨论】:

谢谢!您可以检查编辑以推荐最佳方法吗?

以上是关于在输入失去焦点之前,VueJS 中的计算道具不会更新的主要内容,如果未能解决你的问题,请参考以下文章

更改为多行后文本输入失去焦点

Safari(移动)IOS - 单击外部时输入不会失去焦点

在输入之外单击时,RN TextInput 不会失去焦点并隐藏它的键盘

React - 以动态形式输入 1 个字符后输入失去焦点

在焦点 jquery 上将占位符输入类型文本更改为密码

如何用js改变平板电脑的输入焦点?