web-dev-qa-db-ja.com

Vue.jsバインドオブジェクトプロパティ

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: ""
    }
});

Jsfiddle

7
GMsoF

初期化中Vue=既知のすべてのプロパティに対してゲッターとセッターを設定します。contactNumは最初に設定されていないため、Vue contactNumaddrオブジェクトに追加することで簡単に修正できます。

_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

12
Aer0

私のコメントによると、考慮したいことがいくつかあります。

  • コードが機能しない理由は、JSがオブジェクトのプロパティの変更を監視できないという固有の理由によるものです。これは、addrがリアクティブであっても、addrに追加されたプロパティが宣言されたときに実行されないと、非アクティブになります。詳細については、VueJSのドキュメントを参照してください: https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats
  • 任意の数の入力フィールドを使用する場合は、おそらくカスタム入力コンポーネントを構成し、_v-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>
_

テンプレートは次のようになります。 idid、および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);
    }
  }
});
_

上記のコードでは、実際の例があります。この場合、入力フィールドの任意の配列を作成しました:contactNumab、および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>_
4
Terry

これを使用してVuedataを編集します。これはgetterおよびsetterメソッドが設定されていないためです。また、Declarative Reactive Renderingon Vue docs here

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