本篇说一下组件通信的问题,父子组件通信,前面的博客中已有说明,vue也推荐props in,event out;兄弟节点通信如何做呢?官方其实也给出了实现方式,我们以下面的场景来实现一下:

上图中,实现如下功能:搜索表单组件中,包含各种搜索条件,当点击搜索按钮时,加载数据到列表组件中渲染。

这里会给出三种实现方式,不涉及合适与否,只为演示。

1、使用父组件进行封装,把所有操作都移到父组件中

2、搜索组件,触发事件到父组件,父组件监听到事件发生,则执行查询操作,传递props 到列表组件,这也是我们前面实现过的方式,这里简单写一个demo。

首先定义我们的组件:SearchComponent 、AppComponent、ListComponent

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>demo4</title>
<script src="https://cdn.bootcss.com/vue/2.4.1/vue.js"></script> </head> <body>
<div id="app">
<app></app>
</div>
<script>
var SearchComponent = {
template:`
<div class="toolbar">
<input type="text" placeholder="keyword" v-model="keyword"/>
<input type="text" placeholder="description" v-model="desc"/>
<input type="button" value="search" @click="search()" />
</div>
`,
data:function(){
return {
keyword:'',
desc:''
}
},
methods:{
search:function(){
this.$emit('onsearch',{keyword:this.keyword,desc:this.desc});
}
}
} var ListComponent = {
template:`
<div class="list" >
{{list}}
</div>
`,
props:['list']
} var AppComponent={
template:`
<div class="container">
<search @onsearch="search($event)" ></search>
<list :list="datas" ></list>
</div>
`,
components:{
'list':ListComponent,
'search':SearchComponent
},
methods:{
search:function($e){
this.datas=JSON.stringify({
data:[],
info:'info'
});
}
},
data:function(){
return {
datas:null
}
}
} var app=new Vue({
el:'#app',
components:{
'app':AppComponent
}
});
</script>
</body> </html>

点击搜索按钮,运行效果如下:

上面的例子非常简单,而且所写代码在前面的博文中都有所介绍,这里就不详述了,在这里数据流流向如下:

1、点击按钮,数据由 search组件流向父组件

2、父组件监听onsearch ,监听到事件后,处理并给list赋值,此时数据由 父组件 流向 list组件

父组件这里的作用就是一个中转站,提供了一种数据流的中转功能。那么如果没有父组件,能否实现上述功能呢,毕竟我们不可能每次兄弟组件通信都创建一个多余父组件过来,这样如果嵌套层数过多也是很大的问题,对于兄弟组件通信的问题,官方也提到了叫做event bus的实现方式,下面我们就实现一下第二种方案,基于event bus:

修改我们的代码如下:

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>demo4</title>
<script src="https://cdn.bootcss.com/vue/2.4.1/vue.js"></script> </head> <body>
<div id="app">
<search></search>
<list></list>
</div>
<script>
var eventBus = new Vue(); var SearchComponent = {
template: `
<div class="toolbar">
<input type="text" placeholder="keyword" v-model="keyword"/>
<input type="text" placeholder="description" v-model="desc"/>
<input type="button" value="search" @click="search()" />
</div>
`,
data: function () {
return {
keyword: '',
desc: ''
}
},
methods: {
search: function () {
// this.$emit('onsearch',{keyword:this.keyword,desc:this.desc});
eventBus.$emit('onsearch', { keyword: this.keyword, desc: this.desc });
}
}
} var ListComponent = {
template: `
<div class="list" >
{{list}}
</div>
`, data: function () {
return {
list: null
} },
created: function () {
var self = this;
eventBus.$on('onsearch', function ($e) {
console.log($e);
self.list = JSON.stringify($e);
})
}
} var app = new Vue({
el: '#app',
components: {
// 'app':AppComponent
'list': ListComponent,
'search': SearchComponent
}
});
</script>
</body> </html>

这里借助一个全局的vue空实例,来实现一个全局的eventbus,当然我们也可以使用或者实现自己的eventbus,这个是比较简单的,(大致思路是:定义一个回调列表数组,定义两个方法,一个on一个emit,on即是向回调数组push key 和对应的function,emit就是触发key对应的function)有兴趣的可以简单做一下,保存后运行即可。

对于简单的兄弟组件通信,其实这种方案或者第一种方案已经满足,但是如果兄弟节点过多或者组件层次很深的时候,使用第一种方案我们必须一层一层的传递几乎重复的代码,使用第二种方案所有组件又全部依赖于全局vue实例或者说全局eventbus,有没有更好的状态管理方案呢?能否把状态管理独立出来呢,这就是我们接下来要说的vuex。

Vuex 是一个专为 Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel调试、状态快照导入导出等高级调试功能,如果打开官网,你会看到上面这段话。
这都是什么乱七八糟的,可能让人看不明白,虽然看起来逼格很高,其实它只是做的比我们的eventbus 更高级一点:

每一个 Vuex 应用的核心就是 store(仓库)。"store" 基本上就是一个容器,它包含着你的应用中大部分的状态(state)。Vuex 和单纯的全局对象有以下两点不同:

  1. Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

  2. 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交(commit) mutations。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

vuex中包含很多概念和约定,今天我们就开始体验一下,话不多说,同样的功能基于vuex重构一下:
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>demo4</title>
<script src="https://cdn.bootcss.com/vue/2.4.1/vue.js"></script>
<script src="https://cdn.bootcss.com/vuex/2.3.1/vuex.js"></script> </head> <body>
<div id="app">
<search></search>
<list></list>
</div>
<script>
// var eventBus = new Vue();
var store = new Vuex.Store({
state: {
list: null
},
mutations: {
search: function (state, payload) {
state.list = JSON.stringify(payload);
}
}
}) var SearchComponent = {
template: `
<div class="toolbar">
<input type="text" placeholder="keyword" v-model="keyword"/>
<input type="text" placeholder="description" v-model="desc"/>
<input type="button" value="search" @click="search()" />
</div>
`,
data: function () {
return {
keyword: '',
desc: ''
}
},
methods: {
search: function () {
this.$store.commit("search",{ keyword: this.keyword, desc: this.desc })
//eventBus.$emit('onsearch', { keyword: this.keyword, desc: this.desc });
}
}
} var ListComponent = {
template: `
<div class="list" >
{{list}}
</div>
`,
computed:{
list:function(){
return this.$store.state.list;
}
} } var app = new Vue({
el: '#app',
store:store,
components: {
// 'app':AppComponent
'list': ListComponent,
'search': SearchComponent
}
});
</script>
</body> </html>

这里我们创建了一个全局store,store是唯一的,里面保存着所有的状态(这种状态建议是全局的或者共享的,我们这里假设list组件中的state属于共享,大家不要较真,而search中的state属于组件本身状态),我们做如下约定:不要直接修改状态,要通过提交mutations来修改状态,mutations相当于在react中使用setState去修改状态一样。直接修改会运行时异常。

针对上面的代码,主要包括如下几个知识点:

1、vuex的实例化:直接new Vuex.Store ,创建全局唯一store,通过配置参数,设置state(全局共享的)、mutations(只支持同步操作)

2、vuex和vue的联系,通过new Vue实例时,注入store,这里和前文中注入router类似,注入后,在任何子组件中,就可以通过this.$store来访问store了

3、store中的state是响应式的,所以建议定义为组件计算属性,每次通过mutations提交修改,则可直接驱动view的变化。

本节主要引入vuex,算是vuex的开篇,不介绍过多内容,让我们有一个简单的认识,接下来会向介绍vue-router一样,慢慢的深入其它的方方面面。敬请期待。

 
 

一步一步学习Vue(十)的更多相关文章

  1. 一步一步学习Vue(六)

    本篇继续介绍vue-router,我们需要要完成这样个demo:<分页显示文章列表>:这里我们以博客园首页列表为例简化处理: 按照上图框选所示,简单分为蓝色部分文章组件(ArticleIt ...

  2. 一步一步学习Vue(十一)

    本篇继续学习vuex,还是以实例为主:我们以一步一步学Vue(四)中讲述的例子为基础,对其改造,基于vuex重构一遍,这是原始的代码: todolist.js ; (function () { var ...

  3. 一步一步学Vue(十二)

    为了提升代码的逼格,之后代码改为Vue文件组件,之前代码虽然读起来容易理解,而且适合在小的项目中使用,但是有如下缺点: 全局定义(Global definitions) 强制要求每个 componen ...

  4. 如何一步一步用DDD设计一个电商网站(十四)—— 回顾与总结

    本系列所有文章 如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念 如何一步一步用DDD设计一个电商网站(二)—— 项目架构 如何一步一步用DDD设计一个电商网站(三)—— 初涉核心域 如 ...

  5. 一步一步学Vue(四)

    接上篇.上篇中给出了代码框架,没有具体实现,这一篇会对上篇定义的几个组件进行分别介绍和完善: 1.TodoContainer组件 TodoContainer组件,用来组织其它组件,这是react中推荐 ...

  6. 一步步带你做vue后台管理框架(二)——上手使用

    系列教程<一步步带你做vue后台管理框架>第二课 github地址:vue-framework-wz 线上体验地址:立即体验 闲扯再多不会用也没白搭,这节课我来带大家直接上手框架,体验到简 ...

  7. Vue双向绑定原理,教你一步一步实现双向绑定

    当今前端天下以 Angular.React.vue 三足鼎立的局面,你不选择一个阵营基本上无法立足于前端,甚至是两个或者三个阵营都要选择,大势所趋. 所以我们要时刻保持好奇心,拥抱变化,只有在不断的变 ...

  8. 一步一步学Vue(六)

    本篇继续介绍vue-router,我们需要要完成这样个demo:<分页显示文章列表>:这里我们以博客园首页列表为例简化处理: 按照上图框选所示,简单分为蓝色部分文章组件(ArticleIt ...

  9. 如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车

     阅读目录 前言 回顾 梳理 实现 结语 一.前言 之前的文章中已经涉及到了购买商品加入购物车,购物车内购物项的金额计算等功能.本篇准备把剩下的购物车的基本概念一次处理完. 二.回顾 在动手之前我对之 ...

  10. 12.Linux软件安装 (一步一步学习大数据系列之 Linux)

    1.如何上传安装包到服务器 有三种方式: 1.1使用图形化工具,如: filezilla 如何使用FileZilla上传和下载文件 1.2使用 sftp 工具: 在 windows下使用CRT 软件 ...

随机推荐

  1. 2个问题,解决tomcat启动一闪而过和运行tomcat/bin目录下的startup.bat时报错(the CATALINA_HOME environment variable is not defined correctly)

    1.除手动使用开始菜单自启动或者程序启动TOMCAT时TOMCAT一闪而过,这时候是发生了错误,这时候我们打开BIN目录下的“startup.bat”文件,编辑,在结尾添加pause命名,这样在CMD ...

  2. C# 短信发送 邮件发送

    兴趣是最好的老师. --爱因斯坦 一.实现短信发送 1.使用短信mao的方式进行短信发送,前提要购买硬件设备,这里就不考虑展示了: 2.使用中国网建提供的短信平台,但是用几次后要收费: 我们这里主要介 ...

  3. WPF编程-WPF体系结构

    WPF简介 Windows Presentation Foundation(WPF)是微软新一代图形系统,运行在.NET Framework 3.0架构下,为用户界面.2D/3D 图形.文档和媒体提供 ...

  4. Thrift总结(二)创建RPC服务

    前面介绍了thrift 基础的东西,怎么写thrift 语法规范编写脚本,如何生成相关的语言的接口.不清楚的可以看这个<Thrift总结(一)介绍>.做好之前的准备工作以后,下面就开始如何 ...

  5. 关于Ext 修复源代码 bug的方法

    Ext修复源代码出现的问题 1.使用override属性,重写组件 定义一个新的组件,override属性设为要重写的源组件 例子: Extjs4.2.3遇到的一个bug,Datefield 选择不了 ...

  6. BootStrap dateRangePicker时间范围控件

    BootStrap dateRangePicker时间范围控件 1 安装引用 1.1 下载zip Github:https://github.com/dangrossman/bootstrap-dat ...

  7. IOS开发基础环境搭建

    一.目的 本文的目的是windows下IOS开发基础环境搭建做了对应的介绍,大家可根据文档步骤进行mac环境部署: 二.安装虚拟机 下载虚拟机安装文件绿色版,点击如下文件安装 获取安装包:       ...

  8. 【原创】 Docker 中 运行 ASP.NET Core 站点

    一. 建立 .NetCore 项目  a.新建项目 b.选择项目类型 c.添加控制器 d.添加视图 e.修改默认请求 f.发布 二. 准备 CentOS 环境 a.准备虚拟机 b.安装 docker ...

  9. Ubantu 16.4 samba安装配置

    本文总结了Ubantu 16.04 环境下的samba安装.配置及使用.本文为原创,也是我的第一篇博客,以后会经常写博客,记录自己的学习.总结及研究,让博客见证着我成长的轨迹. 下文中的所有命令均使用 ...

  10. 使用JDK自带的MessageDigest计算消息摘要

    使用JDK自带的MessageDigest计算消息摘要 上代码 /** * 使用JDK自带MessageDigest */ public class MessageDigestUtils { /** ...