读Vue源码二 (响应式对象)

vue在init的时候会执行observer方法,如果value是对象就直接返回,如果对象上没有定义过_ob_这个属性,就 new Observer实例

export function observe (value: any, asRootData: ?boolean): Observer | void {
  if (!isObject(value) || value instanceof VNode) {
    return
  }
  let ob: Observer | void
  if (hasOwn(value, ‘__ob__‘) && value.__ob__ instanceof Observer) {
    ob = value.__ob__
  } else if (
    shouldObserve &&
    !isServerRendering() &&
    (Array.isArray(value) || isPlainObject(value)) &&
    Object.isExtensible(value) &&
    !value._isVue
  ) {
    ob = new Observer(value)
  }
  if (asRootData && ob) {
    ob.vmCount++
  }
  return ob
}

Observer 方法,实例化一个dep是在做依赖收集时用的,调用def方法给对象添加_ob_这个属性,如果是数组就遍历给每个数组中的值都添加_ob_,否则调用walk方法

export class Observer {
  value: any;
  dep: Dep;
  vmCount: number; // number of vms that has this object as root $data
  constructor (value: any) {
    this.value = value
    this.dep = new Dep()
    this.vmCount = 0
    def(value, ‘__ob__‘, this)
    if (Array.isArray(value)) {
      const augment = hasProto
        ? protoAugment
        : copyAugment
      augment(value, arrayMethods, arrayKeys)
      this.observeArray(value)
    } else {
      this.walk(value)
    }
  }

walk方法其实就是把对象的每个key调用defineReactive方法

 walk (obj: Object) {
    const keys = Object.keys(obj)
    for (let i = 0; i < keys.length; i++) {
      defineReactive(obj, keys[i])
    }
  }

defineReactive方法就是将其变为响应式对象,首先调用observer方法如果对象的key还是对象,会再次执行一遍上面的逻辑,如果不是对象会在oberver方法中直接返回,然后就是给对象添加setter和

getter将其变为响应式

export function defineReactive (
  obj: Object,
  key: string,
  val: any,
  customSetter?: ?Function,
  shallow?: boolean
) {
  const dep = new Dep()

  const property = Object.getOwnPropertyDescriptor(obj, key)
  if (property && property.configurable === false) {
    return
  }

  // cater for pre-defined getter/setters
  const getter = property && property.get
  if (!getter && arguments.length === 2) {
    val = obj[key]
  }
  const setter = property && property.set
  
  let childOb = !shallow && observe(val)
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      const value = getter ? getter.call(obj) : val
      if (Dep.target) {
        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.notify()
    }
  })
}

原文地址:https://www.cnblogs.com/zpxm/p/10347212.html

时间: 2024-08-01 22:57:28

读Vue源码二 (响应式对象)的相关文章

vue源码之响应式数据

分析vue是如何实现数据响应的. 前记 现在回顾一下看数据响应的原因. 之前看了vuex和vue-i18n的源码, 他们都有自己内部的vm, 也就是vue实例. 使用的都是vue的响应式数据特性及$watchapi. 所以决定看一下vue的源码, 了解vue是如何实现响应式数据. 本文叙事方式为树藤摸瓜, 顺着看源码的逻辑走一遍, 查看的vue的版本为2.5.2. 目的 明确调查方向才能直至目标, 先说一下目标行为: vue中的数据改变, 视图层面就能获得到通知并进行渲染. $watchapi监

Vue源码之响应式原理(个人向)

浅谈响应式原理 关于响应式原理,其实对于vue这样一个大项目来说肯定有很多细节和优化的地方,在下水平精力有限,不能一一尝试探索,本文仅以将响应式的大致流程个人向的梳理完毕为目的. 对于响应式主要分为三大部分来分析,1.响应式对象:2.依赖收集:3.派发更新. 最后将是个人的分析. 1.响应式对象 (Object.defineProperty) 我们先从初始化数据开始,再介绍几个比较核心的方法. 1.1.initState 文件位置:src/core/instance/state.js 在Vue的

读 vue 源码一 (为什么this.message能够访问data里面的message)

12月离职后,打算在年后再找工作了,最近陆陆续续的看了黄轶老师的vue源码解析,趁着还有几天过年时间记录一下. 目标:vue如何实现通过this.key,就能直接访问data,props,methods,里面的key. 源码:当我们在项目中new Vue实例后会执行Vue构造函数的_init方法,并执行一些混入 function Vue (options) { if (process.env.NODE_ENV !== 'production' && !(this instanceof Vu

Ace 1.3.1 网站管理后台源码 Bootstrap响应式模板主题

Ace 响应式管理后台模板最新版本v1.3.1同步升级,欢迎下载使用,注意:本站提供为官网购买压缩源码版,在官网上用18$买来,现只售20元,可以帮亲省3/4的额外开销哦,需要的亲可以到本博的淘宝小店购买,包升级(免费!). Ace简介: Ace (v1.3.1)是一个轻量.功能丰富.HTML5.响应式.支持手机及平板电脑上浏览的管理后台模板,基于CSS框架Bootstrap制作,Bootstrap版本更新至 3.0,Ace – Responsive Admin Template当前最新版! 淘

Matrix Admin html5网站管理后台源码 Bootstrap响应式模板主题

Matrix Admin 响应式管理后台模板最新版本,欢迎下载使用,注意:本站提供为官网购买未压缩源码版,在官网上用10$买来,现只售15元,可以帮亲省额外开销哦,需要的亲可以到本博的淘宝小店购买. Matrix Admin 简介: Matrix Admin 是一个轻量.功能丰富.HTML5.响应式.支持手机及平板电脑上浏览的管理后台模板,基于CSS框架Bootstrap制作,Bootstrap版本更新至 3.0,Matrix Admin 当前最新版! 淘宝购买地址(新地址,更新至最新的1.3.

读Vue源码 (依赖收集与派发更新)

vue的依赖收集是定义在defineReactive方法中,通过Object.defineProperty来设置getter,红字部分主要做依赖收集,先判断了Dep.target如果有的情况会执行红字逻辑进行依赖收集过程 const getter = property && property.get if (!getter && arguments.length === 2) { val = obj[key] } const setter = property &&

java 企业站源码 自适应响应式 兼容手机平板PC SSM freemaker 静态引擎主流框架

前台: 支持四套模版, 可以在后台切换 系统介绍: 1.网站后台采用主流的 SSM 框架 jsp JSTL,网站后台采用freemaker静态化模版引擎生成html 2.因为是生成的html,所以访问速度快,轻便,对服务器负担小 3.网站前端采用主流的响应式布局,同一页面同时支持PC.平板.手机(三合一)浏览器访问 4.springmvc +spring4.3.7+ mybaits3.3  SSM 普通java web(非maven, 赠送pom.xml)  数据库:mysql --------

java 企业门户网站 源码 自适应响应式 freemarker 静态引擎 html5 SSM

1.网站后台采用主流的 SSM 框架 jsp JSTL,网站后台采用freemaker静态化模版引擎生成html 2.因为是生成的html,所以访问速度快,轻便,对服务器负担小 3.网站前端采用主流的响应式布局,同一页面同时支持PC.平板.手机(三合一)浏览器访问 4.springmvc +spring4.3.7+ mybaits3.3  SSM 普通java web(非maven, 赠送pom.xml)  数据库:mysql 1.   网站信息:维护网站基本信息,比如标题.描述.关键词.联系方

vue源码分析:响应式之依赖收集

今天记录下vue源码的响应式的源码学习,第一步,我们想下,为什么为们写一个data.然后里边的数据变化就能映射到dom的变化上.这里用到了Object.defineProperty(obj,key, {}),如果你还不了解建议去jsmdn上仔细了解下,这个函数的目的就是检测你得赋值和取值的过程用来定义自己的行为,比如obj[key]会拿到配置里边的get函数定义,obj[key] = 'xxx'会调用配置中的set.那么vue也是一样的,在get中做了依赖收集(也就是说哪些dom用到了我定义的这