簡體   English   中英

Vue.js - 觀察 object 的特定屬性並在更改時加載數據

[英]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的屬性p1p2時,組件應加載新數據。 一種方法是觀察整個產品並在更改時加載數據。 但它會產生不必要的請求,因為p1p2可能沒有改變。

另一個想法是觀察product.p1product.p2 ,並調用相同的 function 以在每個觀察者中加載數據。 但是在新版本的產品中可能會發生p1p2都發生變化的情況,它會觸發 2 次調用。

使用去抖動的 function 進行數據加載會是一個很好的解決方案嗎?

或者更確切地說,對整個product使用單個觀察程序,並將新的p1p2字符串化與其舊的字符串化版本進行比較,以確定是否應該觸發數據加載?

有幾種方法可以解決這個問題,每種方法都有優點和缺點。

我采用的一種簡單方法是使用 watch 函數訪問您想要監視的每個屬性,然后返回一個新的空對象。 Vue 知道在 watch 函數中訪問了product.p1product.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
  })
}

優點:

  • 您不必對任何內容進行字符串化。
  • 您不必去抖動監視處理程序函數。

缺點:

  • 您無法跟蹤p1p2的先前值。
  • 請注意this.product是否可能為空/未定義。
  • p1p2改變時,它總是會觸發; 即使p1p2在下一個微任務(即$nextTick() )之前被設置回它們以前的值; 但這在大多數情況下不太可能成為問題。
  • 您需要使用this.$watch() 如果您想改用watch選項,則需要監視計算屬性。

無論如何,其中一些缺點適用於其他方法。

更緊湊的版本是:

this.$watch(
  () => (this.product.p1, this.product.p2, {}),
  () => {
    // changed
  }
})

正如其他一些開發人員所說,您可以使用計算屬性來監視product.p1product.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的計算屬性。 我認為數據的值是字符串格式(但如果不是,您可以轉換它們)。 實際上p1p2productProp.p1productProp.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.p1dataObj.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM