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

提琴手

原文由 Sam YC 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 844
2 个回答

在初始化期间,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 不会将动态添加的属性识别为反应性属性。当然,这只是一种可能的解决方案,可能还有很多其他解决方法。可以在 这里 看到一个完整的工作示例。

原文由 Aer0 发布,翻译遵循 CC BY-SA 4.0 许可协议

根据我的评论,您需要考虑几件事:

  • 您的代码不工作的原因是由于 JS 固有地无法观察对象属性的变化。这意味着即使 addr 是反应性的,添加到 addr 的任何属性在声明时未完成都会使其无反应性。有关更多详细信息,请参阅 VueJS 文档: https ://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats
  • 如果您要拥有任意数量的输入字段,您可能最好 编写一个自定义输入组件,并简单地使用 v-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>

该模板可能如下所示。 It simply uses the id prop for both its id , name , and placeholder attribute (the latter for easy identification in the demo) .我们绑定 @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);
    }
  }
});


使用上面的代码,我们有一个工作示例。 In this case, I have created an arbirary array of input fields: contactNum , a , b , and 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>

原文由 Terry 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题