Vue源码探究之状态初始化(6)

initWatcher 为传入的观察对象创建监视器,比较简单。值得注意的是参数的传入类型,观察对象 expOrFn 可以有两种方式,一种是字符串,一种是函数,在 Watcher 类中对此参数进行了检测,而在初始化的函数里不对它做任何处理。handler 对象也可以接受对象或字符串类型,在代码中对这两种传入方式做判断,最终找到handler引用的函数传入 $watch。

stateMixin

探索完了 initState 函数之后,继续来看看 state 混入的方法 stateMixin,在这个函数里会提供上面还未曾提到的 $watch 方法的具体实现:

// 定义并导出stateMixin函数,接收参数Vue
export function stateMixin (Vue: Class<Component>) {
 // 使用 Object.defineProperty 方法直接声明定义对象时,flow会发生问题
 // 所以必须在此程序化定义对象
 // flow somehow has problems with directly declared definition object
 // when using Object.defineProperty, so we have to procedurally build up
 // the object here.
 // 定义dataDef对象
 const dataDef = {}
 // 定义dataDef的get方法,返回Vue实例私有属性_data
 dataDef.get = function () { return this._data }
 // 定义propsDef对象
 const propsDef = {}
 // 定义propsDef的get方法,返回Vue实例私有属性_props
 propsDef.get = function () { return this._props }
 // 非生产环境下,定义dataDef和propsDef的set方法
 if (process.env.NODE_ENV !== 'production') {
 // dataDef的set方法接收Object类型的newData形参
 dataDef.set = function (newData: Object) {
  // 提示避免传入对象覆盖属性$data
  // 推荐使用嵌套的数据属性代替
  warn(
  'Avoid replacing instance root $data. ' +
  'Use nested data properties instead.',
  this
  )
 }
 // 设置propsDef的set方法为只读
 propsDef.set = function () {
  warn(`$props is readonly.`, this)
 }
 }
 // 定义Vue原型对象公共属性$data,并赋值为dataDef
 Object.defineProperty(Vue.prototype, '$data', dataDef)
 // 定义Vue原型对象公共属性$props,并赋值为propsDef
 Object.defineProperty(Vue.prototype, '$props', propsDef)

 // 定义Vue原型对象的$set方法,并赋值为从观察者导入的set函数
 Vue.prototype.$set = set
 // 定义Vue原型对象的$delete方法,并赋值为从观察者导入的del函数
 Vue.prototype.$delete = del

 // 定义Vue原型对象的$watch方法
 // 接收字符串或函数类型的expOrFn,从命名中可看出希望为表达式或函数
 // 接收任何类型的cb,这里希望为回调函数或者是一个对象
 // 接收对象类型的options
 // 要求返回函数类型
 Vue.prototype.$watch = function (
 expOrFn: string | Function,
 cb: any,
 options?: Object
 ): Function {
 // 把实例赋值给vm变量,类型需为Component
 const vm: Component = this
 // 如果cb是纯粹的对象类型
 if (isPlainObject(cb)) {
  // 返回createWatcher函数
  return createWatcher(vm, expOrFn, cb, options)
 }
 // 定义观察目标的options,大多数情况下为undefined
 options = options || {}
 // 定义options的user属性值为true,标识为用户定义
 options.user = true
 // 创建watcher实例
 const watcher = new Watcher(vm, expOrFn, cb, options)
 // 如果options的immediate为真
 if (options.immediate) {
  // 在vm上调用cb回调函数,并传入watcher.value作为参数
  cb.call(vm, watcher.value)
 }
 // 返回unwatchFn函数
 return function unwatchFn () {
  // 执行watcher.teardown()方法清除观察
  watcher.teardown()
 }
 }
}


      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/428.html