admin管理员组文章数量:1430701
Goal
I want to detect only a change event to searchTerms
.
Problem
The watcher currently triggers on each keypress, but I don't want that many events.
Context (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'
}
},
puted: {
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>
Goal
I want to detect only a change event to searchTerms
.
Problem
The watcher currently triggers on each keypress, but I don't want that many events.
Context (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'
}
},
puted: {
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>
Share
Improve this question
edited Dec 2, 2016 at 16:25
Donnie
asked Dec 2, 2016 at 15:08
DonnieDonnie
6,35110 gold badges38 silver badges55 bronze badges
3 Answers
Reset to default 0The puted property searchTerms
creates a new object every time it runs. This means that the reference to searchTerms
changes, causing the watcher to fire.
You only want the watcher to fire if one of the values has changed. The easiest way to do this is to watch a stringified version of searchTerms
, rather than the object.
Here is the updated fiddle: https://jsfiddle/qLzu0seq/5/
And here is the code as a snippet (it's nice to keep code in stackoverflow, rather than an external site):
new Vue({
el: '#app',
data: {
customer: {
name: 'Donnie',
phone: '',
caller: '',
address: '',
shortCode: 'DO'
}
},
puted: {
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');
}
}
});
<script src="https://cdnjs.cloudflare./ajax/libs/vue/2.1.4/vue.js"></script>
<script src="https://cdnjs.cloudflare./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>
You can check if the value has changed directly in the puted property function.
Since you are generating objects you need to use _.isEqual
method in order to test if the value has changed. You will also need to store the previous value for parison.
new Vue({
el: '#app',
data: {
customer: {
name: 'Donnie',
phone: '',
caller: '',
address: '',
shortCode: 'DO'
},
previousSearchTerms: null
},
puted: {
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./ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare./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./ajax/libs/vue/1.0.12/vue.js"></script>
You can use debounce for this, which is provided by lodash. It Creates a debounced function that delays invoking func until after wait milliseconds have elapsed since the last time the debounced function was invoked. Debouncing is used to limit how often we execute Ajax requests and other expensive operations
You can add the things you want to not call that often in a separate method, and call those actions inside a _.debounce
, like following:
methods: {
// This is where the debounce actually belongs.
expensiveOperation: _.debounce(function () {
this.isCalculating = true
setTimeout(function () {
alert('searchTerms Changed');
}.bind(this), 1000)
}, 500)
}
You can change the delay in setTimeout
as par your requirement.
Find updated fiddle here.
本文标签: javascriptVuejs Detect Change Event On Computed ValueStack Overflow
版权声明:本文标题:javascript - Vuejs: Detect Change Event On Computed Value - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745528522a2661952.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论