首先,提到观察者模式,这不禁让我想到了MVVM,MVVM架构模式感觉用到了观察者的思想。

我们还是按照惯例,了解一下什么是观察者模式

观察者模式,类似发布订阅模式,完成这个动作首先最少得有两个不同的对象,或者多个对象,他更像是一种一队多的依赖关系,也就是一种对象的状态发生改变,与其相关所有的对象的状态都会发生改变;比如说朋友圈这个功能,一个人可能有上百个好友,当我发布一条朋友圈后,所有和我成为好友的人都会看见这个朋友圈,当另一个人点赞后,所有你的好友其他点赞的人也会收到通知,这很像观察者,也就是我是发布者,我的好友是订阅者。

然后我们看一下什么是vue,vue的原理大家都知道,他是一种自底向上的一种深入响应式的双向绑定模式,即MVVM,也就是说,vue关注model的变化,model的变化让mvvm框架更新dom,从而产生视图view变化。

举一个项目中很常见的例子:

在写vue项目中我们都用过父子组件传值,但是兄弟组件传值是怎么实现的,首先我们可以用vuex,这很常见,但是还有一种方法不知道你用过没有,就是Bus,这个Bus只是一种命名而已,叫什么无所谓,你可以叫飞机大炮都可以,这不重要,我们主要看看他是怎么实现的:

第一步,我们先在main.js中注册一下bus:

Vue.prototype.$Bus = new Vue()

我们往vue的原型里注册了一个全局变量$Bus,他的值是vue的实例,也就是说,到现在为止,$Bus里边有了vue所有的属性和方法,这下就好操作了

第二步,我们开始发送消息,这就很符合观察者模式的发布订阅模式

我们在组件1中写如下代码:

<template>
<div>
<button @click="send">发送</button>
</div>
</template> <script>
export default {
methods: {
send () {
this.$Bus.$emit("send",'接收的信息')
}
}
}
</script>

点击按钮发送一条信息,这个按钮也就是充当发布者,我们用到了vue的$emit这个api,那么订阅者是什么呢?我不说你也应该想到了,对,就是他

第三步,在组件三中接收消息

<template>
<div>
{{message}}
</div>
</template> <script>
export default {
data () {
return {
message: ''
}
},
mounted () {
this.$Bus.$on('send', (msg) => {
this.message = msg
})
}
}
</script>

就是用$on这个属性充当接收者

从上可以看出,vue很多地方用到了观察者的思想,包括他的双向绑定也是如此,首先我们看看vue的机制:

从上图我们可以看出,vue是通过Object.defineProperty实现对数据的劫持,然后中间做了一个中转,最后渲染到vue层。

我们可以肯定的是,vue.js借鉴了观察者模式,但是我感觉还是有点区别的,观察者模式跟注重的是事件驱动,比如我买房这个动作,第一次和销售了解可能没有合适的房源,然后销售就会跟你说: ‘如果有合适的房源我们会第一时间通知你’,当有新房源的时候他会给你打电话通知你,这一系列的根源是买房这个事件,他驱动了整套流程。而vue我们都知道是数据驱动,也就是只有data里的值发生改变的话,Object.defineProperty才会对他劫持,从而去更新dom,触发视图的更新。

那么有没有更符合观察者模式特征的?

当然是node.js的events事件了。

首先我们看看events的工作流程:

var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
// 创建事件处理程序
var connectHandler = function connected() {
console.log('连接成功。');
// 触发 data_received 事件
eventEmitter.emit('data_received');
}
// 绑定 connection 事件处理程序
eventEmitter.on('connection', connectHandler);
// 使用匿名函数绑定 data_received 事件
eventEmitter.on('data_received', function(){
console.log('数据接收成功。');
});
// 触发 connection 事件
eventEmitter.emit('connection');
console.log("程序执行完毕。");

输出一下:

这就完全符合观察者的工作模式,由emit发布,由on接收。所以说,node.js提供了很好的监听机制,还有他对整个事务的处理 。其支持了nodejs最特色的I/O模式,比如我们启动http服务时会监听其 connect / close,http.request时会监听 data / end等。

还有没有类似的案例呢?

当然,js有一个事件监听者----addEventListener,也有点观察者的意思,具体用法我就不说了,想必大家用的都很熟悉。

其实只要你认真想一想,还是有很多地方有观察者的身影的,最简单的就是一个点击事件,是不是也有其意思,发布者是一个按钮,而接收者可以是表单,弹层等任何东西。

那么,对于观察者模式存在的意义有哪些呢?

首先我们说说他的优点:

1,观察者模式需要在观察者和被观察者之间建立一个耦合,他需要一个更加抽象化将二者联系在一起

2,观察者模式支持广播,也就是一对多的关系,这就让我们很容易想到一个技术,就是socket,具体可以参考vue项目使用websocket技术

然鹅,他也是优缺点的:

1,创建订阅者本身要消耗一定的时间和内存

2,当订阅一个消息时,也许此消息并没有发生,但这个订阅者会始终存在内存中。

3,观察者模式弱化了对象之间的联系,这本是好事情,但如果过度使用,对象与对象之间的联系也会被隐藏的很深,会导致项目的难以跟踪维护和理解。

等会儿,还有一个模式叫发布订阅模式,很多人都以为他就是观察者模式(包括我),后来我上网查了一下,发现他们还是有区别的,我们可以说观察者模式和发布订阅模式很像,真的很像,但是本质还是有点区别的,最根本的就是调度中心不同。

举个例子,观察者模式更注重是目标和观察者是抽象类,比如天气预报,观察者A负责监听天气的变化,而B想得知天气的变化需要将自己注册到A中,而天气变化的时候A触发天气变化,调度B的接口更新变化。

而发布订阅模式是如何完成这个动作的呢?A想要感知天气变化,需要B这个调度中心,而B得到天气变化需要依赖C的触发,可能我解释的不是很清楚,网上有两个图比较好,我粘到下面,提供参考(侵权必删哈哈哈)

好了,对于观察者模式我的理解就到这里,欢迎指正!

从vue的组件传值着手浅谈观察者模式的更多相关文章

  1. vue父子组件传值加例子

    例子:http://element-cn.eleme.io/#/zh-CN/component/form         上进行改的 父传子:用prop:子组件能够改变父组件的值,是共享的,和父操作是 ...

  2. 关于Vue父子组件传值(复杂数据类型的值)的细节点

    vue 父子组件传值是很常见的,多数情况下都是父传递给子的值是基础数据类型,如string,number,boolean, 当父组件值被修改时,子组件能够实时的作出改变. 如果父子传值的类型是复杂数据 ...

  3. 一个故事讲懂vue父子组件传值

    作者:李佳明同学链接:https://www.jianshu.com/p/2272b6ca0f0c 一个故事讲懂vue父子组件传值 讲故事前先讲代码 父组件向子组件传值 父组件数据传递给子组件可以通过 ...

  4. vue.js组件传值

    组件传值有一下几种方式:父子传值(父传子,子传父),非父子传值,vuex,插槽作用域 1.父子传值: (1)父传子: 传值方:当子元素在父元素中当标签使用时,通过给子标签绑定一个自定义属性,属性值为需 ...

  5. vue兄弟组件传值

    vue中除了父子组件传值,父传子用props,子传父用$emit,有时候兄弟组件之间也需要传值 1. 先定义一个中间件,src下面新建self.js import Vue from 'vue'; le ...

  6. vue父子组件传值

    1.父组件向子组件传值 例如app.vue是父组件,v-header.vue是子组件,实现app向v-header传值父组件需要自定义自己的title值, 子组件v-header内容 <temp ...

  7. vue中组件传值方式汇总

    在应用复杂时,推荐使用vue官网推荐的vuex,以下讨论简单SPA中的组件间传值. 一.路由传值 路由对象如下图所示: 在跳转页面的时候,在js代码中的操作如下,在标签中使用<router-li ...

  8. Vue 父组件传值到子组件

    vue 父组件给子组件传值中 这里的AccessList就是子组件 如果 是静态传值的话直接  msg="xxx"就好 这里动态取值的话就  :msg=xxxxx ________ ...

  9. Vue父子组件传值之——访问根组件$root、$parent、$children和$refs

    Vue组件传值除了prop和$emit,我们还可以直接获取组件对象: 根组件: $root // 单一对象 表示当前组件树的根 Vue 实例,即new Vue({...根组件内容}).如果当前实例没有 ...

随机推荐

  1. This program cannot be run in DOS mode.

    问题:通过ftp上传的exe执行时提示“This program cannot be run in DOS mode.” 解决方法:检查ftp传输模式,设置成binary模式上传即可 参考:https ...

  2. Codeforces Round #420 (Div. 2) - B

    题目链接:http://codeforces.com/contest/821/problem/B 题意:二维每个整点坐标(x,y)拥有的香蕉数量为x+y,现在给你一个直线方程的m和b参数,让你找一个位 ...

  3. python request(HttpRequest对象)请求的属性、方法笔记

    1.属性 path:表示提交请求页面完整地址的字符串,不包括域名,如"/music/bands/the_beatles/". method:表示提交请求使用的HTTP方法.(GET ...

  4. Cytoscape软件简介

    • Cytoscape一款开源的网络显示和分析软件. 软件的核心部分提供了 网络显示.布局.查询等方面的基本功能. • Cytoscape源自系统生物学,通过Cytoscape,用户可以在可视化的 环 ...

  5. 磁盘I/O工作原理

    原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11524947.html TODO Reference https://time.geekbang.or ...

  6. JavaScript之ECMAScript

    JavaScript脚本语言, 运行在浏览器上,无需编译, 轻量级的语言. 功能:让页面有执行逻辑的功能, 可以产生一些动态的效果 JavaScript = ECMAScript + BOM + DO ...

  7. Yii2.0基础框架

    前言:最近在用php写一个项目的接口,所以需要学习一下Yii的框架,也在这里记录一下. 整体结构 ssets文件夹:assets的作用是方便模块化,插件化的,一般来说出于安全原因不允许通过url访问p ...

  8. Heartbeat安装及配置

    1.yum源安装 yum -y install heartbeat 更新yum源 yum install epel-release -y yum源有问题,改用下载rpm包安装 2.rpm安装 下载rp ...

  9. 【FTP】FTP(文件传输协议)工作原理(SFTP)

    目前在网络上,如果你想把文件和其他人共享.最方便的办法莫过于将文件放FTP服务器上,然后其他人通过FTP客户端程序来下载所需要的文件. 1.FTP架构 如同其他的很多通讯协议,FTP通讯协议也采用客户 ...

  10. C# 私有字段前缀 _ 的设置(VS2019, .editorconfig)

    常量和静态只读字段大写 私有字段前缀 _ #### Naming styles #### # Naming rules dotnet_naming_rule.const_should_be_all_u ...