簡體   English   中英

Vue.js 綁定對象屬性

[英]Vue.js bind object properties

為什么我無法在 Vue 中綁定對象屬性? 對象addr不是立即響應的,但是test是響應的,怎么來的? 在這種情況下,我應該如何綁定它?

HTML

<div id="app">

   <input type="text" id="contactNum" v-model="addr.contactNum" name="contactNum">

   <input type="text" id="test" v-model="test" name="test">
   <br/>
   {{addr}}<br/>
   {{addr.contactNum}}<br/>
   {{test}}
</div>

Javascript

var vm = new Vue({
    el: '#app',
    data: {
      addr: {},
      test: ""
    }
});

提琴手

在初始化期間,Vue 為每個已知屬性設置 getter 和 setter。 由於最初沒有設置contactNum ,因此Vue 不知道該屬性並且無法正確更新它。 這可以通過將contactNum添加到您的addr對象來輕松解決。

var vm = new Vue({
  el: '#app',
  data: {
    addr: {
      contactNum: "" // <-- this one
    },
    test: ""
  }
});

以上在 Vue 中稱為反應性 由於 Vue 不支持向其反應系統動態添加屬性,我們可能需要某種解決方法。 API 提供了一個可能的解決方案 如果是動態添加的屬性,我們可以使用Vue.set(vm.someObject, 'b', 2)

這樣做標記需要得到一些更新。 與其使用v-model ,不如使用像@input這樣的事件監聽器。 在這種情況下,我們的標記可能看起來像這樣。

<input type="text" id="contactNum" @input="update(addr, 'contactNum', $event)" name="contactNum">

所以基本上每次輸入元素值發生變化時都會觸發該函數。 顯然這樣做也需要對 JS 部分進行一些調整。

var vm = new Vue({
  el: '#app',
  data: {
    addr: {},
    test: ""
  },
  methods: {
    update: function(obj, prop, event) {
      Vue.set(obj, prop, event.target.value);
    }
  }
});

由於 Vue 會在任何響應式元素上觸發Vue.set() ,我們只需自己調用它,因為 Vue 不會將動態添加的屬性識別為響應式屬性。 當然,這只是一種可能的解決方案,可能還有很多其他解決方法。 可以在這里看到一個完整的工作示例。

根據我的評論,您需要考慮幾件事:

  • 您的代碼不工作的原因是由於JS 固有地無法觀察對象屬性的變化 這意味着即使addr是響應式的,添加到addr的任何屬性如果在聲明時未完成,都會使其變為非響應式。 有關更多詳細信息,請參閱 VueJS 文檔: https ://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats
  • 如果您要擁有任意數量的輸入字段,您可能最好編寫一個自定義輸入組件,並簡單地使用v-for根據您擁有的輸入字段的數量迭代地注入輸入字段。

現在回到第二點,如果您知道addr將具有哪些字段,您可以簡單地在您的應用程序中聲明它。 我們創建一個新的updateFormData方法,由組件調用:

data: {
  addrFields: ['contactNum', ...],
  addr: {},
  test: ""
},
methods: {
  updateFormData: function(id, value) {
    this.$set(this.addr, id, value);
  }
}

我們仍然可以將您的表單數據存儲在addr對象中,該對象將由updateFormData方法根據接收到的有效負載使用.$set()進行更新。 現在,我們可以為您的輸入元素創建一個自定義 Vue 組件。

在下面的示例中,組件將遍歷您的所有addrFields ,並使用:id="addrField"addrField作為道具傳遞。 我們還想確保我們捕獲從組件內部發出的自定義命名的updated事件。

<my-input
     v-for="(addrField, i) in addrFields"
     :key="i"
     :id="addrField"
     v-on:inputUpdated="updateFormData"></my-input>

該模板可能如下所示。 它只是將id屬性用於其idnameplaceholder屬性(后者便於在演示中識別)。 我們綁定@change@input事件,強制它觸發updated的回調:

<script type="text/template" id="my-input">
    <input
    type="text"
    :id="id"
    :name="id"
    :placeholder="id"
    @input="updated"
    @change="updated">
</script>

在組件邏輯中,您讓它知道它將接收id作為道具,並且應該使用$.emit()發出inputUpdated事件。 我們將 ID 和值作為有效負載附加,以便我們可以通知父級更新了什么:

var myInput = Vue.component('my-input', {
    template: '#my-input',
  props: {
    id: {
        type: String
    }
  },
  methods: {
    updated: function() {
        this.$emit('inputUpdated', this.id, this.$el.value);
    }
  }
});

使用上面的代碼,我們有一個工作示例。 在這種情況下,我創建了一個任意輸入字段數組: contactNumabc

 var myInput = Vue.component('my-input', { template: '#my-input', props: { id: { type: String } }, methods: { updated: function() { this.$emit('updated', this.id, this.$el.value); } } }); var vm = new Vue({ el: '#app', data: { addrFields: ['contactNum', 'a', 'b', 'c'], addr: {}, test: "" }, methods: { updateFormData: function(id, value) { this.$set(this.addr, id, value); } } });
 <script src="https://unpkg.com/vue@2.1.3/dist/vue.js"></script> <div id="app"> <my-input v-for="(addrField, i) in addrFields" :key="i" :id="addrField" v-on:updated="updateFormData"></my-input> <input type="text" id="test" v-model="test" name="test" placeholder="test"> <br/> <strong>addr:</strong> {{addr}}<br/> <strong>addr.contactNum:</strong> {{addr.contactNum}}<br /> <strong>test:</strong> {{test}} </div> <script type="text/template" id="my-input"> <input type="text" :id="id" :name="id" :placeholder="id" @input="updated" @change="updated"> </script>

用這個編輯你的Vue data ,因為它的 getter 和 setter 方法沒有設置。 另外,請在此處查看Vue 文檔中的聲明式反應式渲染

data: {
    addr: {
      contactNum: "" // <-- this one
    },
    test: ""
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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