Vuejs:检测计算值上的更改事件

时间:2016-12-02 15:08:58

标签: javascript vue.js

目标

我想检测更改事件searchTerms

问题

观察者目前在每个按键上触发,但我不想要那么多事件。

上下文(View Fiddle

<template>
<div id="app">
  <table class="table">
    <tr>
      <td><label>Name</label></td>
      <td><input class="form-control" v-model="customer.name" autofocus></td>
    </tr>
    <tr>
      <td><label>Short Code</label></td>
      <td><input class="form-control" v-model="customer.shortCode"></td>
    </tr>
    <tr>
      <td><label>Address</label></td>
      <td><input class="form-control" v-model="customer.address"></td>
    </tr>
    <tr>
      <td><label>Caller</label></td>
      <td><input class="form-control" v-model="customer.caller"></td>
    </tr>
    <tr>
      <td><label>Phone</label></td>
      <td><input class="form-control" v-model="customer.phone"></td>
    </tr>
  </table>

  <div class="models">
    <pre><strong>customer:</strong> {{ customer | json }}</pre>
    <pre><strong>searchTerms:</strong> {{ searchTerms | json }}</pre>
  </div>
</div>
</template>

<script>
new Vue({
  el: '#app',
  data: {
    customer: {
      name: 'Donnie',
      phone: '',
      caller: '',
      address: '',
      shortCode: 'DO'
    }
  },

  computed: {
    searchTerms: function() {
      let terms = {};

      _.forOwn(this.customer, (value, key) => {
        if (value.length >= 3) {
          terms[key] = value;
        }
      });

      return terms;
    }
  },

  watch: {
    'searchTerms': function() {
      if (_.isEmpty(this.searchTerms)) {
        return;
      }

      alert('searchTerms Changed');
    }
  }
});
</script>

3 个答案:

答案 0 :(得分:0)

您可以debounce使用lodash,由here提供。它创建一个去抖动函数,该函数延迟调用func直到自上次调用去抖动函数后经过等待毫秒之后。 Debouncing用于限制我们执行Ajax请求和其他昂贵操作的频率

您可以通过单独的方法添加您不想调用的内容,并在_.debounce内调用这些操作,如下所示:

  methods: {
    // This is where the debounce actually belongs.
    expensiveOperation: _.debounce(function () {
      this.isCalculating = true
      setTimeout(function () {
                alert('searchTerms Changed');
      }.bind(this), 1000)
    }, 500)
  }

您可以根据要求更改setTimeout中的延迟。

查找更新的小提琴{{3}}。

答案 1 :(得分:0)

计算属性searchTerms每次运行时都会创建一个新对象。这意味着对searchTerms的引用发生了变化,导致观察者触发。

如果其中一个发生了变化,您只希望触发观察者。最简单的方法是观察searchTerms的字符串化版本,而不是对象。

这是更新的小提琴:https://jsfiddle.net/qLzu0seq/5/

以下是代码作为代码段(将代码保留在stackoverflow中,而不是外部站点,这很好):

&#13;
&#13;
new Vue({
  el: '#app',
  data: {
    customer: {
      name: 'Donnie',
      phone: '',
      caller: '',
      address: '',
      shortCode: 'DO'
    }
  },

  computed: {
    searchTerms: function() {
      let terms = {};

      _.forOwn(this.customer, (value, key) => {
        if (value.length >= 3) {
          terms[key] = value;
        }
      });

      return terms;
    },
    searchTermsStringified: function() {
    	return JSON.stringify(this.searchTerms);
    }
  },

  watch: {
    'searchTermsStringified': function() {
      if (_.isEmpty(this.searchTerms)) {
        return;
      }

      alert('searchTerms Changed');
    }
  }
});
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.js"></script>

<div id="app">
  <table class="table">
    <tr>
      <td><label>Name</label></td>
      <td><input class="form-control" v-model="customer.name" autofocus></td>
    </tr>
    <tr>
      <td><label>Short Code</label></td>
      <td><input class="form-control" v-model="customer.shortCode"></td>
    </tr>
    <tr>
      <td><label>Address</label></td>
      <td><input class="form-control" v-model="customer.address"></td>
    </tr>
    <tr>
      <td><label>Caller</label></td>
      <td><input class="form-control" v-model="customer.caller"></td>
    </tr>
    <tr>
      <td><label>Phone</label></td>
      <td><input class="form-control" v-model="customer.phone"></td>
    </tr>
  </table>

  <div class="models">
    <pre><strong>customer:</strong> {{ JSON.stringify(customer,null,2) }}</pre>
    <pre><strong>searchTerms:</strong> {{ JSON.stringify(searchTerms,null,2) }}</pre>
  </div>
</div>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

您可以直接在计算属性函数中检查值是否已更改 由于要生成对象,因此需要使用_.isEqual方法来测试值是否已更改。您还需要存储以前的值进行比较。

new Vue({
  el: '#app',
  data: {
    customer: {
      name: 'Donnie',
      phone: '',
      caller: '',
      address: '',
      shortCode: 'DO'
    },
    previousSearchTerms: null
  },

  computed: {
    searchTerms: function() {
        let terms = {};

        _.forOwn(this.customer, (value, key) => {
            if (value.length >= 3) {
            terms[key] = value;
            }
        });

        if (this.previousSearchTerms && !_.isEqual(terms, this.previousSearchTerms)) {
            alert('I was changed !');
        }

        this.previousSearchTerms = terms;
        return terms;
    }
  }
});
label { font-weight: bold; }

.models {
  background: #eee;
  margin: 1rem;
  padding: 1rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.min.css" />


<div id="app">
  <table class="table">
    <tr>
      <td><label>Name</label></td>
      <td><input class="form-control" v-model="customer.name" autofocus></td>
    </tr>
    <tr>
      <td><label>Short Code</label></td>
      <td><input class="form-control" v-model="customer.shortCode"></td>
    </tr>
    <tr>
      <td><label>Address</label></td>
      <td><input class="form-control" v-model="customer.address"></td>
    </tr>
    <tr>
      <td><label>Caller</label></td>
      <td><input class="form-control" v-model="customer.caller"></td>
    </tr>
    <tr>
      <td><label>Phone</label></td>
      <td><input class="form-control" v-model="customer.phone"></td>
    </tr>
  </table>

  <div class="models">
    <pre><strong>customer:</strong> {{ customer | json }}</pre>
    <pre><strong>searchTerms:</strong> {{ searchTerms | json }}</pre>
  </div>
</div>

<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.12/vue.js"></script>