2016-11-14 19 views
1

我是Vue js的新手,并试图为自己构建一个简单的CRUD示例。如何修改不同组件中的数据?

按照关于non parent child communication的文档,我想修改一个组件的数据中的heading值,但是从另一个组件中修改heading值。

我成立了a fiddle展示相关的功能我目前了解它,我们在这里的HTML:

<div id="app" v-cloak> 
    <person-add></person-add> 
    <person-list :list="people"></person-list> 
</div> 

<template id="person-add-template"> 
    <div> 
    <h2> 
     <span>{{ heading }}</span> 
     Person 
    </h2> 
    <form @submit.prevent="handleFormSubmit"> 
     <input type="text" placeholder="Enter persons name" v-model="name" /> 
     <button type="submit" v-show="name"> 
     Add Person 
     </button> 
    </form> 
    </div> 
</template> 

<template id="person-list-template"> 
    <div> 
    <h2>People</h2> 
    <table border="1"> 
     <tr> 
     <th>Person</th> 
     <th>Edit</th> 
     </tr> 
     <tr v-for="(person, key) in list"> 
     <td>{{ person.name }}</td> 
     <td><button type="button" @click="editPerson(key)">Edit</button></td> 
     </tr> 
    </table> 
    </div> 
</template> 

而且JS:

// https://vuejs.org/v2/guide/components.html#Non-Parent-Child-Communication 
var bus = new Vue(); 
// Add 
Vue.component('person-add', { 
    template: '#person-add-template', 
    props: ['list'], 
    data: function() { 
    return { 
     heading: 'Add', 
     name: '' 
    } 
    }, 
    created: function() { 
    bus.$on('toggle-heading', function (newHeading) { 
     console.log(newHeading); 
     this.heading = newHeading; 
    }); 
    } 
}); 
// List 
Vue.component('person-list', { 
    template: '#person-list-template', 
    props: ['list'], 
    methods: { 
    editPerson: function (key) { 
     console.log('fired'); 
     bus.$emit('toggle-heading', 'Edit'); 
    } 
    } 
}); 
// Vue 
new Vue({ 
    el: '#app', 
    data: { 
    people: [ 
     { name: 'Bob' }, 
     { name: 'Frank' }, 
     { name: 'Mary' } 
    ] 
    } 
}); 

正如你所看到的,它呈现一个简单的表单,以“添加人员”开头,并列出一些人员以及每个人的编辑按钮:

Person List

我想要发生的事情是,当我点击人名旁边的编辑时,它将改变另一个组件中的标题以表示“编辑人员”,而不是默认的“添加人员”。

在分量AI的方法有:

editPerson: function (key) { 
    console.log('fired'); 
    bus.$emit('toggle-heading', 'Edit'); 
} 

而在组件BI中创建的钩有:

created: function() { 
    bus.$on('toggle-heading', function (newHeading) { 
    console.log(newHeading); 
    this.heading = newHeading; 
    }); 
} 

当我点击编辑,在控制台中我看到了日志fired和然后Edit所以事件似乎跟随到person-add组件,但我试图分配新标题this.heading = newHeading;,标题不会改变,我正在争取理解为什么。

如果有人可以建议为什么会发生这种情况,我在哪里出错或如何处理,如果这不是正确的方式,那么将不胜感激。

非常感谢提前!

回答

1

你的问题实际上是与范围有关,而不是缺乏对Vue的理解。你的代码是正确的,除非你试图从一个函数内部访问this创建它自己的this上下文。

只要你创建一个新的功能,这样一来,它会创建它自己的this所以当你:

bus.$on('toggle-heading', function(newHeading) { 
    console.log(newHeading); 
    // this refers to this anonymous function only 
    this.heading = newHeading; 
}); 

this只是指函数本身,而不是在Vue实例。

来解决这个问题的方法是使用一个arrow function,不建立自己的this

bus.$on('toggle-heading', (newHeading) => { 
     console.log(newHeading); 
     // No new 'this' context is created in an arrow function 
     this.heading = newHeading; 
    }); 

或者,如果你不使用ECMAScript 2015则需要参考设置this功能外:

var self = this; // set a reference to "this" 

    bus.$on('toggle-heading', function(newHeading) { 
     console.log(newHeading); 
     // Now self refers to the view models `this` 
     self.heading = newHeading; 
    }); 

我已经更新了你的提琴向您展示这两种方法:

氩排功能:https://jsfiddle.net/abtgmx47/3/

使用var self=this参考:https://jsfiddle.net/abtgmx47/4/

+0

当你说这像那么它非常有意义,最明显,我现在。感谢您的详细解释,以及可能的选项代码和小提琴。今天我已经在这里教了几件事,你应该超越我的分数,非常感谢:-) –