vue观察模式浅析


Posted in Javascript onSeptember 25, 2018

观察者模式

首先话题下来,我们得反问一下自己,什么是观察者模式?

概念

观察者模式(Observer):通常又被称作为发布-订阅者模式。它定义了一种一对多的依赖关系,即当一个对象的状态发生改变的时候,所有依赖于它的对象都会得到通知并自动更新,解决了主体对象与观察者之间功能的耦合。

讲个故事

上面对于观察者模式的概念可能会比较官方化,所以我们讲个故事来理解它。

A:是共产党派往国民党密探,代号 001(发布者)
B:是共产党的通信人员,负责与 A 进行秘密交接(订阅者)

  • A 日常工作就是在明面采集国民党的一些情报
  • B 则负责暗中观察着 A
  • 一旦 A 传递出一些有关国民党的消息(更多时候需要对消息进行封装传递,后面根据源码具体分析)
  • B 会立马订阅到该消息,然后做一些相对应的变更,比如说通知共产党们做一些事情应对国民党的一些动作。

适用性

以下任一场景都可以使用观察者模式

  • 当一个抽象模型有两个方面,其中一个方面依赖于另一方面。讲这两者封装在独立的对象中可以让它们可以各自独立的改变和复用
  • 当一个对象的改变的时候,需要同时改变其它对象,但是却不知道具体多少对象有待改变
  • 当一个对象必须通知其它对象,但是却不知道具体对象到底是谁。换句话说,你不希望这些对象是紧密耦合的。

以下是我对vue观察者模式的理解:

不要对框架的偏见, 你真的了解jquery、angular、react 等等,框架是什么只是工具而已。

你用过jquery的 trigger、on、off 事件绑定的方法吗?事实上 vue 不过也是这种模式,只不过vue 是自动调用on方法,自动触发trigger。甚至可以不用jquery对事件监听触发的实现。其实最终解释就是对某种事件的callback(基础原理)。

以下是源码目录截图:

vue观察模式浅析

1... vue 实例初始化时,会对data函数返回的对象里的属性调用以下方法,代码注释如下:

// 这个是 vue 绑定自动绑定事件的方法和触发事件方法, 会把data函数返回的对象变量属性,重写对应属性的 赋值 和获取的操作。具体查看 (mdn Object.defineProperty api)
 Object.defineProperty(obj, key, {
  enumerable: true,
  configurable: true,
  get: function reactiveGetter () {
   const value = getter ? getter.call(obj) : val
   // watcher 对象, 如果存在
   if (Dep.target) {
    // 把Watcher 实例 推入 Dep 实例的 subs 数组里, 这个就相当于 on
    dep.depend()
    if (childOb) {
     childOb.dep.depend()
     if (Array.isArray(value)) {
      dependArray(value)
     }
    }
   }
   return value
  },
  set: function reactiveSetter (newVal) {
   const value = getter ? getter.call(obj) : val
   /* eslint-disable no-self-compare */
   if (newVal === value || (newVal !== newVal && value !== value)) {
    return
   }
   /* eslint-enable no-self-compare */
   if (process.env.NODE_ENV !== 'production' && customSetter) {
    customSetter()
   }
   if (setter) {
    setter.call(obj, newVal)
   } else {
    val = newVal
   }
   childOb = !shallow && observe(newVal)
   // 通知 Dep 实例 中subs 里数组 中所有 Watcher 实例, 然后调用Watcher实例里的 update方法(), 这个就相当于 trigger。
   dep.notify()
  }
 })
// Watcher 构造函数 
 constructor (
  vm: Component,
  expOrFn: string | Function,
  cb: Function,
  options?: ?Object,
  isRenderWatcher?: boolean
 )

2...Watcher初始化时,会调用Dep.pushTarget方法, 把 Wathcer实例赋值到dep.js 里的Dep.target, 接着会根据 exporFn,运行exporFn 所代表的方法。这个方法里基本上包含调用 1...里的getter方法(想想render钩子里的操作基本有获取vue实例属性data里的值或者获取vue实例的计算属性的值)。

var vm = new Vue({
  data () {
    return {msg: '找个小姐姐!'}
  },
  // 相当于 exporFn
  render(h) {
    return h('h3', {},
     // 这里面就会调用 msg 对应的 getter方法
     this.msg
    )
  }
})

所以就会使 render 函数 与 Vue 实例 的 数据 data属性 和观察属性等产生联系,这就形成一个闭环。当其中的属性变化,就会自动调用 setter 方法,从而触发dep.notify 方法,进而又会触发 dep.subs 里的 Watcher 实例调用 update方法,进而更新。
(这部分代码不知如何说,故此没写, 具体查看源码)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery 操作XML入门
Dec 25 Javascript
Js制作简单弹出层DIV在页面居中 中间显示遮罩的具体方法
Aug 08 Javascript
js和php如何获取当前url的内容
Sep 22 Javascript
轻松实现javascript图片轮播特效
Jan 13 Javascript
jQuery form插件的使用之处理server返回的JSON, XML,HTML数据
Jan 26 Javascript
jQuery Dialog对话框事件用法实例分析
May 10 Javascript
Js+Ajax,Get和Post在使用上的区别小结
Jun 08 Javascript
JavaScript从0开始构思表情插件
Jul 26 Javascript
Vue 实现树形视图数据功能
May 07 Javascript
Layui带搜索的下拉框的使用以及动态数据绑定方法
Sep 28 Javascript
Vue实现可移动水平时间轴
Jun 29 Javascript
浅谈vue.watch的触发条件是什么
Nov 07 Javascript
详解搭建es6+devServer简单开发环境
Sep 25 #Javascript
解决v-for中使用v-if或者v-bind:class失效的问题
Sep 25 #Javascript
在axios中使用params传参的时候传入数组的方法
Sep 25 #Javascript
VUE实现可随意拖动的弹窗组件
Sep 25 #Javascript
vue移动端弹框组件的实例
Sep 25 #Javascript
JavaScript常用数组操作方法,包含ES6方法
May 10 #Javascript
在vue项目中,将juery设置为全局变量的方法
Sep 25 #Javascript
You might like
单一index.php实现PHP任意层级文件夹遍历(Zjmainstay原创)
2012/07/31 PHP
深入理解ob_flush和flush的区别(ob_flush()与flush()使用方法)
2013/02/06 PHP
php Session存储到Redis的方法
2013/11/04 PHP
PHP变量赋值、代入给JavaScript中的变量
2015/06/29 PHP
PHP正则删除HTML代码中宽高样式的方法
2017/06/12 PHP
Thinkphp5行为使用方法汇总
2017/12/21 PHP
php curl简单采集图片生成base64编码(并附curl函数参数说明)
2019/02/15 PHP
jquery简单体验
2007/01/10 Javascript
IE和firefox浏览器的event事件兼容性汇总
2009/12/06 Javascript
js中for in的用法示例解析
2013/12/25 Javascript
jquery实现简易的移动端验证表单
2015/11/08 Javascript
10个JavaScript中易犯小错误
2016/02/14 Javascript
BootStrap使用popover插件实现鼠标经过显示并保持显示框
2016/06/23 Javascript
Angular2学习笔记——详解NgModule模块
2016/12/02 Javascript
JS与jQuery实现子窗口获取父窗口元素值的方法
2017/04/17 jQuery
React.Js添加与删除onScroll事件的方法详解
2017/11/03 Javascript
基于vue2.0实现仿百度前端分页效果附实现代码
2018/10/30 Javascript
微信小程序实现日历签到
2020/09/21 Javascript
如何在现代JavaScript中编写异步任务
2021/01/31 Javascript
Python采用raw_input读取输入值的方法
2014/08/18 Python
在Python中操作字典之fromkeys()方法的使用
2015/05/21 Python
python3爬虫之设计签名小程序
2018/06/19 Python
利用python list完成最简单的DB连接池方法
2019/08/09 Python
Python-openCV开运算实例
2020/07/05 Python
美国奢侈品在线团购网站:Gilt City
2017/11/16 全球购物
美国现代家具网站:Design Within Reach
2018/07/19 全球购物
含精油的天然有机化妆品:Indemne
2019/08/27 全球购物
工程造价专业大学生职业规划范文
2014/03/09 职场文书
主管竞聘书范文
2014/03/31 职场文书
网站客服岗位职责
2014/04/05 职场文书
企业文明单位申报材料
2014/05/16 职场文书
人事主管岗位职责说明书
2014/07/30 职场文书
公司授权委托书范文
2014/09/21 职场文书
公安交警中队队长个人对照检查材料思想汇报
2014/10/05 职场文书
教师党的群众路线教育实践活动个人整改措施
2014/11/04 职场文书
2014年药剂科工作总结
2014/11/26 职场文书