https://vue3js.cn/global/

调试环境搭建

  1. git clone https://github.com/vuejs/vue-next.git
  • 安装依赖: yarn

    1. yarn install
  • 生成sourcemap文件,package.json

    1. "dev": "node scripts/dev.js --sourcemap"
  • 编译:yarn dev

  • 生成结果:packages\vue\dist\vue.global.js

结构:源码位置是在package文件件内,实际上源码主要分为两部分,编译器和运行时环境。
image.png

  • 编译器

    • compiler-core 核心编译逻辑
    • compiler-dom 针对浏览器平台编译逻辑
    • compiler-sfc 针对单文件组件编译逻辑
    • compiler-ssr 针对服务端渲染编译逻辑
  • 运行时环境

    • runtime-core 运行时核心
    • runtime-dom 运行时针对浏览器的逻辑
    • runtime-test 浏览器外完成测试环境仿真
  • reactivity 响应式逻辑
  • template-explorer 模板浏览器
  • server-renderer 服务器端渲染
  • share 公用方法
  • vue 代码入口,整合编译器和运行时
    1. +---------------------+ +----------------------+
    2. | | | |
    3. +------------>| @vue/compiler-dom +--->| @vue/compiler-core |
    4. | | | | |
    5. +----+----+ +---------------------+ +----------------------+
    6. | |
    7. | vue |
    8. | |
    9. +----+----+ +---------------------+ +----------------------+ +-------------------+
    10. | | | | | | |
    11. +------------>| @vue/runtime-dom +--->| @vue/runtime-core +--->| @vue/reactivity |
    12. | | | | | |
    13. +---------------------+ +----------------------+ +-------------------+

调试:https://vue3js.cn/run/start.html

createApp

runtime-dom/src/index.ts

  1. export const createApp = ((...args) => {
  2. const app = ensureRenderer().createApp(...args)
  3. if (__DEV__) {
  4. injectNativeTagCheck(app)
  5. injectCustomElementCheck(app)
  6. }
  7. const { mount } = app
  8. app.mount = (containerOrSelector: Element | ShadowRoot | string): any => {
  9. const container = normalizeContainer(containerOrSelector)
  10. if (!container) return
  11. const component = app._component
  12. if (!isFunction(component) && !component.render && !component.template) {
  13. component.template = container.innerHTML
  14. }
  15. // clear content before mounting
  16. container.innerHTML = ''
  17. const proxy = mount(container, false, container instanceof SVGElement)
  18. if (container instanceof Element) {
  19. container.removeAttribute('v-cloak')
  20. container.setAttribute('data-v-app', '')
  21. }
  22. return proxy
  23. }
  24. return app
  25. }) as CreateAppFunction<Element>

ensureRenderer()——->baseCreateRenderer()

vnode\diff\patch均在这个方法中实现

  1. function baseCreateRenderer(
  2. options: RendererOptions,
  3. createHydrationFns?: typeof createHydrationFunctions
  4. ): any {
  5. const {
  6. insert: hostInsert,
  7. remove: hostRemove,
  8. patchProp: hostPatchProp,
  9. createElement: hostCreateElement,
  10. createText: hostCreateText,
  11. createComment: hostCreateComment,
  12. setText: hostSetText,
  13. setElementText: hostSetElementText,
  14. parentNode: hostParentNode,
  15. nextSibling: hostNextSibling,
  16. setScopeId: hostSetScopeId = NOOP,
  17. cloneNode: hostCloneNode,
  18. insertStaticContent: hostInsertStaticContent
  19. } = options
  20. // ....此处省略两千行,我们先不管
  21. return {
  22. render,
  23. hydrate,
  24. createApp: createAppAPI(render, hydrate)
  25. }
  26. }

从源码中我们看到baseCreateRenderer最终返回render``hydrate``createApp3个函数, 但在createApp这个函数中我们本质上只需要返回createApp这个函数就好

接着将生成的render传给createAppAPI这个真正的createApp方法,hydrate为可选参数,ssr 的场景下会用到

  1. export function createAppAPI<HostElement>(
  2. render: RootRenderFunction,
  3. hydrate?: RootHydrateFunction
  4. ): CreateAppFunction<HostElement> {
  5. return function createApp(rootComponent, rootProps = null) {
  6. if (rootProps != null && !isObject(rootProps)) {
  7. __DEV__ && warn(`root props passed to app.mount() must be an object.`)
  8. rootProps = null
  9. }
  10. // 创建默认APP配置
  11. const context = createAppContext()
  12. const installedPlugins = new Set()
  13. let isMounted = false
  14. const app: App = {
  15. _component: rootComponent as Component,
  16. _props: rootProps,
  17. _container: null,
  18. _context: context,
  19. get config() {
  20. return context.config
  21. },
  22. set config(v) {
  23. if (__DEV__) {
  24. warn(
  25. `app.config cannot be replaced. Modify individual options instead.`
  26. )
  27. }
  28. },
  29. // 都是一些眼熟的方法
  30. use() {},
  31. mixin() {},
  32. component() {},
  33. directive() {},
  34. // mount 我们拎出来讲
  35. mount() {},
  36. unmount() {},
  37. // ...
  38. }
  39. return app
  40. }
  41. }
  1. export function createAppContext(): AppContext {
  2. return {
  3. config: {
  4. isNativeTag: NO,
  5. devtools: true,
  6. performance: false,
  7. globalProperties: {},
  8. optionMergeStrategies: {},
  9. isCustomElement: NO,
  10. errorHandler: undefined,
  11. warnHandler: undefined
  12. },
  13. mixins: [],
  14. components: {},
  15. directives: {},
  16. provides: Object.create(null)
  17. }
  18. }