[英]Vue.js - watch particular properties of the object and load data on change
我有一個名為product
的 Vue 組件,它是一個具有一堆屬性的 object。 而且它經常變化。
export default {
props: {
product: {
type: Object,
default: () => {},
},
},
watch: {
'product.p1'() {
this.loadData()
},
'product.p2'() {
this.loadData()
},
},
methods: {
loadData() {
doApiRequest(this.product.p1, this.product.p2)
}
},
}
當僅更改product
的屬性p1
和p2
時,組件應加載新數據。 一種方法是觀察整個產品並在更改時加載數據。 但它會產生不必要的請求,因為p1
和p2
可能沒有改變。
另一個想法是觀察product.p1
和product.p2
,並調用相同的 function 以在每個觀察者中加載數據。 但是在新版本的產品中可能會發生p1
和p2
都發生變化的情況,它會觸發 2 次調用。
使用去抖動的 function 進行數據加載會是一個很好的解決方案嗎?
或者更確切地說,對整個product
使用單個觀察程序,並將新的p1
和p2
字符串化與其舊的字符串化版本進行比較,以確定是否應該觸發數據加載?
有幾種方法可以解決這個問題,每種方法都有優點和缺點。
我采用的一種簡單方法是使用 watch 函數訪問您想要監視的每個屬性,然后返回一個新的空對象。 Vue 知道在 watch 函數中訪問了product.p1
和product.p2
,因此它會在這些屬性中的任何一個發生更改時重新執行它。 然后,通過從 watch 函數返回一個新的空對象實例,Vue 將觸發 watch 處理程序,因為 watch 函數返回了一個新值(因此正在監視的內容“已更改”)。
created() {
this.$watch(() => {
// Touch the properties we want to watch
this.product.p1;
this.product.p2;
// Return a new value so Vue calls the handler when
// this function is re-executed
return {};
}, () => {
// p1 or p2 changed
})
}
優點:
缺點:
p1
和p2
的先前值。this.product
是否可能為空/未定義。p1
或p2
改變時,它總是會觸發; 即使p1
和p2
在下一個微任務(即$nextTick()
)之前被設置回它們以前的值; 但這在大多數情況下不太可能成為問題。this.$watch()
。 如果您想改用watch
選項,則需要監視計算屬性。無論如何,其中一些缺點適用於其他方法。
更緊湊的版本是:
this.$watch(
() => (this.product.p1, this.product.p2, {}),
() => {
// changed
}
})
正如其他一些開發人員所說,您可以使用計算屬性來監視product.p1
或product.p2
或兩者的變化,然后在每種情況下只調用一次loadData()
方法。 這是一個假設的product.vue
組件的代碼:
<template> <div> this is product compo </div> </template> <script> export default { name: "product", watch: { p1p2: function(newVal, oldVal) { this.loadData(); } }, props: { productProp: { type: Object, default: () => {}, }, }, computed: { p1p2: function() { return this.productProp.p1 + this.productProp.p2; } }, methods: { loadData() { console.log("load data method"); } }, } </script>
我將它收到的 prop 重命名為productProp並在其中觀察了一個名為p1p2
的計算屬性。 我認為數據的值是字符串格式(但如果不是,您可以轉換它們)。 實際上p1p2是productProp.p1
和productProp.p2
的串聯。 因此,更改其中一個或兩個可能會觸發loadData()方法。 這是將數據傳遞給product.vue
的父組件的代碼:
<template> <section> <product :productProp = "dataObj"></product> <div class="d-flex justify-space-between mt-4"> <v-btn @click="changeP1()">change p1</v-btn> <v-btn @click="changeP2()">change p2</v-btn> <v-btn @click="changeBoth()">change both</v-btn> <v-btn @click="changeOthers()">change others</v-btn> </div> </section> </template> <script> import product from "../components/product"; export default { name: 'parentCompo', data () { return { dataObj: { p1: "name1", p2: "name2", p3: "name3", p4: "name4" } } }, components: { product }, methods: { changeP1: function() { if (this.dataObj.p1 == "name1") { this.dataObj.p1 = "product1" } else { this.dataObj.p1 = "name1" } }, changeP2: function() { if (this.dataObj.p2 == "name2") { this.dataObj.p2 = "product2" } else { this.dataObj.p2 = "name2" } }, changeBoth: function() { if (this.dataObj.p2 == "name2") { this.dataObj.p2 = "product2" } else { this.dataObj.p2 = "name2" } if (this.dataObj.p1 == "name1") { this.dataObj.p1 = "product1" } else { this.dataObj.p1 = "name1" } }, changeOthers: function() { if (this.dataObj.p3 == "name3") { this.dataObj.p3 = "product3" } else { this.dataObj.p3 = "name3" } } }, } </script>
您可以通過更改dataObj.p1
或dataObj.p2
或兩者來測試更改按鈕以查看loadData()方法只調用一次,而通過更改其他方法則不會調用它。
數據(){返回{
model: {},
error_message: [],
}
},
watch: {
'model.EmailAddress'(value) {
// binding this to the data value in the email input
this.model.EmailAddress = value;
this.validateEmail(value);
},
},
methods: {
validateEmail(value) {
if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(value)) {
this.error_message['EmailAddress'] = '';
} else {
this.error_message['EmailAddress'] = 'Invalid Email Address';
}
}
},
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.