一步一步学习Vue(十)
本篇说一下组件通信的问题,父子组件通信,前面的博客中已有说明,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 应用的核心就是 store(仓库)。"store" 基本上就是一个容器,它包含着你的应用中大部分的状态(state)。Vuex 和单纯的全局对象有以下两点不同:
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交(commit) mutations。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
<!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(十)的更多相关文章
- 一步一步学习Vue(六)
本篇继续介绍vue-router,我们需要要完成这样个demo:<分页显示文章列表>:这里我们以博客园首页列表为例简化处理: 按照上图框选所示,简单分为蓝色部分文章组件(ArticleIt ...
- 一步一步学习Vue(十一)
本篇继续学习vuex,还是以实例为主:我们以一步一步学Vue(四)中讲述的例子为基础,对其改造,基于vuex重构一遍,这是原始的代码: todolist.js ; (function () { var ...
- 一步一步学Vue(十二)
为了提升代码的逼格,之后代码改为Vue文件组件,之前代码虽然读起来容易理解,而且适合在小的项目中使用,但是有如下缺点: 全局定义(Global definitions) 强制要求每个 componen ...
- 如何一步一步用DDD设计一个电商网站(十四)—— 回顾与总结
本系列所有文章 如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念 如何一步一步用DDD设计一个电商网站(二)—— 项目架构 如何一步一步用DDD设计一个电商网站(三)—— 初涉核心域 如 ...
- 一步一步学Vue(四)
接上篇.上篇中给出了代码框架,没有具体实现,这一篇会对上篇定义的几个组件进行分别介绍和完善: 1.TodoContainer组件 TodoContainer组件,用来组织其它组件,这是react中推荐 ...
- 一步步带你做vue后台管理框架(二)——上手使用
系列教程<一步步带你做vue后台管理框架>第二课 github地址:vue-framework-wz 线上体验地址:立即体验 闲扯再多不会用也没白搭,这节课我来带大家直接上手框架,体验到简 ...
- Vue双向绑定原理,教你一步一步实现双向绑定
当今前端天下以 Angular.React.vue 三足鼎立的局面,你不选择一个阵营基本上无法立足于前端,甚至是两个或者三个阵营都要选择,大势所趋. 所以我们要时刻保持好奇心,拥抱变化,只有在不断的变 ...
- 一步一步学Vue(六)
本篇继续介绍vue-router,我们需要要完成这样个demo:<分页显示文章列表>:这里我们以博客园首页列表为例简化处理: 按照上图框选所示,简单分为蓝色部分文章组件(ArticleIt ...
- 如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车
阅读目录 前言 回顾 梳理 实现 结语 一.前言 之前的文章中已经涉及到了购买商品加入购物车,购物车内购物项的金额计算等功能.本篇准备把剩下的购物车的基本概念一次处理完. 二.回顾 在动手之前我对之 ...
- 12.Linux软件安装 (一步一步学习大数据系列之 Linux)
1.如何上传安装包到服务器 有三种方式: 1.1使用图形化工具,如: filezilla 如何使用FileZilla上传和下载文件 1.2使用 sftp 工具: 在 windows下使用CRT 软件 ...
随机推荐
- java 实例变量的初始化
1.对于实例变量,该类没创建一次实例,就需要为实例变量分配一块内存空间:2.程序通过Person对象来访问eyeNum类变量时,底层依然会转换为通过Person访问eyeNum类变量:3.当Perso ...
- 查找oracle自己用户的表
查找oracle自己用户的表 select table_name from user_tables;
- jquery $.each 和for 怎么跳出循环
jquery $.each 和for 怎么跳出循环 1.for循环中我们使用continue:终止本次循环计入下一个循环,使用break终止整个循环.2.而在jquery中 $.each则对应的使用r ...
- 验证表格多行某一input是否为空
function checkTableKeyWordVal(tableId){ var result = true; $("#"+tableId+" tbody tr&q ...
- 拉勾网招聘数据分析(Echarts, SQL, java)
这次的数据分析与决策课程,我做的是通过爬取拉勾网上的招聘信息,并用爬取到的数据整体分析互联网行业数据,项目做得差不多了,先总结下吧,后边有时间了再完善. 主要工具: Echarts, SQL, ja ...
- 【Android Developers Training】 7. 添加Action Buttons
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- Redis初体验
简介 Redis是一个速度非常快的非关系型数据库,它不仅性能强劲,而且还具有复制特性以及为解决问题而生的独一无二的数据模型.作为键值型数据库,Redis支持5中数据类型:字符串,列表,集 ...
- 通过history解决ajax不支持前进/后退/刷新
前言: 现在前后端基本都是通过ajax实现前后端接口数据的交互,但是,ajax有个小小的劣势,即:不支持浏览器“后退”和“前进“键. 但是,现在我们可以通过H5的histroy属性 解决ajax在交互 ...
- spring +springmvc+mybatis组合mybatis-config.xml文件配置
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC &q ...
- 在线用户数-Constants
package com.pb.news.constants; public class Constants { public static int ONLINE_USER_COUNT=0;//在线用户 ...