2017-06-12 9 views
2

私は、カスタムコンポーネントでv-model双方向バインディングを1レベル深く実行することができましたが、それを一層深くする必要があります。Vue.js v-modelコンポーネント

現在の作業コード:このように使用

<template lang="html"> 

     <div class="email-edit"> 

     <input ref="email" :value="value.email" @input="updateInput()"/> 
<input ref="body" :value="value.body" @input="updateInput()"/> 

     </div> 

    </template> 
    <script type="text/javascript"> 
     import LineEditor from './LineEditor.vue' 
     export default { 
     components: { 
      LineEditor 
     }, 
     computed: { 
     }, 
     methods: { 
      updateInput: function(){ 
      this.$emit('input',{ 
       email: this.$refs.email.value, 
       body: this.$refs.body.value 
      }) 
      } 
     }, 
     data: function(){ 
      return {} 
     }, 
     props: { 
      value: { 
      default: { 
       email: "", 
       body: "" 
      }, 
      type:Object 
      } 
     } 
     } 
    </script> 

<email-edit-input v-model="emailModel" />

私はこの作品を追加する場合は、値はもはや上向きに伝播しません:

 <div class="email-edit"> 

     <line-editor ref="email" :title="'Email'" :value="value.email" @input="updateInput()"/> 
<input ref="body" :value="value.body" @input="updateInput()"/> 

     </div> 

    </template> 
    <script type="text/javascript"> 
     import LineEditor from './LineEditor.vue' 
     export default { 
     components: { 
      LineEditor 
     }, 
     computed: { 
     }, 
     methods: { 
      updateInput: function(){ 
      this.$emit('input',{ 
       email: this.$refs.email.value, 
       body: this.$refs.body.value 
      }) 
      } 
     }, 
     data: function(){ 
      return {} 
     }, 
     props: { 
      value: { 
      default: { 
       email: "", 
       body: "" 
      }, 
      type:Object 
      } 
     } 
     } 
    </script> 

この第2カスタムコンポーネントの使用:

<template lang="html"> 

    <div class="line-edit"> 
    <div class="line-edit__title">{{title}}</div> 
    <input class="line-edit__input" ref="textInput" type="text" :value="value" @input="updateInput()" /> 
    </div> 

</template> 
<script type="text/javascript"> 
    export default { 
    components: { 
    }, 
    computed: { 
    }, 
    methods: { 
     updateInput: function(){ 
     this.$emit('input', this.$refs.textInput.value) 
     } 
    }, 
    data: function(){ 
     return {} 
    }, 
    props: { 
     title:{ 
     default:"", 
     type:String 
     }, 
     value: { 
     default: "", 
     type: String 
     } 
    } 
    } 
</script> 

最初のコードブロックは、入力だけで正常に動作します。しかし、2つのカスタムコンポーネントを使用しても、両方のコンポーネントに泡立つように見えることはなく、LineEditorのみです。入れ子に関係なく、これらの値をすべてのカスタムコンポーネントにバブルアップさせるにはどうすればよいですか?

答えて

2

コンポーネントのv-modelを使用して処理するコードを少し更新しました。値をツリーに渡してツリーをバックアップすることができます。電子メールエディタコンポーネントの外から電子メールオブジェクトの値を更新する必要がある場合、更新プログラムがコンポーネントに反映されるように、コンポーネントにウォッチャを追加しました。上記の例で

console.clear() 
 

 
const LineEditor = { 
 
    template:` 
 
    <div class="line-edit"> 
 
     <div class="line-edit__title">{{title}}</div> 
 
     <input class="line-edit__input" type="text" v-model="email" @input="$emit('input',email)" /> 
 
    </div> 
 
    `, 
 
    watch:{ 
 
    value(newValue){ 
 
     this.email = newValue 
 
    } 
 
    }, 
 
    data: function(){ 
 
    return { 
 
     email: this.value 
 
    } 
 
    }, 
 
    props: { 
 
    title:{ 
 
     default:"", 
 
     type:String 
 
    }, 
 
    value: { 
 
     default: "", 
 
     type: String 
 
    } 
 
    } 
 
} 
 

 
const EmailEditor = { 
 
    components: { 
 
    LineEditor 
 
    }, 
 
    template:` 
 
    <div class="email-edit"> 
 
     <line-editor :title="'Email'" v-model="email" @input="updateInput"/> 
 
     <input :value="value.body" v-model="body" @input="updateInput"/> 
 
    </div> 
 
    `, 
 
    watch:{ 
 
    value(newValue){console.log(newValue) 
 
     this.email = newValue.email 
 
     this.body = newValue.body 
 
    } 
 
    }, 
 
    methods: { 
 
    updateInput: function(value){ 
 
     this.$emit('input', { 
 
     email: this.email, 
 
     body: this.body 
 
     }) 
 
    }, 
 
    }, 
 
    data: function(){ 
 
    return { 
 
     email: this.value.email, 
 
     body: this.value.body 
 
    } 
 
    }, 
 
    props: { 
 
    value: { 
 
     default: { 
 
     email: "", 
 
     body: "" 
 
     }, 
 
     type: Object 
 
    } 
 
    } 
 
} 
 

 
new Vue({ 
 
    el:"#app", 
 
    data:{ 
 
    email: {} 
 
    }, 
 
    components:{ 
 
    EmailEditor 
 
    } 
 
})
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script> 
 
<div id="app"> 
 
    <email-editor v-model="email"></email-editor> 
 
    <div> 
 
    {{email}} 
 
    </div> 
 
    <button @click="email={email:'[email protected]', body: 'testing body' }">change</button> 
 
</div>

、入力に値を入力すると、親を更新します。さらに、親の値を変更しての値を変更するボタンを追加しました。のコンポーネントとその変更がコンポーネントに反映されています。

refをこのコードに使用する本当の理由はありません。

+0

これらはもっと完全な解決策であるようです。私は自分のコードベースに追加しました。私があなたのロジックに従っていることを確認するだけです。小道具は子供に渡され、子供はウォッチャーを使用して親から小道具への変更をキャッチし、それに従ってインスタンススコープ変数を調整します。インスタンススコープ変数dataは、ユーザーが編集した内容を維持するためにv-modelとして入力に使用され、入力時にemitを介して親に渡されます。これはあなたのロジックチェーンをカバーしていますか? – steventnorris

+0

@steventnorrisあなたはそれを持っています。 – Bert

0

私のケースでは、パススルーを手動で両方のコンポーネントで実行しても機能しませんでした。しかし、これで私の最初のカスタム・コンポーネントを交換することはなかった:

<line-editor ref="email" :title="'Email'" v-model="value.email"/> 
<input ref="body" :value="value.body" @input="updateInput()"/> 

第一の成分で唯一のVモデルを使用した後、第2カスタムコンポーネントが上向きに放出するトリックをしたすることができます。

関連する問題