Vue源码(一)
入口文件 src/core/instance/index.js 中可以看到
function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
!(this instanceof Vue)) {
warn('Vue is a constructor and should be called with the `new` keyword')
}
this._init(options)
}
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
export default Vue
Vue的构造函数在此, 然后通过mixin的方式将
- 数据方法等特性处理(state)
- 事件处理(events)
- 生命周期(lifecycle)
- 渲染函数(render)
的相关的方法挂到Vue的原型上去。
1.init
挂上了_init 方法,没错就是 构造函数当中调用的_init方法。
这里做了一些参数处理,其中作者在参数对象赋值的时候,用一个个赋值代替列举赋值来提升性能。 这样注释的: // doing this because it's faster than dynamic enumeration.
然后就是依次执行以下方法,包括各个init函数和触发钩子
/* istanbul ignore else */
if (process.env.NODE_ENV !== 'production') {
initProxy(vm)
} else {
vm._renderProxy = vm
}
// expose real self
vm._self = vm
initLifecycle(vm)
initEvents(vm)
initRender(vm)
callHook(vm, 'beforeCreate')
initState(vm)
callHook(vm, 'created')
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
2.state
initState一共做了如下操作
vm._watchers = []
const opts = vm.$options
if (opts.props) initProps(vm, opts.props)
if (opts.methods) initMethods(vm, opts.methods)
if (opts.data) {
initData(vm)
} else {
observe(vm._data = {}, true /* asRootData */)
}
if (opts.computed) initComputed(vm, opts.computed)
if (opts.watch) initWatch(vm, opts.watch)
initProps和initData的处理类似:
initProps做了类型检验,做了defineReactive就是响应式处理;
initData做了函数处理(data是对象或者函数),然后检查key是否与props重复,还检查了key是否$ 或者 _ 开头,这是vue内部使用, 如果你的key以此开头,你就会拿不到你的key了(这个好像没看到说明,感觉可以提示下)
然后做了个proxy,把用户参数props和data分别代理到 _props 和 _data 这2个内部属性,用户访问其实访问到了_props和_data下。
initMethods 这个就是把methods内部的函数bind到实例然后挂到实例
initWatch 通过遍历然后执行$watch方法来处理
initComputed 遍历为创建一个 Watcher 实例,然后放到_computedWatchers
(响应式相关后续再展开)
stateMixin 混入方法挂了$data,$props,$set,$delete等让数据操作指向_data 和 _props,然后挂了$watch 方法
3.events
挂载$on,$once,$off,$emit 四个方法
事件句柄都保存在 _events 这个属性里,在$on方法里做了个处理,判断该实例是否有使用生命周期的hook,如果没有_hasHookEvent这个值是false,然后在lifecycle的callHook方法里将不会$emit生命周期hook,是一个性能优化。
4.lifecycle
在原型上挂上 _mount 方法,这个比较重要, $mount 用的就是方法, ($mount在上面的init函数被调用)这个方法运行的时候需要用到render函数里了,没有会报错(关于这点,vue会把template或者el里的html模版最终转成render函数,一般如果我们用vue-loader开发,已经把template里的内容转成了render函数,所以最后打包出来的不会含有转化template的功能代码),render函数返回的是一个vnode,下面贴个_mount部分代码:
callHook(vm, 'beforeMount')
vm._watcher = new Watcher(vm, function updateComponent () {
vm._update(vm._render(), hydrating)
}, noop)
hydrating = false
// manually mounted instance, call mounted on self
// mounted is called for render-created child components in its inserted hook
if (vm.$vnode == null) {
vm._isMounted = true
callHook(vm, 'mounted')
}
这里可以看到2个生命周期了
_update 方法开始去做dom更新了,看_update方法
一开始用_isMounted判断是否触发beforeUpdate钩子,因为第一次插入dom也是调用这个方法,但是不应该触发beforeUpdate
然后就去调用 patch 方法去做diff 然后更新dom了。(vnode以后再看)
另外,还挂载了$forceUpdate和$destroy 这2个方法
5.render
先挂载了 $nextTick 方法.
然后在renderMixin函数内往原型挂载了_render 方法(在instancei 下有个render-helpers文件夹里面有处理render相关的工具函数供调用)这个方法做了slot相关的操作,然后调用render函数拿到vnode ( render 相关的需要具体展开)
这里有个_renderProxy ,在非生产环境下做了proxy,看 proxy.js ,就是在访问实例属性的时候,访问不存在的属性的时候给予提示.
Vue源码(一)的更多相关文章
- VUE 源码学习01 源码入口
VUE[version:2.4.1] Vue项目做了不少,最近在学习设计模式与Vue源码,记录一下自己的脚印!共勉!注:此处源码学习方式为先了解其大模块,从宏观再去到微观学习,以免一开始就研究细节然后 ...
- Vue源码后记-其余内置指令(3)
其实吧,写这些后记我才真正了解到vue源码的精髓,之前的跑源码跟闹着玩一样. go! 之前将AST转换成了render函数,跳出来后,由于仍是字符串,所以调用了makeFunction将其转换成了真正 ...
- Vue源码后记-钩子函数
vue源码的马拉松跑完了,可以放松一下写点小东西,其实源码讲20节都讲不完,跳了好多地方. 本人技术有限,无法跟大神一样,模拟vue手把手搭建一个MVVM框架,然后再分析原理,只能以门外汉的姿态简单过 ...
- 大白话Vue源码系列(01):万事开头难
阅读目录 Vue 的源码目录结构 预备知识 先捡软的捏 Angular 是 Google 亲儿子,React 是 Facebook 小正太,那咱为啥偏偏选择了 Vue 下手,一句话,Vue 是咱见过的 ...
- 大白话Vue源码系列(02):编译器初探
阅读目录 编译器代码藏在哪 Vue.prototype.$mount 构建 AST 的一般过程 Vue 构建的 AST 题接上文,上回书说到,Vue 的编译器模块相对独立且简单,那咱们就从这块入手,先 ...
- 大白话Vue源码系列(03):生成AST
阅读目录 AST 节点定义 标签的正则匹配 解析用到的工具方法 解析开始标签 解析结束标签 解析文本 解析整块 HTML 模板 未提及的细节 本篇探讨 Vue 根据 html 模板片段构建出 AST ...
- 大白话Vue源码系列(03):生成render函数
阅读目录 优化 AST 生成 render 函数 小结 本来以为 Vue 的编译器模块比较好欺负,结果发现并没有那么简单.每一种语法指令都要考虑到,处理起来相当复杂.上篇已经生成了 AST,本篇依然对 ...
- 大白话Vue源码系列(04):生成render函数
阅读目录 优化 AST 生成 render 函数 小结 本来以为 Vue 的编译器模块比较好欺负,结果发现并没有那么简单.每一种语法指令都要考虑到,处理起来相当复杂.上篇已经生成了 AST,本篇依然对 ...
- 大白话Vue源码系列(05):运行时鸟瞰图
阅读目录 Vue 实例的生命周期 实例创建 响应的数据绑定 挂载到 DOM 节点 结论 研究 runtime 一边 Vue 一边源码 初看 Vue 是 Vue 源码是源码 再看 Vue 不是 Vue ...
- vue源码入口文件分析
开发vue项目有段时间了, 之前用angularjs 后来用 reactjs 但是那时候一直没有时间把自己看源码的思考记录下来,现在我不想再浪费这 来之不易的思考, 我要坚持!! 看源码我个人感觉非常 ...
随机推荐
- java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\xB3' for column 'Content' at row 1
在尝试将 emoji 表情符号 插入MySQL数据库时,遇到以下错误信息: ### The error occurred while setting parameters ### SQL: INSER ...
- spring boot 教程(一) 构建我的第一个Spring boot
Spring Boot特点 1. 创建独立的Spring应用程序 2. 嵌入的Tomcat,无需部署WAR文件 3. 简化Maven配置 4. 自动配置Spring 5. 提供生产就绪型功能,如指标, ...
- postfix邮件服务器搭建03-webmail安装篇
本文接着上文的安装进行,介绍另一个WebMail功能更加人性化的roundcube.当然也可以对已有的postfix邮件系统进行功能完善 1.下载安装roundcube cd /server/tool ...
- Buildroot 指定内核版本
/******************************************************************************** * Buildroot 指定内核版本 ...
- I.MX6 修改调试串口号(ttymx0 -> ttymxc2)
I.MX6 修改调试串口号(ttymx0 -> ttymxc2) 一.参考文章: uboot修改默认调试串口ttymxc0 ->ttymxc4(imx53) http://www.xueb ...
- wait() ,notify() ,notifyAll(),synchronized 和同步方法锁,对象锁的联系,关系,区别;
一直不明白一个问题,因为在书上关于生产者和消费者的例子里看到一段这样的代码,估计很多人都和我一样迷惑 public synchronized void set(String name, String ...
- System.Net.FtpClient改进
项目用到Ftp,搜了下现有的类库System.Net.FtpClient 貌似比较不错. 一开始用着还行,但是有个FtpServer下有8k多内容,列表需要很久(7.8s)才能刷新出来. 翻源码吧,有 ...
- 编程技巧:使用整数同时进行多个true|false判断
情景 : 假设需要判断某银行用户的其中一个账号(profileA),币种(Currency)为人民币(CNY),余额是否大于1,0000,然后进行某业务逻辑处理. 概述: 为了进行这种判断,需要判断/ ...
- AngularX 路由总结
路由是 Angular 应用程序的核心,它加载与所请求路由相关联的组件,以及获取特定路由的相关数据.这允许我们通过控制不同的路由,获取不同的数据,从而渲染不同的页面. Installing the r ...
- C#-StructLayoutAttribute(结构体布局)
struct实例字段的内存布局(Layout)和大小(Size) 在C/C++中,struct类型中的成员的一旦声明,则实例中成员在内存中的布局(Layout)顺序就定下来了,即与成员声明的顺序相同, ...