1.背景
Vue.js是一款MVVM框架,个人对MVVM框架的理解不是很透彻,简单介绍一下自己的理解,更全面准确的解释请参见文章 《MVVM》。
MVVM(model-view-viewModel)同MVC设计模式一样,用于将数据和视图解耦,使程序设计的思路更加清晰,代码更易于维护。model-数据-就是组件中的data,view-视图-就是组件中的模板。viewModel,将两者连接在一起的,就是vue。vue将数据和模板通过vue实例进行绑定。使得我们可以通过改变数据来更新视图,而在必要时,也可以让视图的变化更新数据。那么,我们现在需要弄清楚两个问题:1.vue.js如何将数据和视图绑定在一起?2.组件之间如何通信?
Vue.js通过vue的一些指令,将数据和视图绑定到一起,如,v-bind指令可以将数据作为属性绑定到元素或组件上,v-model则可以实现双向绑定(所谓双向绑定,就是对于input、textarea等输入元素,用户输入的值绑定到数据,使数据可以同步更新)。Vue组件通信分为3部分:父组件到子组件,子组件到父组件,子组件到子组件。Vue.js是单向数据流的设计。就是说父组件到子组件的通信是靠传递数据,子组件不能向父组件传递数据,那么子组件向父组件如何传递消息呢?答案是通过事件,通过触发可携带数据的事件,子组件就可以实现和父组件的通信了。子组件和子组件之间的通信则需要靠总线机制。这个不详细介绍,请参见文档 《Vue.js非父子组件通信》。下面通过文档中的例子《vue-实例 todo》来说明一下这两个问题。
下面的例子实现了一个任务列表的简单应用,用户输入内容,按回车可以生成记录item,每个item后有一个删除按钮。
<div id="todo-list-example"><inputv-model="newTodoText"v-on:keyup.enter="addNewTodo"placeholder="Add a todo"><ul><liis="todo-item"v-for="(todo, index) in todos"v-bind:title="todo"v-on:remove="todos.splice(index, 1)"></li></ul>
</div>
Vue.component('todo-item', {template: '<li>{
{ title }}<button v-on:click="$emit('remove')">X</button></li>',props: ['title']
})
new Vue({el: '#todo-list-example',data: {newTodoText: '',todos: ['Do the dishes','Take out the trash','Mow the lawn']},methods: {addNewTodo: function () {this.todos.push(this.newTodoText)this.newTodoText = ''}}
})
该应用的设计是,有一个根组件,和一个子组件。根组件即id为todo-list-example的元素对应的Vue实例。它维护了两个数据:newTodoText和todos。根组件的模板里包括两部分:用于输入的input元素和用于显示todo列表的ul。通过创建vue实例,并传入dom #todo-list-example,Vue.js就把数据和视图绑定在了一起,这样我们就可以通过改变数据来更新视图了。newTodoText这个数据表示当前正在创建的todo,可以看到,input元素通过指令 v-model将自身的内容和newTodoText进行了双向绑定。这样当我们输入内容时,newTodoText会和内容进行同步,输入完内容,再按回车,就会执行input中使用v-on监听的按键事件,更新todos,将新添加的todo append到todos的末尾。更新后的todos会触发视图的更新,即添加一个新的li,文本即我们刚输入的内容。删除则是子组件向父组件传递消息的一个案例。点击子组件时,向父组件抛出一个remove事件,父组件接到这个事件会执行remove将该li组件删除。
$emit触发的事件不会向上冒泡,只能传递到上一级的组件那里。那么Vue怎么进行跨层级的事件传递呢?比如孙子组件向父组件传递事件,在Vue1中,可以在父组件中使用events属性进行事件监听,孙子组件就使用$emit触发事件即可。还有$dispatch和$broadcast API可以进行事件跨层级传递,事件会一直向上冒泡,直到被父组件捕获。
在Vue2中,可能出于规范消息传递机制和状态管理,撤销了这些API。其实组件事件传递就是通信,组件间的通信包括父子组件和其它关系的组件之间的通信。组件之间的通信推荐使用总线机制或者vuex。