9.1. 引言

Vue组件化做的确实非常彻底,它独有的vue单文件组件也是做的非常有特色。组件化的同时带来的是:组件之间的数据共享和通信的难题。 尤其Vue组件设计的就是,父组件通过子组件的prop进行传递数据,而且数据传递是单向的。也就是说:父组件可以把数据传递给子组件,但是 反之则不同。如下图所示:

9.2. 单向数据流动

单方向的数据流动带来了非常简洁和清晰的数据流,纯展示性或者独立性较强的模块的开发确实非常方便和省事。 但是复杂的页面逻辑,组件之间的数据共享处理就会需要通过事件总线的方式解决或者使用Vue的Vuex框架了。

9.3. 子组件通知父组件数据更新:事件方式的实现

子组件可以在子组件内触发事件,然后在父容器中添加子组件时绑定父容器的方法为事件响应方法的方式.如下图所示:

  • 使用 v-on 绑定自定义事件
每个 Vue 实例都实现了事件接口(Events interface),即:
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件

参考代码案例:

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>Vue入门之event message</title>
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css"> <!-- 可选的Bootstrap主题文件(一般不用引入) -->
<link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap-theme.min.css"> <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script> <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="http://cdn.bootcss.com/bootstrap/3.3.0/js/bootstrap.min.js"></script> <script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head> <body>
<div id="app">
<p>推荐次数:{{ voteCount }}</p>
<hr>
<!--绑定两个自定义事件,当组件内部触发了事件后,会自定调用父容器绑定的methods的方法,达到了子容器向父容器数据进行通信同步的方法-->
<vote-btn v-on:vote="voteAction" v-on:sendmsg="sendMsgAction"></vote-btn>
<hr>
<ul class="list-group">
<li v-for="o in msg" class="list-group-item">{{o}}</li>
</ul>
</div>
<script>
Vue.component('vote-btn', {
template: `
<div>
<button class="btn btn-success" v-on:click="voteArticle">推荐</button>
<hr/>
<input type="text" v-model="txtMsg" />
<button v-on:click="sendMsg" class="btn btn-success">发送消息</button>
</div>
`,
data: function () {
return {
txtMsg: ""
}
},
methods: {
voteArticle: function () {
// 触发事件,vote
this.$emit('vote')
},
sendMsg: function () {
// 触发事件,sendmsg,并
this.$emit('sendmsg', this.txtMsg)
}
}
}) var app = new Vue({
el: '#app',
data: {
voteCount: 0,
msg: []
},
methods: {
voteAction: function() { // 事件触发后,会直接执行此方法
this.voteCount += 1
},
sendMsgAction: function (item) {
this.msg.push(item)
}
}
});
</script>
</body> </html>

  

9.4. 事件总线方式解决非父子组件数据同步

如果非父子组件怎么通过事件进行同步数据,或者同步消息呢?Vue中的事件触发和监听都是跟一个具体的Vue实例挂钩。 所以在不同的Vue实例中想进行事件的统一跟踪和触发,那就需要一个公共的Vue实例,这个实例就是公共的事件对象。

参考下面做的一个购物车的案例的代码:

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>Vue入门之event message</title>
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css"> <!-- 可选的Bootstrap主题文件(一般不用引入) -->
<link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap-theme.min.css"> <!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script> <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="http://cdn.bootcss.com/bootstrap/3.3.0/js/bootstrap.min.js"></script> <script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head> <body>
<div id="app">
<product-list :products="products" v-on:addpro="addToCarts"> </product-list>
<hr>
<cart :cart-products="carts"> </cart>
</div>
<script>
var eventBus = new Vue() Vue.component('cart', {
template: `
<table class="table table-borderd table-striped table-hover">
<thead>
<tr>
<th>商品编号</th>
<th>商品名</th>
<th>数量</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item in cartProducts"> <td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>
{{ item.count }}
</td>
<td>
<button type="button" @click="removeCarts(item)" class="btn btn-success"><i class="glyphicon glyphicon-remove"></i></button>
</td>
</tr>
</tbody>
</table>
`,
data: function () {
return {
}
},
methods: {
removeCarts: function (item) {
eventBus.$emit('remo', item)
}
},
props: ['cartProducts']
}) Vue.component('product-list', {
template: `
<table class="table table-borderd table-striped table-hover">
<thead>
<tr>
<th>商品编号</th>
<th>商品名</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item in products">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>
<button type="button" v-on:click="addToCarts(item)" class="btn btn-success"><i class="glyphicon glyphicon-shopping-cart"></i></button>
</td>
</tr>
</tbody>
</table>
`,
data: function () {
return {
}
},
methods: {
addToCarts: function (item) {
this.$emit('addpro', item)
}
},
props: ['products'], }) var app = new Vue({
el: '#app',
data: {
products: [
{ id: '1', name: '鳄鱼' },
{ id: '2', name: '蛇' },
{ id: '3', name: '兔子' },
{ id: '4', name: '驴' },
{ id: '5', name: '孔雀' }
],
carts: []
},
methods: {
addToCarts: function (item) {
var isExist = false
for(var i=0; i<this.carts.length; i++) {
if( item.id === this.carts[i].id ) {
item.count = this.carts[i].count + 1
Vue.set(this.carts, i, item)
isExist = true
}
}
!isExist && (item.count = 1, this.carts.push(item))
},
removeCarts: function (item) {
for(var i =0; i<this.carts.length; i++) {
if( item.id === this.carts[i].id) {
this.carts.splice(i,1)
}
}
}
},
mounted: function () {
self = this;
eventBus.$on('remo', function (item) {
self.removeCarts(item)
})
}
});
</script>
</body> </html>

  

9.5. Vuex解决复杂单页面应用

上面的方式只能解决一些简单的页面中的组件的通信问题,但是如果是复杂的单页面应用就需要使用更强大的Vuex来帮我们进行状态的统一管理和同步。

当第一次接触Vuex的时候,眼前一亮,之前经过Redux之后,被它繁琐的使用令我痛苦不已,虽然思路很清晰,其实完全可以设计的更简单和高效。 当我接触到Vuex之后,发现这就是我想要的。的确简洁就是一种艺术。

其实本质上,Vuex就是一个大的EventBus对象的升级版本,相当于一个特定的仓库,所有数据都在统一的仓库中,进行统一的管理。

几个核心的概念:

  • State: Vuex仓库中的数据。
  • Getter: 类似于Vue实例中的计算属性,Getter就是普通的获取state包装函数。
  • Mutations: Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutations 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
  • Action: action可以触发Mutations,不能直接改变state。

看下面一张图了解一下Vuex整体的数据流动:

9.6. Vuex实例demo

可能前面的图和概念都太多了,先看一个例子,简单了解一下Vuex中的仓库的数据 怎么整合到 Vue的实例中去。

创建Vuexdemo的项目

# 通过vue-cli创建vuexdemo的项目,注意首先cd到你的存放项目代码的目录
vue init webpack vuexdemo # 过程中,会有几个选项你可以选择输入Y或者n来开启或者关闭某些选项。 # 创建完成后,就可以通过以下命令,进行初始化和安装相关的依赖项了。
cd vuexdemo
npm install
npm run dev # 然后安装 vuex
npm i vuex -S 转载:http://aicoder.com/vue/preview/all.html#9

10. 总结

Vue的入门系列基本都写完了,大部分内容是参考了官网的文档。

还有很多内容没有整理到这个系列中。比如:vue的过渡动画,vue的异步刷新队列,vue的过滤器等,我相信你通过本文档就能 实现vue的入门了,那些琐碎的知识点只要看一下官方的文档应该很容入门。

这一次整理过程,让我对Vue有了更深入的认识,之前不熟悉的东西,强迫自己把 文档写一遍后,认识比以前更清晰了。Vue确实带来很多的惊喜。希望这个文档对你有用。

【09】Vue 之 Vuex 数据通信的更多相关文章

  1. Vue 2.0 + Vue Router + Vuex

    用 Vue.js 2.x 与相配套的 Vue Router.Vuex 搭建了一个最基本的后台管理系统的骨架. 当然先要安装 node.js(包括了 npm).vue-cli 项目结构如图所示: ass ...

  2. Vue之Vuex

    一.什么是vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.简单来说就是一个数据统一 ...

  3. requirejs、vue、vuex、vue-route的结合使用,您认为可行吗?

    在五一节之前和一网友讨论前端技术时,对方提到vue.vue-route如果配合requirejs应用.当时的我没有想得很明白,也没能这位网友一个准确的回复,但我许诺于他五一研究后给他一个回复.本是一天 ...

  4. Vue中Vuex的详解与使用(简洁易懂的入门小实例)

    怎么安装 Vuex 我就不介绍了,官网上有 就是 npm install xxx 之类的.(其实就是懒~~~哈哈) 那么现在就开始正文部分了 众所周知 Vuex 是什么呢?是用来干嘛的呢? Vuex ...

  5. vue:vuex中mapState、mapGetters、mapActions辅助函数及Module的使用

    一.普通store中使用mapState.mapGetters辅助函数: 在src目录下建立store文件夹: ​ index.js如下: import Vue from 'vue'; import ...

  6. vue+vue-router+vuex实战

    shopping vue + vue-router + vuex实现电商网站 效果展示 install 下载代码: git clone https://github.com/chenchangyuan ...

  7. 15.vue动画& vuex

    Vue.config.productionTip = false; ==是否显示提示信息== ==import/export== export xxx 必须跟跟对象或者和定义一起 对象: export ...

  8. Vue、Vuex+Cookie 实现自动登陆 。

    概述 1.自动登陆实现思路. 2.vuex + cookie 多标签页状态保持. 自动登陆的需求: 1.登陆时勾选自动登陆,退出登陆或登陆到期后再次登陆后自动填写表单(记住密码)或访问登陆页自动登陆. ...

  9. 深入浅出的webpack4构建工具--webpack4+vue+route+vuex项目构建(十七)

    阅读目录 一:vue传值方式有哪些? 二:理解使用Vuex 三:webpack4+vue+route+vuex 项目架构 回到顶部 一:vue传值方式有哪些? 在vue项目开发过程中,经常会使用组件来 ...

随机推荐

  1. struts2、hibernate的知识点

    以下内容是我在复习struts2.hibernate和spring的时候记下得到,部分书上找不到的内容来自网络 以下是网络部分的原文网站: http://blog.csdn.net/frankaqi/ ...

  2. ASP.NET Core模块化前后端分离快速开发框架介绍之1、开篇

    源码地址 GitHub:https://github.com/iamoldli/NetModular 演示地址 地址:https://nm.iamoldli.com 账户:admin 密码:admin ...

  3. ELK详细安装部署

    一.前言 ​ 日志主要包括系统日志和应用程序日志,运维和开发人员可以通过日志了解服务器中软硬件的信息,检查应用程序或系统的故障,了解故障出现的原因,以便解决问题.分析日志可以更清楚的了解服务器的状态和 ...

  4. HTML5/CSS3 第二章页面组件

    页面组件 1 元素的尺寸/边框/背景 1.1 css尺寸相关属性 height 高度 min-height 最小高度 max-height 最大高度 width 宽度 min-width 最小宽度 m ...

  5. iframe子元素相对于父页面滚动条固定(iframe无滚动条,iframe固定高度有滚动条,两种情况)

    一.当iframe自适应高度,无滚动条时候: 例如这样: //随着父页面滚动条滚动定位“#qn-quc”他的位置固定在顶部 $(parent.window).scroll(function() { v ...

  6. Django框架基础知识01-配置环境

    Django框架 Django是个怎样的东西呢? Web应用框架----Django  http服务器:用来接受用户请求,并将请求转发给web应用框架进行处理. Web应用框架处理完以后再发送给htt ...

  7. 最短路径:HDU2006-一个人的旅行(多个起点,多个终点)

    题目: 一个人的旅行 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  8. PowerShell批量配置VM端点

    我们可以通过PowerShell脚本批量添加VM端点.请您参考以下方案. 准备工作 – PowerShell连接China Azure 1. 从官网下载页面,下载并安装Windows Azure Po ...

  9. java十分钟速懂知识点——NIO

    一.引子 nio是java的IO框架里边十分重要的一部分内容,其最核心的就是提供了非阻塞IO的处理方式,最典型的应用场景就是处理网络连接.很多同学提起nio都能说起一二,但是细究其背后的原理.思想往往 ...

  10. 8 REST Framework 实现Web API 1

    1 参考博客: http://blog.csdn.net/SVALBARDKSY/article/details/50548073 2  准备工作 1. 环境 Python: Python 3.5 D ...