Vue事件处理程序的可组合函数

时间:2016-10-31 05:59:50

标签: vue.js

我正在使用Vue 2.0,ES6,Webpack。

我有一个组件(让我们称之为Parent)和几个孩子(让我们称之为text-input)。每个text-input都会发出一个名为change的事件,每个事件都应该更改Parent中的一个不同属性。假设Parent有一个名为info的数据,我在info内有姓名,电子邮件等。

我想要完成的是使用@change选项的相同功能设置正确的属性(名称,电子邮件,...)。

<text-input
   @change="alterProperty('name')">  
 </text-input>
 <text-input
   @change="alterProperty('email')">  
 </text-input>

我的Parent会有这种方法:

alterProperty (property) {
  return (changeValue) => {
    this.info[property] = changeValue
  }
}

到目前为止,没有,我无法让这个工作,也许是Vue处理事情的方式,我不知道。如果有人知道这件事,我感谢你的帮助。

由于

2 个答案:

答案 0 :(得分:4)

请查看此jsFiddle示例:https://jsfiddle.net/mani04/2mmbsyy3/

它的工作方式正如您所期望的那样。以下是我使用text-input组件的方式:

<text-input :value="userInfo.name" @change="alterProperty('name', $event)"></text-input>

注意: alterProperty内联方法,可在@change事件处理程序中直接调用。所以它不会得到默认的$event参数 - 带有子组件参数的特殊变量,除非你包含它。在您的代码中,这是缺少的部分。

参考:https://vuejs.org/guide/events.html#Methods-in-Inline-Handlers

在示例jsFiddle实现中,$event只是来自子组件的事件参数,而不是DOM event。我的alterProperty方法(在父组件中)的工作方式如下:

alterProperty: function(propToChange, newValue) {
    this.userInfo[propToChange] = newValue;
}

jsFiddle还输出父组件上的对象,该组件按预期进行修改。

编辑:附加说明

您的子组件不应将this.value直接绑定到您的input元素,因为this.value是通过道具传递的。如果您尝试这样做,您将收到一个控制台错误消息,如:

  

[Vue警告]:避免直接改变道具......

为了避免这种情况,我使用了本地计算属性 - textFieldValue,它具有getter和setter方法。虽然getter只返回this.value,但是setter是将change事件发送回父组件的,而不会触及通过props传递的this.value

答案 1 :(得分:0)

我写了2个小提琴来存档有效。一种方法是使用v-on,emitter,来存档子组件和父组件之间的通信。一种方法是直接更新子组件中的父数据。

我建议第一种方式。

检查第一个,使用v-on,发射器方式,https://jsfiddle.net/seaify/p8fh108j/

Vue.component('text-input', {
    props: ["parent_field"],
    template: `
        <input type="text" v-model="text">
    `,
    data: function() {
      return {text: ''}
    },
    watch: {
       text: function(value, old_value) {
          this.$emit('update_parent', this.parent_field, value)
       }
    }
});

Vue.component('my-app-form', {
    template: `
        <div class="my-app-form">
            <div class="my-text-input">
                Name: <text-input parent_field="name" v-on:update_parent='update_self'></text-input>
            </div>
            <div class="my-text-input">
                Email: <text-input parent_field="email" v-on:update_parent='update_self'></text-input>
            </div>
            <div class="result">Result: name = {{name}}, email = {{email}}</div>
        </div>

        `,
    methods: {
       update_self: function(key, value) {
       this[key] = value
      }
    },
    data: function() {
        return {
                name: "",
                email: ""          
        }
    },
});

new Vue({
    el: '#app',
    template: `
        <div>
            <my-app-form></my-app-form>
        </div>
    `,
});

检查这个小提琴示例,直接更新父组件,无需通信,https://jsfiddle.net/seaify/jczowb54/10

Vue.component('text-input', {
    props: ["parent_field"],
    template: `
        <input type="text" v-model="text">
    `,
    data: function() {
      return {text: ''}
    },
    watch: {
       text: function(value, old_value) {
            this.$parent[this.parent_field] = value
       }
    }
});

Vue.component('my-app-form', {
    template: `
        <div class="my-app-form">
            <div class="my-text-input">
                Name: <text-input parent_field="name"></text-input>
            </div>
            <div class="my-text-input">
                Email: <text-input parent_field="email" ></text-input>
            </div>
            <div class="result">Result: name = {{name}}, email = {{email}}</div>
        </div>

        `,
    data: function() {
        return {
                name: "",
                email: ""          
        }
    },
});

new Vue({
    el: '#app',
    template: `
        <div>
            <my-app-form></my-app-form>
        </div>
    `
});

感谢Mani,我已经把你的小提琴分开并更新了代码。