vue04-源码学习方法

项目地址:https://github.com/vuejs/vue

迁出项目:git clone https://github.com/vuejs/vue.git

 

目录机构:

dist:最终输出目标,运行在不同的运行时里

examples:官方准备的案例

flows:(类型声明)vue2用flows语言编写,类似于ts,强类型编译语言,有一些语言的类型声明文件,明确告诉你都实现了那些方法及方法的签名是怎样的

packages:有一些独立的包如vue-server-render:vue服务端渲染器;作为一些独立的包存在,和vue的核心功能有区分

scripts:打包的脚本,用什么方法打包,打包的配置,入口文件的查找跟此包息息相关

src:核心代码存放:compiler(编译器)、core(vue核心代码)、plateform(平台持有代码web weex)

server:服务端相关东西

sfc:单文件解析器

shared:少量共享代码

types:ts类型文件(专门为ts编写了一套文件)

 

调试环境搭建:

安装依赖:npm i

安装rollup:npm i -g rollup (打包工具,与webpack的区别在于他用于纯js库的编写)

修改dev脚本,添加sourcemap -> package.json

"dev":"rollup -w -c scripts/config.js --sourcemap --environment TARGE:web-full-dev"

运行:npm run dev

//运行完可看见文件的入口:entry-runtime-with-compiler.js   

验证是否成功:dist下的vue.js目录颜色变了;多了vue.js.map文件

写一个html文件,将dist/vue.js引进去就可以了,打开文件就可以了调试了,F12-sources-有src目录(所有源码的结构,刚才的步骤代表成功)-文件-打断点-调试

 

dist文件中,输出版本的术语:

common关键字:nodejs模块,叫cjs,运行在旧版打包器webpack1,broswerify

esm:es模块化规范,常用语webpack2+  不带编译器

umd(无后缀):兼容cjs和amd规范,常用语浏览器,但也可用于服务端

runtime:说明输出的库仅有核心运行时代码,没有编译器

 

寻找入口文件的方法:

package.json文件中,scripts下的dev的配置中-c后面的文件就是配置文件(scripts/config.js),最终的输出目标是(TARGET:web-full-dev),打开配置文件,寻找web-full-dev关键字,就找到了入口文件

 

 如何找到web/entry-runtime-with-compiler.js,核心在resolve里,当前文件找到resolve方法

 

他是传入一个地址,然后将地址稍微做一下处理,转为一个绝对地址出去,(通过/分开两部分,web和文件名,web会通过aliases里查找具体路径,)我们打开./alias文件,找到web对应的源码路,再加上后面的后缀名找到具体文件(src/plateforms/web/entry-runtime-with-compiler.js)

vue的初始化流程:

根据上一节vue03的流程图,vue的整体流程是两条线,第一条是初始化这条线;第二条是更新的这条线;我们研究第一条初始化流程

整体流程:(只大致说下实现了什么,不上源码图了,大家根据源码对照着看)

1.入口:src/platforms/web/entry-runtime-with-compiler.js

   入口文件主要做的事情:首先获取原始$mount方法,并扩展;然后处理跟render/template/el相关的选项(优先级:render>template>el) ;然后开始编译,将用户编写的模板转换为渲染函数(compileToFunctions实现);最后执行挂载(虚拟DOM转化为真实     DOM)

2.Vue的构造函数:图中初始化的点是Vue构造函数,入口文件中Vue的引入在runtime/index,我们打开这个文件

  

  src/platforms/web/runtime/index:首先定义补丁函数patch(patch()做更新,将虚拟DOM变为真实DOM),定义挂载函数$mount(对函数mountComponent的调用,挂载逻辑需研究此函数,主要实习渲染<获取vdom>、更新<将vdom转换为dom>)

  此文件未找到Vue的构造函数,此文件中找到Vue的引入在core/index,我们打开这个文件

  

   src/core/index:初始化全局API(initGlobalAPI(Vue));定义一些属性,看起来和服务端渲染有关直接跳过去,主要实现全局API,点进去看一下这个方法

    initGlobalAPI(Vue):主要实现声明全局API,(我们随便打开里面的inituse方法看一下,我们就知道为什么Vue.use()方法会调用插件的install方法了);

  此文件中也没有Vue的初始化,根据引入的地址我们找instance/index

  

 src/core/instance/index.js:终于找到了----初始化中只执行了init方法,我们回想那张图,初始化中执行了init方法

  

   init方法是哪来的,我们看下面有或多Mixin方法,典型的混入模式,对Vue进行扩展,我们看一下怎么进行混入的,initMixin方法来自./init文件,我们点进去看一下,只给了原型一个init的方法,实现了扩展,如果研究初始化方法,init就是核心方法

  

   看一下里面的核心代码,进行一些初始化,初始化顺序:生命周期,事件监听,渲染,beforeCreate,注入,组件状态(数据,属性,methods,watch),数据响应化,提供数据,created;然后如果存在el宿主,则执行挂载---(进入入口文件);

   

        initLifecycle():初始化声明$parent,$root,$children,$refs等

  initEvent():事件监听的开始,事件的起始点

  initRender():渲染相关的东西($slots,$scopedSlots,$createElement,_c) 

数据响应式:

  mvvm框架最大特点数据响应式

  ·对象响应式:Object.defineProperty

  ·数组响应式:  

   src/core/instance/state.js----initState方法

   数据响应化定义

异步更新队列:

  •  vue更新dom是异步的:修改了一个data,dom不会立刻更新(updata()------》queueWatcher(this)-----》nextTick())
  • 是批量的:对同一个数据的连续同一个操作,他不会执行多次
原文地址:https://www.cnblogs.com/znLam/p/12920724.html