1.组件初始化方法 init

 Vue.prototype._init = function (options) {
/* istanbul ignore if */
if ("development" !== 'production' && config.performance && perf) {
perf.mark('init');
} var vm = this;
//设置组件唯一ID
vm._uid = uid++;
//设置是vue对象
vm._isVue = true;
if (options && options._isComponent) {
//初始化组件配置$options
initInternalComponent(vm, options);
} else {
// 当options 的属性为 data,components,filter,dereactor,生命周期函数,watch,props,method,computed 会触发 合并策略
    //props,direcotives 转为对象
    // 可以用 optionMergerStrategies 自定义 其他合并策略
    // 合并data options[data]将对象转为一个函数 如果是函数 则返回两个函数的返回obj 如果是对象直接合并对象
    // 生命周期 返回生命周期 函数数组
    // components,filters,dereactors 合并返回新对象
    // watch 返回监控某个的 函数数组
   //
vm.$options = mergeOptions( // 合并 构造函数的 Vue.options 和 options
resolveConstructorOptions(vm.constructor),
options || {},
vm
);
}
/* istanbul ignore else */
{
initProxy(vm);
}
// 扩展_self 为自己
vm._self = vm;
   // 如果有父组件,向父组件 $children push当前组件
   // 将$root = $parent 如果有$parent 不存在 ,根组件本身
   // $children = [],$refs={},_wather=null,_inacitve=null,_directInactive=null,_isMounted=null,_isDestroyed=null,isBeingDestroyed=null
initLifecycle(vm);

   //_event = {},_hasHookEvent = false
   //vm._events 创建_events,并将 _parentListeners 事件添加到 vm._events对象中
    initEvents(vm);
  
initRender(vm); //绑定vm._c 和vm.createElement函数 创建标签
callHook(vm, 'beforeCreate');
initInjections(vm); // resolve injections before data/props
initState(vm);
initProvide(vm); // resolve provide after data/props
callHook(vm, 'created'); // 触发 created方法 /* istanbul ignore if */
if ("development" !== 'production' && config.performance && perf) {
vm._name = formatComponentName(vm, false);
perf.mark('init end');
perf.measure(((vm._name) + " init"), 'init', 'init end');
}
console.log(vm)
if (vm.$options.el) { // 存在el 直接挂载到 el 对象上面
vm.$mount(vm.$options.el);
}
};

  

initState (vm)

function initState (vm) {
vm._watchers = [];
var opts = vm.$options;
  // 将属性全部转到 vm._props 上面, 并且监听该上面的数据 改变,如果改变的触发所有依赖该数据的 数据
if (opts.props) { initProps(vm, opts.props); }
//绑定方法 将方法绑定到 vm 上面
if (opts.methods) { initMethods(vm, opts.methods); }
if (opts.data) {
  //观察data以及上面的所有数据
initData(vm);
} else {
//得到或者创建一个 Observer 对象
observe(vm._data = {}, true /* asRootData */);
} //监控 Compuetd 函数和对象,并把他们绑定到vm._computedWatchers上面,get方法执行得到数据
if (opts.computed) { initComputed(vm, opts.computed); }
  //为每一个 watch 创建 watcher对象进行监听
if (opts.watch) { initWatch(vm, opts.watch); }
}

  

 
//监听器
/*
传入当前组件,需要监听的表达式或者函数,回调函数,参数
当监听的表达式值或者函数发生变化
执行run函数
get函数用于得到当前值
evalute函数与用于重新脏检测
updata函数用于更新所以以来该表达式的数据
*/
var Watcher = function Watcher (vm, expOrFn, cb, options) {
this.vm = vm;
vm._watchers.push(this);
// options
if (options) {
this.deep = !!options.deep;
this.user = !!options.user;
this.lazy = !!options.lazy;
this.sync = !!options.sync;
} else {
this.deep = this.user = this.lazy = this.sync = false;
}
this.cb = cb;
this.id = ++uid$2; // uid for batching
this.active = true;
this.dirty = this.lazy; // for lazy watchers
this.deps = [];
this.newDeps = [];
this.depIds = new _Set();
this.newDepIds = new _Set();
this.expression = expOrFn.toString();
// parse expression for getter
if (typeof expOrFn === 'function') {
this.getter = expOrFn;
} else {
this.getter = parsePath(expOrFn);
if (!this.getter) {
this.getter = function () {};
"development" !== 'production' && warn(
"Failed watching path: \"" + expOrFn + "\" " +
'Watcher only accepts simple dot-delimited paths. ' +
'For full control, use a function instead.',
vm
);
}
}
this.value = this.lazy
? undefined
: this.get();
};
//返回当前的value
/*
方法:
get : 访问器,得到该属性值
addDep(dep) : 添加依赖,将该watcher添加到传入的dep的子依赖列表subs中,将传入的依赖添加到newDeps中。 当前wather 依赖 dep , dep,子列表subs中包含该wather
cleanupDep : 用newDeps更新当前wather的依赖列表deps ,清空newDeps列表
run : 检查wather 的值是否改变,如果改变触发 ck 函数并传入 new,old 值
evaluate : 设置this.value,dirty=false 计算完毕,
depend : 将该 watcher 添加到 需要依赖的 某个列表中
teardown : 从所有依赖列表中移除该wather
update : 如果是函数(lazy) dirty = true, sysc , 检查值是否改变 ,
*/

  

//队列执行该依赖 watcher 的 数据更新 依次执行 watcher 的 run方法,结束后执行 updated 组件的函数
/*
has当前队列的id 集合
queue 当前队列watcher集合
*/
function queueWatcher (watcher) {
var id = watcher.id;
if (has[id] == null) {
has[id] = true;
if (!flushing) {
queue.push(watcher); //如果wait 就添加到队列
} else {
// if already flushing, splice the watcher based on its id
// if already past its id, it will be run next immediately.
var i = queue.length - 1;
while (i >= 0 && queue[i].id > watcher.id) {
i--;
}
queue.splice(Math.max(i, index) + 1, 0, watcher);
}
// queue the flush
if (!waiting) { //上一个队列完成后 执行
waiting = true;
nextTick(flushSchedulerQueue); //执行队列中的每个一个watcher run方法
}
}
}

  

 
//组件上面的监听函数,用于监听 函数或者 exp 表达式值变化 , watch 就是调用的该方法  
Vue.prototype.$watch = function (expOrFn, cb, options) { //调用该方法监听某个表达式,返回unwatcher解除监听, expOrFn 的值变化 就执行回调函数 cb
var vm = this;
options = options || {};
options.user = true;
var watcher = new Watcher(vm, expOrFn, cb, options);
if (options.immediate) {
cb.call(vm, watcher.value); //立即执行,新的值
}
return function unwatchFn () { //用于解除绑定
watcher.teardown();
}
};

  

 

http://www.cnblogs.com/jiebba/p/6575214.html

http://www.cnblogs.com/jiebba    我的博客,来看吧!

如果有错误,请留言修改下 哦!

vue2源码浏览分析02的更多相关文章

  1. vue2源码浏览分析01

    1.构造函数  Vue$3 function Vue$3 (options) { if ("development" !== 'production' && !(t ...

  2. Spring IOC 源码简单分析 02 - Bean Reference

    ### 准备 ## 目标 了解 bean reference 装配的流程 ##测试代码 gordon.study.spring.ioc.IOC02_BeanReference.java   ioc02 ...

  3. Vue2源码分析-逻辑梳理

    很久之前就看完vue1,但是太懒就一直没写博客,这次打算抽下懒筋先把自己看过了记录下来,否则等全部看完,估计又没下文了 看源码总需要抱着一个目的,否则就很难坚持下去,我并没做过vue的项目,我几乎很少 ...

  4. 自定义View系列教程03--onLayout源码详尽分析

    深入探讨Android异步精髓Handler 站在源码的肩膀上全解Scroller工作机制 Android多分辨率适配框架(1)- 核心基础 Android多分辨率适配框架(2)- 原理剖析 Andr ...

  5. 自定义View系列教程02--onMeasure源码详尽分析

    深入探讨Android异步精髓Handler 站在源码的肩膀上全解Scroller工作机制 Android多分辨率适配框架(1)- 核心基础 Android多分辨率适配框架(2)- 原理剖析 Andr ...

  6. MapReduce的ReduceTask任务的运行源码级分析

    MapReduce的MapTask任务的运行源码级分析 这篇文章好不容易恢复了...谢天谢地...这篇文章讲了MapTask的执行流程.咱们这一节讲解ReduceTask的执行流程.ReduceTas ...

  7. Activity源码简要分析总结

    Activity源码简要分析总结 摘自参考书籍,只列一下结论: 1. Activity的顶层View是DecorView,而我们在onCreate()方法中通过setContentView()设置的V ...

  8. MapReduce的MapTask任务的运行源码级分析

    TaskTracker任务初始化及启动task源码级分析 这篇文章中分析了任务的启动,每个task都会使用一个进程占用一个JVM来执行,org.apache.hadoop.mapred.Child方法 ...

  9. TaskTracker任务初始化及启动task源码级分析

    在监听器初始化Job.JobTracker相应TaskTracker心跳.调度器分配task源码级分析中我们分析的Tasktracker发送心跳的机制,这一节我们分析TaskTracker接受JobT ...

随机推荐

  1. 无法连接到已配置的web服务器

    问题:如题,asp.net WebForm的项目,在vs中选择aspx文件在浏览器中查看时候回报该错误. 网上最多的解决方案是防火墙的原因,说关闭防火墙就可以了.但问题是我另一个项目没有问题啊,所以不 ...

  2. iOS基础笔试题 - 集锦一

    前言 下文转载自https://mp.weixin.qq.com/s?__biz=MzA4ODk0NjY4NA==&mid=454115946&idx=1&sn=c7f1b50 ...

  3. ES6 学习笔记 - 变量的解构赋值

    变量的解构赋值 学习资料:ECMAScript 6 入门 数组的解构赋值 基本用法 可以从数组中提取值,按照对应位置,对变量赋值.这种写法属于"模式匹配". let [a, b, ...

  4. 高效程序员的45个习惯·敏捷开发修炼之道(Practices of an Agile Developer)读书笔记

    首先,这本书值得再看一遍——这次的阅读,有很多东西都是知其“形”,不知其“神”的,这导致了我对其中某些建议持怀疑态度,接受了的建议也有待商榷. 总之,先记录本书的一些信息: Practices of ...

  5. 微信小程序组件解读和分析:二、scroll-view可滚动视图区域

    scroll-view可滚动视图区域组件说明: 可滚动视图区域. 组件用法:纵向滚动用法 Tip: 使用竖向滚动时,需要给一个固定高度,通过 WXSS 设置 height,否则无法滚动. 当滚动到顶部 ...

  6. jq微信分享

    (function() { var weChat = { init: function() { this.getData(); }, getData: function() { $.ajax({ ty ...

  7. 梦想MxWeb3D,三维CAD协同设计平台 2019.05.05更新

    SDK开发包下载地址: http://www.mxdraw.com/ndetail_20140.html 在线演示网址: http://www.mxdraw.com:3000/ 1.  增加CAD绘图 ...

  8. java中随机生成字符串的方法(三种)

    org.apache.commons.lang(2.6): 链接:https://pan.baidu.com/s/1k_oeA5AjSt6evoR7zT8gpQ 提取码:yhl5 1.生成的字符串每个 ...

  9. 洛谷P1107 & BZOJ1270 [BJWC2008]雷涛的小猫

    一道DP. 给你一个矩阵里面有很多数,你需要从上往下找到一种跳跃方法使得经过的点的价值之和最大. 具体题面见链接 洛谷P1107 BZOJ1270 很明显是一个二维的DP. #include<b ...

  10. CSDN怎么转载别人的博客

    在参考"如何快速转载CSDN中的博客"后,由于自己不懂html以及markdown相关知识,所以花了一些时间来弄明白怎么转载博客,以下为转载CSDN博客步骤和一些知识小笔记. 参考 ...