前言
-
本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。
-
这是源码共读的第23期,链接:juejin.cn/post/708298… 。
清单
- 如何学习调试 vue2 源码
- data 中的数据为什么可以用 this 直接获取到
- methods 中的方法为什么可以用 this 直接获取到
- 源码中哪些优秀代码和思想可以投入到自己的项目中
如何调试vue2源码
- 先下载源代码
git clone https://github.com/vuejs/vue.git
- 切换到2.6分支上,找到
examples/todomvc/
目录,就以todomvc为例子进行debugger调试
this为什么能够直接获取到data、methods中数据
先说总结:
methods中把所有方法都绑定到vue实例上,所以能通过this获取到实例上的方法
data中的所有数据都绑定给了vue实例中_data对象上,每次通过this.xxx拿数据的时候,其实是拿的this._data.xxx中的数据
- 开始调试
examples/todomvc/index.html
找到当前引入的app.js文件,这里是业务逻辑实现的地方- 在new Vue之前debugger一下
- 在浏览器中刷新页面,进入浏览器断点模式
- this._init(options)
- 沿着断点调试,首先来到了_init初始化的地方
- 接着进入该方法里面
- Vue.prototype._init
- 发现这是一个定义在Vue原型对象上的方法
- 里面执行了以下事件
vm._self = vm;
initLifecycle(vm); // 初始化声明周期
initEvents(vm); // 初始化事件
initRender(vm); // 初始化渲染
callHook(vm, 'beforeCreate'); // 执行钩子函数
initInjections(vm); // 初始化 injections before data/props
initState(vm); // 初始化状态,这里开始处理data相关的
initProvide(vm); // 初始化注入 initProvide provide after data/props
callHook(vm, 'created'); // 执行钩子函数created
这里就是面试过程中常问问题,vue初始化过程中都发生了什么?以及声明周期的执行顺序和过程是什么?
- 重点看initState()方法
- 本次文章的主题就是为了探索data和methods的问题
- 在该方法中重点看下initMethods和initData方法
- 先看initMethods
- methods中
- vm[key] = typeof methods[key] !== ‘function’ ? noop : bind(methods[key], vm);
给vue实例vm添加绑定的方法,并把this指向指向vm - 如下图中看到的结果
- 接下来看下initData方法
- 该代码中重点是
proxy(vm, "_data", key);
方法,给_data对象添加key,proxy方法具体实现如下图,所有的data中的数据都添加_data对象上,并从其上面拿数据;
- 关于函数的默认配置
- Object.defineProperty(target, key, sharedPropertyDefinition);
- 直接在一个对象上定义一个新的属性,或者修改一个已经存在的属性
- target:在哪个对象身上添加或者修改属性
- key: 添加或修改的属性名
- sharedPropertyDefinition:配置项,一般是一个对象
哪些思想可以用于自己项目
在_init方法中,那一排初始化函数调用中initxxxx(),最深的感受两点:
- 一个好的函数命名的重要性,见名知意,省了好多烦恼
- 每个函数都只做自己该做的事件,负责自己的职责,配合恰当的名字,让代码看起来简洁了很多
总结
-
一般框架项目中都有可以调试的test example
-
之前看vue2工具函数那一部分的时候,单看很多想不到应用场景,在调试代码的时候,发现封装的工具函数在好多地方都用到了
-
亲自动手调试了vue框架的一部分代码,发现对框架原理和源码也不是那么害怕了
-
之前觉得高深的东西,一旦开始行动了,困难也不是坚不可摧的?
© 版权声明
文章版权归作者所有,未经允许请勿转载,侵权请联系 admin@trc20.tw 删除。
THE END