具有v模型的Vue.js组件

时间:2017-06-12 18:19:40

标签: input vuejs2 vue-component v-model

我已经能够在自定义组件上完成单层深度的v-model双向绑定,但需要更深入一级。

当前工作代码:

OSError

像这样使用: <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>

第一个代码块只需输入即可正常工作。但是,使用两个自定义组件似乎并没有通过两个组件,只有LineEditor。无论嵌套如何,如何让这些值在所有自定义组件中冒泡?

2 个答案:

答案 0 :(得分:6)

我已经稍微更新了您的代码以处理在组件上使用v-model,以便您可以在树中传递值并备份树。我还在您的组件中添加了观察者,这样如果您应该从电子邮件编辑器组件外部更新电子邮件对象值,则更新将反映在组件中。

&#13;
&#13;
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
  }
})
&#13;
<script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="app">
  <email-editor v-model="email"></email-editor>
  <div>
    {{email}}
  </div>
  <button @click="email={email:'testing@email', body: 'testing body' }">change</button>
</div>
&#13;
&#13;
&#13;

在上面的示例中,在输入中输入值会更新父项。此外,我添加了一个按钮,用于更改父级值,以模拟更改外部组件的值以及组件中反映的更改。

对于此代码,没有任何理由可以使用ref

答案 1 :(得分:0)

在我的情况下,在两个组件上手动完成passthrough都不起作用。但是,用这个替换我的第一个自定义组件:

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

在第一个组件中仅使用v-model然后允许第二个自定义组件向上发射就可以了。