Open huixisheng opened 5 years ago
$ yarn $ cd packages/vue-server-renderer && yarn $ cd packages/weex-vue-framework && yarn $ npm run dev:test
"dev:test": "karma start test/unit/karma.dev.config.js", 加载相关测试用例 test/unit/index.js
"dev:test": "karma start test/unit/karma.dev.config.js",
test/unit/index.js
components directives filter global-api instance options transition debug error-handling ref
以上可以对照 Api 文档 https://cn.vuejs.org/v2/api/
Vue 核心模块
compiler observer server-compoler sfc util vdom
库入口 src/platforms/web/entry-runtime-with-compiler 。对应文档的完整版
src/platforms/web/entry-runtime-with-compiler
module.exports = { vue: resolve('src/platforms/web/entry-runtime-with-compiler'), compiler: resolve('src/compiler'), core: resolve('src/core'), shared: resolve('src/shared'), web: resolve('src/platforms/web'), weex: resolve('src/platforms/weex'), server: resolve('src/server'), entries: resolve('src/entries'), sfc: resolve('src/sfc') }
object instanceof constructor
instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。
src/platforms/web/entry-runtime-with-compiler.js import Vue from './runtime/index' // src/platforms/web/runtime/index.js const mount = Vue.prototype.$mount Vue.prototype.$mount // Compile Template compileToFunctions mount.call src/platforms/web/runtime/index.js Vue.config.mustUseProp/isReservedTag/isReservedAttr/getTagNamespace/isUnknownElement Vue.options.directives Vue.options.components Vue.prototype.__patch__ Vue.prototype.$mount mountComponent beforeMount updateComponent mounted beforeUpdate updated // 手动调用 $destroy callHook(vm, 'beforeDestroy') vm._watcher.teardown() callHook(vm, 'destroyed') src/core/index.js import Vue from './instance/index' initGlobalAPI Vue.config // 不是公开的 API Vue.util.* Vue.set/delete Vue.nextTick Vue.observable // 2.6 Vue.options.components、directives、filters Vue.use Vue.mixin Vue.extend Vue.components、directives、filters Vue.prototype.$isServer Vue.prototype.$ssrContext Vue.FunctionalRenderContext Vue.version src/core/instance/index.js function Vue (options) { this._init(options) } initMixin(Vue) Vue.prototype.__init // 初始化组件的属性 initInternalComponent // 数据绑定? initProxy vm._self = vm // 初始化生命周期 initLifecycle(vm) initEvents(vm) initRender(vm) callHook(vm, 'beforeCreate') initInjections(vm) // resolve injections before data/props defineReactive // Define a reactive property on an Object. initState(vm) initProps initMethods initData initWatch initProvide(vm) // resolve provide after data/props callHook(vm, 'created') vm.$mount(vm.$options.el) stateMixin(Vue) Vue.prototype.$data Vue.prototype.$props Vue.prototype.$set、$delete Vue.prototype.$watch eventsMixin(Vue) Vue.prototype.$on Vue.prototype.$once Vue.prototype.$off Vue.prototype.$emit lifecycleMixin(Vue) Vue.prototype._update Vue.prototype.$forceUpdate Vue.prototype.$destroy renderMixin(Vue) Vue.prototype.$nextTick Vue.prototype._render
配置 jsconfig.json 方便代码跳转
重启 VSCode 才生效
{ "compilerOptions": { "target": "es2017", "baseUrl": "./", "paths": { "vue/*": ["src/platforms/web/entry-runtime-with-compiler/*"], "compiler/*": ["src/compiler/*"], "core/*": ["src/core/*"], "shared/*": ["src/shared/*"], "web/*": ["src/platforms/web/*"], "weex/*": ["src/platforms/weex/*"], "server/*": ["src/server/*"], "entries/*": ["src/entries/*"], "sfc/*": ["src/sfc/*"], } }, "exclude": ["node_modules", "dist"], "include": ["src/**/*"] }
关于 jasmine、karma、ChromeHeadless 参考 https://github.com/huixisheng/huixisheng.github.com/issues/80
jasmine
karma
ChromeHeadless
require.context
// require all test files const testsContext = require.context('./', true, /\.spec$/) testsContext.keys().forEach(testsContext)
ƒ webpackContext(req) id: "./test/helpers sync recursive ^\.\/.*$" keys: ƒ webpackContextKeys() resolve: ƒ webpackContextResolve(req) arguments: null caller: null length: 1 name: "webpackContext" prototype: {constructor: ƒ} __proto__: ƒ () [[FunctionLocation]]: .*$:19 [[Scopes]]: Scopes[2] webpackContext(req) { var id = webpackContextResolve(req); return __webpack_require__(id); }
src/unit/index.js 添加 debugger
src/unit/index.js
var map = { "./classlist": "./test/helpers/classlist.js", "./classlist.js": "./test/helpers/classlist.js", "./test-object-option": "./test/helpers/test-object-option.js", "./test-object-option.js": "./test/helpers/test-object-option.js", "./to-equal": "./test/helpers/to-equal.js", "./to-equal.js": "./test/helpers/to-equal.js", "./to-have-been-warned": "./test/helpers/to-have-been-warned.js", "./to-have-been-warned.js": "./test/helpers/to-have-been-warned.js", "./trigger-event": "./test/helpers/trigger-event.js", "./trigger-event.js": "./test/helpers/trigger-event.js", "./vdom": "./test/helpers/vdom.js", "./vdom.js": "./test/helpers/vdom.js", "./wait-for-update": "./test/helpers/wait-for-update.js", "./wait-for-update.js": "./test/helpers/wait-for-update.js" }; function webpackContext(req) { var id = webpackContextResolve(req); return __webpack_require__(id); } function webpackContextResolve(req) { var id = map[req]; if(!(id + 1)) { // check for number or string var e = new Error("Cannot find module '" + req + "'"); e.code = 'MODULE_NOT_FOUND'; throw e; } return id; } webpackContext.keys = function webpackContextKeys() { return Object.keys(map); }; webpackContext.resolve = webpackContextResolve; module.exports = webpackContext; webpackContext.id = "./test/helpers sync recursive ^\\.\\/.*$";
var map = { "./features/component/component-async.spec": "./test/unit/features/component/component-async.spec.js", "./features/component/component-keep-alive.spec": "./test/unit/features/component/component-keep-alive.spec.js", "./features/component/component-scoped-slot.spec": "./test/unit/features/component/component-scoped-slot.spec.js", "./features/component/component-slot.spec": "./test/unit/features/component/component-slot.spec.js", "./features/component/component.spec": "./test/unit/features/component/component.spec.js", "./features/debug.spec": "./test/unit/features/debug.spec.js", "./features/directives/bind.spec": "./test/unit/features/directives/bind.spec.js", "./features/directives/class.spec": "./test/unit/features/directives/class.spec.js", "./features/directives/cloak.spec": "./test/unit/features/directives/cloak.spec.js", "./features/directives/for.spec": "./test/unit/features/directives/for.spec.js", "./features/directives/html.spec": "./test/unit/features/directives/html.spec.js", "./features/directives/if.spec": "./test/unit/features/directives/if.spec.js", "./features/directives/model-checkbox.spec": "./test/unit/features/directives/model-checkbox.spec.js", "./features/directives/model-component.spec": "./test/unit/features/directives/model-component.spec.js", "./features/directives/model-dynamic.spec": "./test/unit/features/directives/model-dynamic.spec.js", "./features/directives/model-file.spec": "./test/unit/features/directives/model-file.spec.js", "./features/directives/model-parse.spec": "./test/unit/features/directives/model-parse.spec.js", "./features/directives/model-radio.spec": "./test/unit/features/directives/model-radio.spec.js", "./features/directives/model-select.spec": "./test/unit/features/directives/model-select.spec.js", "./features/directives/model-text.spec": "./test/unit/features/directives/model-text.spec.js", "./features/directives/on.spec": "./test/unit/features/directives/on.spec.js", "./features/directives/once.spec": "./test/unit/features/directives/once.spec.js", "./features/directives/pre.spec": "./test/unit/features/directives/pre.spec.js", "./features/directives/show.spec": "./test/unit/features/directives/show.spec.js", "./features/directives/static-style-parser.spec": "./test/unit/features/directives/static-style-parser.spec.js", "./features/directives/style.spec": "./test/unit/features/directives/style.spec.js", "./features/directives/text.spec": "./test/unit/features/directives/text.spec.js", "./features/error-handling.spec": "./test/unit/features/error-handling.spec.js", "./features/filter/filter.spec": "./test/unit/features/filter/filter.spec.js", "./features/global-api/assets.spec": "./test/unit/features/global-api/assets.spec.js", "./features/global-api/compile.spec": "./test/unit/features/global-api/compile.spec.js", "./features/global-api/config.spec": "./test/unit/features/global-api/config.spec.js", "./features/global-api/extend.spec": "./test/unit/features/global-api/extend.spec.js", "./features/global-api/mixin.spec": "./test/unit/features/global-api/mixin.spec.js", "./features/global-api/observable.spec": "./test/unit/features/global-api/observable.spec.js", "./features/global-api/set-delete.spec": "./test/unit/features/global-api/set-delete.spec.js", "./features/global-api/use.spec": "./test/unit/features/global-api/use.spec.js", "./features/instance/init.spec": "./test/unit/features/instance/init.spec.js", "./features/instance/methods-data.spec": "./test/unit/features/instance/methods-data.spec.js", "./features/instance/methods-events.spec": "./test/unit/features/instance/methods-events.spec.js", "./features/instance/methods-lifecycle.spec": "./test/unit/features/instance/methods-lifecycle.spec.js", "./features/instance/properties.spec": "./test/unit/features/instance/properties.spec.js", "./features/instance/render-proxy.spec": "./test/unit/features/instance/render-proxy.spec.js", "./features/options/_scopeId.spec": "./test/unit/features/options/_scopeId.spec.js", "./features/options/comments.spec": "./test/unit/features/options/comments.spec.js", "./features/options/components.spec": "./test/unit/features/options/components.spec.js", "./features/options/computed.spec": "./test/unit/features/options/computed.spec.js", "./features/options/data.spec": "./test/unit/features/options/data.spec.js", "./features/options/delimiters.spec": "./test/unit/features/options/delimiters.spec.js", "./features/options/directives.spec": "./test/unit/features/options/directives.spec.js", "./features/options/el.spec": "./test/unit/features/options/el.spec.js", "./features/options/errorCaptured.spec": "./test/unit/features/options/errorCaptured.spec.js", "./features/options/extends.spec": "./test/unit/features/options/extends.spec.js", "./features/options/functional.spec": "./test/unit/features/options/functional.spec.js", "./features/options/inheritAttrs.spec": "./test/unit/features/options/inheritAttrs.spec.js", "./features/options/inject.spec": "./test/unit/features/options/inject.spec.js", "./features/options/lifecycle.spec": "./test/unit/features/options/lifecycle.spec.js", "./features/options/methods.spec": "./test/unit/features/options/methods.spec.js", "./features/options/mixins.spec": "./test/unit/features/options/mixins.spec.js", "./features/options/name.spec": "./test/unit/features/options/name.spec.js", "./features/options/parent.spec": "./test/unit/features/options/parent.spec.js", "./features/options/props.spec": "./test/unit/features/options/props.spec.js", "./features/options/propsData.spec": "./test/unit/features/options/propsData.spec.js", "./features/options/render.spec": "./test/unit/features/options/render.spec.js", "./features/options/renderError.spec": "./test/unit/features/options/renderError.spec.js", "./features/options/template.spec": "./test/unit/features/options/template.spec.js", "./features/options/watch.spec": "./test/unit/features/options/watch.spec.js", "./features/ref.spec": "./test/unit/features/ref.spec.js", "./features/transition/transition-group.spec": "./test/unit/features/transition/transition-group.spec.js", "./features/transition/transition-mode.spec": "./test/unit/features/transition/transition-mode.spec.js", "./features/transition/transition.spec": "./test/unit/features/transition/transition.spec.js", "./modules/compiler/codeframe.spec": "./test/unit/modules/compiler/codeframe.spec.js", "./modules/compiler/codegen.spec": "./test/unit/modules/compiler/codegen.spec.js", "./modules/compiler/compiler-options.spec": "./test/unit/modules/compiler/compiler-options.spec.js", "./modules/compiler/optimizer.spec": "./test/unit/modules/compiler/optimizer.spec.js", "./modules/compiler/parser.spec": "./test/unit/modules/compiler/parser.spec.js", "./modules/observer/dep.spec": "./test/unit/modules/observer/dep.spec.js", "./modules/observer/observer.spec": "./test/unit/modules/observer/observer.spec.js", "./modules/observer/scheduler.spec": "./test/unit/modules/observer/scheduler.spec.js", "./modules/observer/watcher.spec": "./test/unit/modules/observer/watcher.spec.js", "./modules/server-compiler/compiler-options.spec": "./test/unit/modules/server-compiler/compiler-options.spec.js", "./modules/server-compiler/optimizer.spec": "./test/unit/modules/server-compiler/optimizer.spec.js", "./modules/sfc/sfc-parser.spec": "./test/unit/modules/sfc/sfc-parser.spec.js", "./modules/util/invoke-with-error-handling.spec": "./test/unit/modules/util/invoke-with-error-handling.spec.js", "./modules/util/next-tick.spec": "./test/unit/modules/util/next-tick.spec.js", "./modules/vdom/create-component.spec": "./test/unit/modules/vdom/create-component.spec.js", "./modules/vdom/create-element.spec": "./test/unit/modules/vdom/create-element.spec.js", "./modules/vdom/modules/attrs.spec": "./test/unit/modules/vdom/modules/attrs.spec.js", "./modules/vdom/modules/class.spec": "./test/unit/modules/vdom/modules/class.spec.js", "./modules/vdom/modules/directive.spec": "./test/unit/modules/vdom/modules/directive.spec.js", "./modules/vdom/modules/dom-props.spec": "./test/unit/modules/vdom/modules/dom-props.spec.js", "./modules/vdom/modules/events.spec": "./test/unit/modules/vdom/modules/events.spec.js", "./modules/vdom/modules/style.spec": "./test/unit/modules/vdom/modules/style.spec.js", "./modules/vdom/patch/children.spec": "./test/unit/modules/vdom/patch/children.spec.js", "./modules/vdom/patch/edge-cases.spec": "./test/unit/modules/vdom/patch/edge-cases.spec.js", "./modules/vdom/patch/element.spec": "./test/unit/modules/vdom/patch/element.spec.js", "./modules/vdom/patch/hooks.spec": "./test/unit/modules/vdom/patch/hooks.spec.js", "./modules/vdom/patch/hydration.spec": "./test/unit/modules/vdom/patch/hydration.spec.js" }; function webpackContext(req) { var id = webpackContextResolve(req); return __webpack_require__(id); } function webpackContextResolve(req) { var id = map[req]; if(!(id + 1)) { // check for number or string var e = new Error("Cannot find module '" + req + "'"); e.code = 'MODULE_NOT_FOUND'; throw e; } return id; } webpackContext.keys = function webpackContextKeys() { return Object.keys(map); }; webpackContext.resolve = webpackContextResolve; module.exports = webpackContext; webpackContext.id = "./test/unit sync recursive \\.spec$";
/******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = "/_karma_webpack_/"; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = "./test/unit/index.js"); /******/ }) /************************************************************************/
安装依赖
根据测试用例看代码
"dev:test": "karma start test/unit/karma.dev.config.js",
加载相关测试用例test/unit/index.js
以上可以对照 Api 文档 https://cn.vuejs.org/v2/api/
Vue 核心模块
代码流程
库入口
src/platforms/web/entry-runtime-with-compiler
。对应文档的完整版object instanceof constructor
instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。
VSCode 代码跳转
配置 jsconfig.json 方便代码跳转
相关知识点
关于
jasmine
、karma
、ChromeHeadless
参考 https://github.com/huixisheng/huixisheng.github.com/issues/80require.context
src/unit/index.js
添加 debugger