Commit df64ebc4 by jiangqifan

add Vue源码

parent eaca008b
# Vue源码分析
# Vue源码分析
## 目录结构
我们先看看vue的git库中的目录结构:
```
-scripts
-dist
-flow
-packages
-test
-src
--compiler
--core
--platforms
--server
--sfc
--shared
```
- `scripts`构建相关脚本和配置文件
- `dist`构建结果
- `flow` Flow 需要用到的类型声明(Flow可以为JavaScript做静态类型检查), 不过vue正在往`TypeScript`上转,估计Vue3里面就没有这个目录了。
- `packages` 包含`vue-server-renderer``vue-template-compiler`, 会单独发布成npm里的package。
- `src` 自然就是Vue的源码了,代码是基于`ES6``Flow`的。
- `shared`目录下有两个文件, 分别为`constants``util`, 分别是一些常量和工具方法,可以先忽略。
- `src` 目录中是用来编译但文件(`*.vue`)组件的逻辑.在 `vue-template-compiler`中会用到.
- `server`目录中是用于服务端渲染的代码
- `platforms`中是跟平台有关的代码,每个平台分别有`compiler`,`runtime`,`server` 三部分, 目前有web和weex两种
- `core`包含通用的跟平台无关的代码,里面又分为
- `observer` 包含响应式系统的代码
- `vdom` 包含虚拟dom相关的代码
- `instance` 包含Vue实例的构造函数和原型方法
- `global-api` 全局api
- `components` 通用抽象组件,目前只有keep-alive
- `compiler` 包含将template编译成render函数的代码
## instance
instance中的index.js文件中的代码非常简单,如下可见,在Vue的构造函数中只有一行关键代码是调用`_init`方法.
```javascript
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)
```
那个Vue类又哪些方法呢,主要就是通过后面的几个Mixin函数往Vue.prototype上加的一些方法了。
`initMixin`中主要是增加了`__init`这个方法,主要内容为:
- 合并参数。把当前组件的参数和Vue.options进行合并。这里对于内置组件有优化,因为动态参数合并实在是太慢,但是内置组件都不需要。
- [非生产环境]components检查
- 标准化Props
- 标准化inject
- 标准化Directives
- 如果有extends,则会把extends中的组件拿过来一起合并
- 如果有mixins,则一起参与合并
- 合并
- [非生产环境],会创建了一个Proxy对象,放在实例的`_renderProxy`属性上。 这个Proxy里逻辑是当访问的属性不存在的时候,会报提示,所以应该是为了方便开发期容易发现错误而做的处理。
- 初始化声明周期,这个这是将自己加在parent的`$chilren`属性中并为自己设置上`$parent`属性的值,然后把各种跟声明周期相关的标识设置成false。
- 初始化Events
- 初始化Render
- 调用钩子函数`beforeCreate`
- 初始化Injections
- 初始化状态
- 初始化Provide
- 调用钩子函数`created`
- [非生产环境], 记录一些性能数据
- 如果有参数中有`el`属性,则调用`$mount`方法进行挂载
> provide和inject是2.2.0新增的,主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。
>
> 这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的上下文特性很相似。
其中的参数合并可以举个例子。 我们有个prop-mixin.js:
```javascript
export default {
props:{
name:String
}
}
```
和一个组件Item.vue
```javascript
import PropMixin from './prop-mixin.js'
export default {
mixin: [PropMixin],
props: {
title: String
}
}
```
合并之后就变成了
```javascript
{
mixin: [PropMixin],
props: {
name: {
type: String,
},
title: {
type: String
}
}
}
```
## 响应式系统
src/observer中的目录结构如下:
```
-array.js
-dep.js
-index.js
-scheduler.js
-traverse.js
-watcher.js
```
`watcher``Dep`分别提供了类`Watcher``Dep`;
`index`文件中提供了一个类`Observer` 和几个方法如如下:
```javascript
export class Observer
export function toggleObserving (value: boolean)
export function observe (value: any, asRootData: ?boolean): Observer | void
export function defineReactive (
obj: Object,
key: string,
val: any,
customSetter?: ?Function,
shallow?: boolean
)
export function set (target: Array<any> | Object, key: any, val: any): any
export function del (target: Array<any> | Object, key: any)
```
`Wacher`,`Dep`,`Observer`的关系为:
![](/Users/jiangqifan/Documents/技术研究/复习/assets/observer.png)
`Watcher`代表一个监听器,会解析表达式收集依赖,以及在表达式中的值发生变化时触发回调。
为需要监听的数据对象创建一个Observer对象,在Observer的构造函数中,会遍历每一个属性及属性的属性,分别调用`defineReactive`方法。`defineReactive`方法的逻辑为: 创建一个Dep对象,然后利用`Object.defineProperty`指定改属性的get和set方法。 在get方法中,
...@@ -411,3 +411,29 @@ react 和 vue的区别? ...@@ -411,3 +411,29 @@ react 和 vue的区别?
> 优化渲染: js写在最后面, 图片懒加载, ssr,减少dom操作(合并操作,缓存查询结果) > 优化渲染: js写在最后面, 图片懒加载, ssr,减少dom操作(合并操作,缓存查询结果)
### vuex的原理
vue兄弟组件之间通信
如何让一段逻辑在vue更新了dom之后执行
update和nextTick的顺序
nextTick的原理
### 定高元素和不定高元素的垂直居中
### 定宽元素和不定宽元素的水平居中
### 防抖和节流
###setTimout(fn,0)是同步还是异步
###Promise.resolve()是同步还是异步
###CSS3有哪些新东西
怎么实现动画 怎么让元素扩大一倍
ES6新增了哪些东西
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment