[英]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 不會將動態添加的屬性識別為響應式屬性。 當然,這只是一種可能的解決方案,可能還有很多其他解決方法。 可以在這里看到一個完整的工作示例。
根據我的評論,您需要考慮幾件事:
addr
是響應式的,添加到addr
的任何屬性如果在聲明時未完成,都會使其變為非響應式。 有關更多詳細信息,請參閱 VueJS 文檔: https ://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveatsv-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
屬性用於其id
、 name
和placeholder
屬性(后者便於在演示中識別)。 我們綁定@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);
}
}
});
使用上面的代碼,我們有一個工作示例。 在這種情況下,我創建了一個任意輸入字段數組: contactNum
、 a
、 b
和c
:
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.