vue内置组件
是 Vue 实现的一个内置组件,也就是说 Vue 源码不仅实现了一套组件化的机制,也实现了一些内置组件,关于组件,官网如下介绍:
是Vue中内置的一个抽象组件,它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
这句话的意思简单来说:就是我们可以把一些不常变动的组件或者需要缓存的组件用包裹起来,这样就会帮我们把组件保存在内存中,而不是直接的销毁,这样做可以保留组件的状态或避免多次重新渲染,以提高页面性能。
<div id="app">
<button @click="switchComp('child1')">组件1</button>
<button @click="switchComp('child2')">组件2</button>
<component :is="chooseComponent"></component>
</div>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue ...
vue全局API
与实例方法不同,实例方法是将方法挂载到Vue的原型上,而全局API是直接在Vue上挂载方法。在Vue中,全局API一共有12个,分别是Vue.extend、Vue.nextTick、Vue.set、Vue.delete、Vue.directive、Vue.filter、Vue.component、Vue.use、Vue.mixin、Vue.observable、Vue.version。这12个API中有的是我们在日常业务开发中经常会用到的,有的是对Vue内部或外部插件提供的,我们在日常业务开发中几乎用不到。
Vue.extendVue.extend( options )
参数{Object} options
作用使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。data 选项是特例,需要注意 - 在 Vue.extend() 中它必须是函数<div id="mount-point"></div>
// 创建构造器
var Profile = Vue.extend({
template: '<p>{{first ...
vue生命周期销毁阶段
当调用了vm.$destroy方法,Vue实例就进入了销毁阶段,该阶段所做的主要工作是将当前的Vue实例从其父级实例中删除,取消当前实例上的所有依赖追踪并且移除实例上的所有事件监听器。也就是说,当这个阶段完成之后,当前的Vue实例的整个生命流程就全部走完了
销毁阶段分析当调用了实例的$destroy方法之后,当前实例就进入了销毁阶段。所以分析销毁阶段就是分析$destroy方法的内部实现。该方法的定义位于源码的src/core/instance.lifecycle.js中,如下:
Vue.prototype.$destroy = function () {
const vm: Component = this
if (vm._isBeingDestroyed) {
return
}
callHook(vm, 'beforeDestroy')
vm._isBeingDestroyed = true
// remove self from parent
const parent = vm.$parent
if (pare ...
vue实例方法
数据相关的方法
vm.$set
vm.$delete
vm.$watch
事件相关的方法
vm.$on
vm.$emit
vm.$off
vm.$once
生命周期相关的方法
vm.$mount
vm.$forceUpdate
vm.$nextTick
vm.$destory
数据相关的方法与数据相关的实例方法有3个,分别是vm.$set、vm.$delete和vm.$watch。它们是在stateMixin函数中挂载到Vue原型上的,代码如下:
import {set,del} from '../observer/index'
// 当执行stateMixin函数后,会向Vue原型上挂载上述3个实例方法
export function stateMixin (Vue) {
Vue.prototype.$set = set
Vue.prototype.$delete = del
Vue.prototype.$watch = function (expOrFn,cb,options) {}
...
vue生命周期挂载阶段
模板编译阶段完成之后,接下来就进入了挂载阶段,从官方文档给出的生命周期流程图中可以看到,挂载阶段所做的主要工作是创建Vue实例并用其替换el选项对应的DOM元素,同时还要开启对模板中数据(状态)的监控,当数据(状态)发生变化时通知其依赖进行视图更新。
挂载阶段分析在完整版本的$mount方法中将模板编译完成之后,会回过头去调只包含运行时版本的$mount方法进入挂载阶段,所以要想分析挂载阶段我们必须从只包含运行时版本的$mount方法入手。
只包含运行时版本的$mount代码如下:
Vue.prototype.$mount = function (el,hydrating) {
el = el && inBrowser ? query(el) : undefined;
return mountComponent(this, el, hydrating)
};
可以看到,在该函数内部首先获取到el选项对应的DOM元素,然后调用mountComponent函数并将el选项对应的DOM元素传入,进入挂载阶段。
export function mou ...
vue生命周期-模板编译
前言在初始化阶段各项工作做完之后调用了vm.$mount方法,该方法的调用标志着初始化阶段的结束和进入下一个阶段,从官方文档给出的生命周期流程图中可以看到,下一个阶段就进入了模板编译阶段,该阶段所做的主要工作是获取到用户传入的模板内容并将其编译成渲染函数。
模板编译阶段并不是存在于Vue的所有构建版本中,它只存在于完整版(即vue.js)中。在只包含运行时版本(即vue.runtime.js)中并不存在该阶段,这是因为当使用vue-loader或vueify时,*.vue文件内部的模板会在构建时预编译成渲染函数,所以是不需要编译的,从而不存在模板编译阶段,由上一步的初始化阶段直接进入下一阶段的挂载阶段。
vue基于源码构建的有两个版本,一个是runtime only(一个只包含运行时的版本),另一个是runtime + compiler(一个同时包含编译器和运行时的完整版本)。而两个版本的区别仅在于后者包含了一个编译器。
完整版本一个完整的Vue版本是包含编译器的,我们可以使用template选项进行模板编写。编译器会自动将template选项中的模板字符串编译成渲染函数的代码,源码 ...
vue生命周期-初始化阶段
new Vue()初始化阶段所做的第一件事就是new Vue()创建一个Vue实例,那么new Vue()的内部都干了什么呢? 我们知道,new 关键字在 JS中表示从一个类中实例化出一个对象来,由此可见, Vue 实际上是一个类。所以new Vue()实际上是执行了Vue类的构造函数
做了什么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)
}
可以看到,Vue类的定义非常简单,其构造函数核心就一行代码:this._init(options)
调用原型上的_init(options)方法并把用户所写的选项options传入。那这个_init方法是从哪来的呢?
initM ...
vue生命周期综述
在Vue中,把Vue实例从被创建出来到最终被销毁的这一过程称为Vue实例的生命周期,同时,在Vue实例生命周期的不同阶段Vue还提供了不同的钩子函数,以方便用户在不同的生命周期阶段做一些额外的事情
初始化阶段:为Vue实例上初始化一些属性,事件以及响应式数据;
模板编译阶段:将模板编译成渲染函数;
挂载阶段:将实例挂载到指定的DOM上,即将模板渲染到真实DOM中;
销毁阶段:将实例自身从父组件中删除,并取消依赖追踪及事件监听器;
vue模板编译-模板解析
整体流程在模板解析阶段主要做的工作是把用户在标签内写的模板使用正则等方式解析成抽象语法树(AST)。而这一阶段在源码中对应解析器(parser)模块。
解析器,顾名思义,就是把用户所写的模板根据一定的解析规则解析出有效的信息,最后用这些信息形成AST。我们知道在模板内,除了有常规的HTML标签外,用户还会一些文本信息以及在文本信息中包含过滤器。而这些不同的内容在解析起来肯定需要不同的解析规则,所以解析器不可能只有一个,它应该除了有解析常规HTML的HTML解析器,还应该有解析文本的文本解析器以及解析文本中如果包含过滤器的过滤器解析器。
另外,文本信息和标签属性信息却又是存在于HTML标签之内的,所以在解析整个模板的时候它的流程应该是这样子的:HTML解析器是主线,先用HTML解析器进行解析整个模板,在解析过程中如果碰到文本内容,那就调用文本解析器来解析文本,如果碰到文本中包含过滤器那就调用过滤器解析器来解析。如下图所示:
// 代码位置:/src/complier/parser/index.js
/**
* Convert HTML string to AST.
*/
export ...
diff算法
创建节点
删除节点
更新节点
patch在Vue中,把 DOM-Diff过程叫做patch过程。patch,意为“补丁”,即指对旧的VNode修补,打补丁从而得到新的VNode,非常形象哈。那不管叫什么,其本质都是把对比新旧两份VNode的过程。我们在下面研究patch过程的时候,一定把握住这样一个思想:所谓旧的VNode(即oldVNode)就是数据变化之前视图所对应的虚拟DOM节点,而新的VNode是数据变化之后将要渲染的新的视图所对应的虚拟DOM节点,所以我们要以生成的新的VNode为基准,对比旧的oldVNode,如果新的VNode上有的节点而旧的oldVNode上没有,那么就在旧的oldVNode上加上去;如果新的VNode上没有的节点而旧的oldVNode上有,那么就在旧的oldVNode上去掉;如果某些节点在新的VNode和旧的oldVNode上都有,那么就以新的VNode为准,更新旧的oldVNode,从而让新旧VNode相同。总体来说就是以新的标准,多的加上去,少的删掉,将老的改成新的
创建节点
判断是否为元素节点只需判断该VNode节点是否有tag标签即可。如果 ...