MVVM原理(Object.defineProperty和订阅者模式)

想着去了解vue的mvvm数据驱动是怎么实现的,百度中看了这篇文章,demo很好。其他文章只是讲到defineProperty的set,get。

彻底理解Vue中的Watcher、Observer、Dep

我把文章的代码demo简化成自己的代码并且做了注释
class Observer {
  constructor(targetObject) {
    //console.log('targetObject',targetObject);
    //def(targetObject, '__ob__', this);//在 targetObject 上 添加  Observer 实例, setter时 通知该实例
    Object.defineProperty(targetObject, '__ob__', {
        value: this,
        //enumerable: !!enumerable,
        writable: true,
        configurable: true
    });  
    //给对象的每个属性设置get set方法
    Object.keys(targetObject).forEach(key => {
      //console.log('targetObject',targetObject,'key',key,'targetObject[key]',targetObject[key]);
      defineReactive(targetObject, key, targetObject[key])//给对象(包括对象内的对象)定义GET SET方法
    });

    //给每个Observer都添加dep实例
    this.dep = new Dep()
    
    //手动执行订阅
    //this.dep.depend()
  }
}
function observe(data) {
  if (Object.prototype.toString.call(data) !== '[object Object]') {
    return
  }
  new Observer(data)
}
function defineReactive(obj, key, val) {
    //再去判断对象属性的值是不是对象,是的话给该对象也新增__ob__属性
    observe(val)
    //上面的oberve()执行完毕之后对象内所有的对象都有__ob__属性

    //去给对象(包括对象内的对象)设置get set方法
    Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: function reactiveGetter() {
        console.log('get');
        const ob = this.__ob__
        ob.dep.depend();
        return val
        },
        set: function reactiveSetter(newVal) {
        console.log('set');
        if (newVal === val) return
        val = newVal
        observe(newVal)//新值如果是对象也要给其设置__ob__(值为Observer实例)
        const ob = this.__ob__
        ob.dep.notify(newVal);
        },

    })
}

class Dep {
  constructor() {
    this.subs = []
  }

  addSub(sub) {
    this.subs.push(sub)
  }

  depend() {
    this.subs.push(Dep.target)
  }

  notify(val) {
    for (let i = 0; i < this.subs.length; i++) {
      this.subs[i].fn(val)
    }
  }
}

Dep.target = null

class Watcher {
  constructor(vm, exp, fn) {
    //console.log('vm',vm,'exp',exp,'fn',fn)
    this.vm = vm
    this.exp = exp
    this.fn = fn
    Dep.target = this//将自己挂载到 Dep.target,调用 Dep.depend时会读取该变量
    this.vm[exp]//取值 触发get方法 依赖
  }
}

//实验代码
const obj = {
  a: 1,
  b: {
    c: 2
  }
}

new Observer(obj)
console.log('给obj内所有对象设置__ob__以及SET,GET方法',obj)

//在obj这个对象去监听a这个属性的变化(执行订阅)
new Watcher(obj, 'a', (val) => {
  console.log('obj.a设置了新值了',val);
})
obj.a='222';

所有Vue中的MVVM是用Object.defineProperty和订阅者模式实现的。
设置GET动作是去添加依赖(订阅),SET方法是根据依赖(订阅)菜单去发布更新的值,而真正去做动作的(比如更新到DOM中去)是__ob__的值(即observer)中dep中每个watcher实例去做的。
Image placeholder
gaoxiufu
未设置
  51人点赞

没有讨论,发表一下自己的看法吧

推荐文章
react是mvvm框架吗?

react是mvvm框架吗?不是。React可以作为MVVM中第二个V,也就是View,但是并不是MVVM框架。MVVM一个最显著的特征:双向绑定。React没有这个,它是单向数据绑定的。React是

面试问烂的 Spring AOP 原理、SpringMVC 过程

  正文  SpringAOP,SpringMVC,这两个应该是国内面试必问题,网上有很多答案,其实背背就可以。但今天笔者带大家一起深入浅出源码,看看他的原理。以期让印象更加深刻,面试的时候游刃有余。

JVM CPU Profiler技术原理及源码深度解析

本文介绍了JVM平台上CPUProfiler的实现原理,希望能帮助读者在使用类似工具的同时也能清楚其内部的技术实现。引言研发人员在遇到线上报警或需要优化系统性能时,常常需要分析程序运行行为和性能瓶颈。

Spring-SpringAOP原理,手写Spring事务框架

一、Spring核心知识Spring是一个开源框架,Spring是于2003年兴起的一个轻量级的Java开发框架,由RodJohnson在其著作ExpertOne-On-OneJ2EEDevelopm

IBM Spectrum Protect 8.1.7在AIX7.1上的安装和配置

                                                本文作者: 谷铁柏摘要:    本文章主要讲述IBMSpectrumProtect8.1.7版本在AIX

jquery和zepto的区别是什么?

jQuery是一个简洁而快速的JavaScript库,可用于简化事件处理,HTML文档遍历,Ajax交互和动画,以便快速开发网站。jQuery简化了HTML的客户端脚本,从而简化了Web2.0应用程序

jQuery和Zepto是什么?

jQuery是什么?jQuery是一个简洁而快速的JavaScript库,可用于简化事件处理,HTML文档遍历,Ajax交互和动画,以便快速开发网站。jQuery简化了HTML的客户端脚本,从而简化了

1.1. 建造者模式(Builder)

1.2.1.目的 建造者是创建一个复杂对象的一部分接口。 有时候,如果建造者对他所创建的东西拥有较好的知识储备,这个接口就可能成为一个有默认方法的抽象类(又称为适配器)。 如果对象有复杂的继承树,那么

Jenkins export and import jobs 迁移导出导入任务实践小结

前言我遇到的Jenkins迁移项目并非可以通过简单的物理文件复制就可以轻松解决,需要考虑上千个不同项目的jobs分离,Jenkins1.x和2.x大版本兼容性,JenkinsPlugins插件,Jen

搭建 Spring+SpringMVC+MyBatis 框架

SSM框架整合 pom中添加依赖 添加编辑Spring配置文件 添加编辑SpringMVC配置文件 添加编辑Mybatis配置文件 配置web.xml 1、pom中添加依赖 junit ju

jquery和jquery ui的区别?

jquery和jqueryui的区别?区别有:1、jQuery是一个js库,主要提供的功能是选择器,属性修改和事件绑定等等。 2、jQueryUI则是在jQuery的基础上,利用jQuery的扩展性,

gMIS吉密斯十年执念:Lower Costs较低成本Better Productivity较高效率

Hello2020!元旦快乐!今起揭开21世纪20年代的篇章.1.gMIS吉密斯十周年2010-2020,十年转眼已成历史,gMIS吉密斯——通用管理信息系统(generalManagementInf

Stylus系列——webpack-spritesmith配合stylus使用示例

一、前言基于Webpack的CSSSprites实现方案,若是直接在html中调用雪碧图图标已经很方便,但是实际开发过程可能遇到需要在伪元素中使用雪碧图,或者需要hover切换另一个图标,这种情况下就

jquery和js的区别是什么?

jquery和js的区别是什么?一、首先来看一下jQuery和js的概念jquery是一个快速、简洁的JavaScript库,极大的简化了javascript编程。js是一种脚本语言,常用于网页客户端

jquery和javascript有关系吗?

jquery和javascript有关系吗?有关系,具体的关系是:jquery是基于JavaScript编写的,jquery全部都是JavaScript代码组成。jquery和javascript的关

jquery和vue的区别是什么?

jquery和vue的区别是什么?●jquery是直接操作DOM;使用选择器($)选取DOM对象,对其进行赋值、取值、事件绑定等操作;和原生的js区别只在于可以更方便的选取和操作DOM对象;数据和界面

jquery和ajax是什么?

jquery是什么?jQuery是一个简洁而快速的JavaScript库,可用于简化事件处理,HTML文档遍历,Ajax交互和动画,以便快速开发网站。jQuery简化了HTML的客户端脚本,从而简化了

jquery和js之间有什么区别?

js是一种脚本语言,常用于网页客户端编程,使网页在客户端浏览器中,实现更多地动态功能,表现出更加丰富的视觉效果。jQuery是一个简洁而快速的JavaScript库,可用于简化事件处理,HTML文档遍

jquery和ajax的区别是什么?

jquery和ajax的区别Ajax是一门技术,它提供了异步更新的机制,使用客户端与服务器间交换数据而非整个页面文档,实现页面的局部更新。jQuery是一个库,它对JS进行了封装,使其更方便使用。jQ

0103-springmvc的基本流程

背景现在的it研发,已经从管理系统时代迈入了互联网系统时代。页面开发已经从基于JSP+struts转变为为前后端分离的方式(springMVC+JS);思想MVCmvc框架不仅适用于java的开发,也

SpringMVC加载流程

 这节介绍SpringMVC,SpringMVC是一种基于Java的实现MVC设计模式的请求驱动类型的轻量级Web框架。本章会介绍相关概念,流程,再从源码进行讲解。1.MVC MVC(ModelVie

阿里提出针对多目标优化的全新算法框架,同时提升电商推荐场景 GMV 和 CTR

在推荐系统中,多目标优化一直是热门话题,阿里巴巴的XiaoLin、HongjieChen等人针对推荐中的多目标优化问题提出了一种基于帕累托效率的优化算法框架,并应用在电商推荐场景中,对GMV和CTR

OpenStack容器服务Zun初探与原理分析

01Zun服务简介Zun是OpenStack的容器服务(ContainersasService),类似于AWS的ECS服务,但实现原理不太一样,ECS是把容器启动在EC2虚拟机实例上,而Zun会把容器

你不知道的 CSS : Next-generation web styling

最近看了ChromeDevSummit2019大会视频,了解到了很多之前不知道的CSS新特性,挺有意思的。下面我就介绍几个激动人心的特性。特性总览:StickyStickeyStackSticySli

结合Spring Security进行web应用会话安全管理

在本文中,将为大家说明如何结合SpringSecurity和SpringSession管理web应用的会话。 一、SpringSecurity创建使用session的方法 SpringSecurit