首页 技术 正文
技术 2022年11月22日
0 收藏 614 点赞 2,282 浏览 6132 个字

Vue源码学习二 是对Vue的原型对象的包装,最后从Vue的出生文件导出了 Vue这个构造函数

来到 src/core/index.js 代码是:

    import Vue from './instance/index'    import { initGlobalAPI } from './global-api/index'    import { isServerRendering } from 'core/shared/env'    import { FunctionalRenderContext } from 'core/vdom/create-functional-component'    // 将 Vue 构造函数作为参数, 传递给 initGlobalAPI 方法    // 向Vue.prototype 上添加一些静态属性和方法    initGlobalAPI(Vue)    Object.defineProperty(Vue.prototype, '$isServer', {      get: isServerRendering    })    Object.defineProperty(Vue.prototype, '$ssrContext', {      get () {        /* istanbul ignore next */        return this.$vnode && this.$vnode.ssrContext      }    })    // expose FunctionalRenderContext for ssr runtime helper installation    Object.defineProperty(Vue, 'FunctionalRenderContext', {      value: FunctionalRenderContext    })    Vue.version = '__VERSION__'    // http://hcysun.me/vue-design/art/2vue-constructor.html#with-compiler    export default Vue

看第一句 import Vue from './instance/index', 导入了Vue这个构造函数,且原型在上面已经添加了一些属性和方法。

然后 initGlobalAPI(Vue)执行 initGlobalAPI 方法并且将 Vue构造函数就为参数调用。
又再 Vue的原型上添加了两个只读的属性 $isServer、$ssrContext。并且再 Vue构造函数上定义了 FunctionalRenderContext静态属性,之所以在 Vue构造函数上定义,是因为在 ssr的时候要使用它。最后 Vue.version = '__VERSION__'又在 Vue构造函数上定义了version,即版本号。

然后再看 initGlobalAPI 方法的来源地, 它主要是丰富 Vue构造函数,在构造函数上添加静态属性和方法。import { initGlobalAPI } from ‘./global-api/index’。 来到 ./global-api/index.js文件中

export function initGlobalAPI (Vue: GlobalAPI) {  // config  const configDef = {}  configDef.get = () => config  if (process.env.NODE_ENV !== 'production') {    configDef.set = () => {      warn(        'Do not replace the Vue.config object, set individual fields instead.'      )    }  }  // Vue构造函数上添加config属性, 也是只读的属性。  // Vue.config 代理的是从../config文件导出的对象  Object.defineProperty(Vue, 'config', configDef)

首先是这样的一段代码, 这段代码是在 Vue构造函数上添加 config属性, 他也是一个只读的属性,和 $data$prop是一样的。当你试图修改这个属性时,在非生产环境下会给你提醒warn
这个 config从哪里来的呢, 这个文件的最顶部 import config from '../config'
所以 Vue.config 代理的是从 core/config导入的config对象。

然后是这样一段代码:

 // exposed shared methods.  // NOTE: these are not considered part of the public API - avoid relying on  // them unless you are aware of the risk.  Vue.util = {    warn,    extend,    mergeOptions,    defineReactive  }

这是在Vue原型上添加了一个 util属性,它是一个对象。这个对象有四个属性 warn、extend、mergeOptions、defineReactive。他们都是来自于 src/core/util/index文件中。官网上没有这些api的说明, 也不推荐使用。

然后是一段这样的代码:

  Vue.set = set  Vue.delete = del  Vue.nextTick = nextTick  // options 通过Object.create()创建的一个空对象  Vue.options = Object.create(null)

上面这段代码是在 Vue构造函数上又添加了四个属性 set、delete、nextTickoptionsoptions是通过 Object.create(null)创建的一个空对象。下面的代码即丰富了 options这个对象。

   ASSET_TYPES.forEach(type => {      Vue.options[type + 's'] = Object.create(null)  })  // this is used to identify the "base" constructor to extend all plain-object  // components with in Weex's multi-instance scenarios.  Vue.options._base = Vue

ASSET_TYPES是上面呢?很明显他是一个数组,遍历它的每一个属性 + s 并且添加到 Vue.options上。并且初始赋值的都是 Object.create(null)。看一下 ASSET_TYPES来自src/shared/constants.js文件。

export const ASSET_TYPES = [  'component',  'directive',  'filter']

可以看到 ASSET_TYPES是这么一个数组。原来是通过遍历向 Vue.options中添加 components、directives、filters

到目前,Vue.options现在是这样样子:

Vue.options = {    components: Object.create(null),    directives: Object.create(null),    filters: Object.create(null),    _base: Vue}

然后继续向下看是这样的一句代码

extend(Vue.options.components, builtInComponents)

extend是 Vue的一个工具方法,在 src/shared/util.js文件中

/** * Mix properties into target object. */export function extend (to: Object, _from: ?Object): Object {  for (const key in _from) {    to[key] = _from[key]  }  return to}

主要作用是将一个对象的属性混入到另外一个对象中。
那么上面的 extend(Vue.options.components, builtInComponents)的意思就是将 builtInComponents对象的属性混入到 Vue.options.components对象中。那么builtInComponents对象是啥呢? 来到 src/core/components/indes.js文件中:

import KeepAlive from './keep-alive'export default {  KeepAlive}

就是将 KeepAlive 这个属性添加到 Vue.options.conponents中。

那么到目前为止, Vue.options对象已经变成了这个样子

Vue.options = {    components: {        KeepAlive    },    directives: Object.create(null),    filters: Object.create(null),    _base: Vue}

再看这个文件的最后一部分代码

  initUse(Vue)  initMixin(Vue)  initExtend(Vue)  initAssetRegisters(Vue)

依此调用了四个方法,都是将 Vue这个构造函数作为其参数。initUse、initMixin、initExtend、initAssetRegisters四个方法分别来自 ./global-api/use.js./global-api/mixin.js./global-api/extend.js./global-api/assets.js文件。

先看 initUse文件:

// 全局的 Vue.use()  用来安装插件的方法export function initUse (Vue: GlobalAPI) {  Vue.use = function(){}}

该方法的主要作用是在 Vue上添加 use方法,也就是用来安装 Vue插件的全局API Vue.use()

initMixin文件

// 在Vue上添加mixin的全局APIexport function initMixin (Vue: GlobalAPI) {  Vue.mixin = function (mixin: Object) {    this.options = mergeOptions(this.options, mixin)    return this  }}

initMixin方法的主要作用是在 Vue原型上添加 mixin这个全局API。再看 initExtend

initExtend文件

export function initExtend (Vue: GlobalAPI) {  /**   * Each instance constructor, including Vue, has a unique   * cid. This enables us to create wrapped "child   * constructors" for prototypal inheritance and cache them.   */  Vue.cid = 0  let cid = 1  /**   * Class inheritance   */  // 使用基础Vue构造器, 创建一个"子类", 参数是一个包含组件选项的对象  // API 详细 https://cn.vuejs.org/v2/api/#Vue-extend  // ...  Vue.extend = function (extendOptions: Object): Function {  }}

这个方法在 Vue构造函数上添加了 cid、extend一个静态属性和一个静态方法。

最后一个 initAssetRegisters文件

import { ASSET_TYPES } from 'shared/constants'import { isPlainObject, validateComponentName } from '../util/index'export function initAssetRegisters (Vue: GlobalAPI) {  /**   * Create asset registration methods.   */  ASSET_TYPES.forEach(type => {    Vue[type] = function (){}}

ASSET_TYPES这个文件前面见到过:

export const ASSET_TYPES = [  'component',  'directive',  'filter']

这个方法的主要作用是在 Vue 构造函数上添加全局的 component、directive、filter, 分别用来注册 全局组件、指令、过滤器的。

initGlobalAPI这个方法就说完了。就是在 Vue这个构造函数上定义静态属性和方法。Vue的出生文件是在 Vue原型对象上丰富了内容,现在又再 Vue构造函数上丰富了内容。

到现在 Vue 构造函数上有以下属性和方法

// initGlobalAPIVue.configVue.util = {    warn,    extend,    mergeOptions,    defineReactive}Vue.set = setVue.delete = delVue.nextTick = nextTickVue.options = {    components: {        KeepAlive    },    directives: Object.create(null),    filters: Object.create(null),    _base: Vue}// initUse ***************** global-api/use.jsVue.use = function (plugin: Function | Object) {}// initMixin ***************** global-api/mixin.jsVue.mixin = function (mixin: Object) {}// initExtend ***************** global-api/extend.jsVue.cid = 0Vue.extend = function (extendOptions: Object): Function {}// initAssetRegisters ***************** global-api/assets.jsVue.component =Vue.directive =Vue.filter = function (  id: string,  definition: Function | Object): Function | Object | void {}// expose FunctionalRenderContext for ssr runtime helper installationObject.defineProperty(Vue, 'FunctionalRenderContext', {  value: FunctionalRenderContext})Vue.version = '__VERSION__'
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,026
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,517
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,364
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,145
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,779
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,856