Watch.js v1.0.13源码学习

前言

从事前端开发工作从实习开始算起到现在也一年多了,然后也只会三大流行框架之一的vue.js以及小程序开发,工作之余也只是偶尔看看书,补充补充知识。最近开始考虑跳槽的时候才发现自己还真的只是一个菜鸟,因此想好好静下心来好好学习,沉淀自己,写这个博客记录一下自己的学习历程。

背景

学习vue早期源码学习系列之一的时候看到了WatchJS这个库可以做到监听数据的变化,于是也想学着youngwind介绍vue早期源码学习的思路开扒WatchJS。

效果

我们需要实现下面的效果

// 定义一个对象
var ex = {
    attr1: 'attr1',
    attr2: 'attr2'
};
// 监听attr1属性
ex.onWatch('attr1', function () {
    console.log('attr1 change')
})
// 改变attr1属性触发回调
ex.attr1 = 'new attr1'
复制代码

思路

  • 首先要把onWatch 方法添加到Object.prototype 上,这样任何一个对象都可以调用onWatch方法了。
  • 通过Object.defineProperty 劫持对象的属性,在有变化的时候通知订阅者执行相应的函数。

简单实现

var watchjs = {
  isArray: function(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]'
  },
  // 用来添加修改对象的自有属性
  defineGetAndSet: function(obj, propName, setter, getter) {
    Object.defineProperty(obj, propName, {
      enumerable: true, // 能被枚举,监听的对象属性应该可以被枚举,即hasOwnProperty访问到
      configurable: true, // enumerable, writable等属性描述符可以被改变
      set: setter,
      get: getter
    })
  },
  // 用来添加object.prototype上的方法
  defineProp: function(obj, propName, value) {
    Object.defineProperty(obj, propName, {
      enumerable: false, // 不能被枚举,在Object.property上自定义的属性不应该被枚举
      configurable: true, // enumerable, writable等属性描述符可以被改变
      writable: false, // 不可被重写,防止被他人重写
      value: value // 设置值,与setter, getter不共存
    })
  }
}
watchjs.defineProp(Object.prototype, 'onWatch', function(prop, handler) {
  var obj = this // 被监听的对象
  var val = obj[prop]
  if (!obj.handlers) {
    watchjs.defineProp(obj, 'handlers', {})
  }
  // 将监听的对象的属性和响应的回调函数以键值对的形式存在被监听的对象的handlers属性中
  if (!obj.handlers.hasOwnProperty(prop)) {
    obj.handlers[prop] = [handler]
  } else {
    obj.handlers[prop].push(handler)
  }
  var getter = function() {
    return val
  }
  var setter = function(newVal) {
    // 当属性值有变化时执行相应的回调函数
    if (val !== newVal) {
      val = newVal
      obj.emitWatch(prop)
    }
  }
  watchjs.defineGetAndSet(obj, prop, setter, getter)
})
watchjs.defineProp(Object.prototype, 'emitWatch', function(prop) {
  var obj = this
  if (obj.handlers.hasOwnProperty(prop)) {
    for (let i = 0; i < obj.handlers[prop].length; i++) {
      obj.handlers[prop][i]()
    }
  }
})
复制代码

效果

源码

转载于:https://juejin.im/post/5c78de2f51882534bf002934

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值