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=既知のすべてのプロパティに対してゲッターとセッターを設定します。contactNum
は最初に設定されていないため、Vue contactNum
をaddr
オブジェクトに追加することで簡単に修正できます。
_var vm = new Vue({
el: '#app',
data: {
addr: {
contactNum: "" // <-- this one
},
test: ""
}
});
_
上記は、Vueでは反応性と呼ばれます。 Vueは、反応性システムへのプロパティの動的な追加をサポートしていないため、何らかの回避策が必要になる場合があります。APIによって solution が提供されます。 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は動的に追加されたプロパティを認識しないため、独自に呼び出します。もちろん、これは可能な解決策の1つにすぎず、他にも多くの回避策が存在する可能性があります完全に機能する例を見ることができます here 。
私のコメントによると、考慮したいことがいくつかあります。
addr
がリアクティブであっても、addr
に追加されたプロパティが宣言されたときに実行されないと、非アクティブになります。詳細については、VueJSのドキュメントを参照してください: https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveatsv-for
_を使用することをお勧めします持っている入力フィールドの数に基づいて入力フィールドを繰り返し挿入します。2番目のポイントに戻ります。addr
が持つフィールドがわかっている場合は、アプリで宣言するだけです。コンポーネントによって呼び出される新しいupdateFormData
メソッドを作成します。
_data: {
addrFields: ['contactNum', ...],
addr: {},
test: ""
},
methods: {
updateFormData: function(id, value) {
this.$set(this.addr, id, value);
}
}
_
フォームデータはaddr
オブジェクトに保存できます。このオブジェクトは、 .$set()
を使用して、受信したペイロードに基づいてupdateFormData
メソッドによって更新されます。これで、入力要素にカスタム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
propを使用します(後者はデモで簡単に識別できるようにします)。 _@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/[email protected]/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>
_
これを使用してVuedata
を編集します。これはgetterおよびsetterメソッドが設定されていないためです。また、Declarative Reactive Renderingon Vue docs here :
data: {
addr: {
contactNum: "" // <-- this one
},
test: ""
}