Vue————Vue v2.7.14 入口文件【二】

简介: Vue————Vue v2.7.14 入口文件【二】

前言

按着我的习惯,拿到一个项目首先我会查看项目下的README.md其次查看package.json,这里也不例外看过 README.md 后,来看下package.json;

GitHub

github page

内容

package.json

vue package.json 字段解释

这里我一般只关注script部分,从这里我们再抽丝剥茧。

"scripts": {
    "dev": "rollup -w -c scripts/config.js --environment TARGET:full-dev",
    "dev:cjs": "rollup -w -c scripts/config.js --environment TARGET:runtime-cjs-dev",
    "dev:esm": "rollup -w -c scripts/config.js --environment TARGET:runtime-esm",
    "dev:ssr": "rollup -w -c scripts/config.js --environment TARGET:server-renderer",
    "dev:compiler": "rollup -w -c scripts/config.js --environment TARGET:compiler ",
    "build": "node scripts/build.js",
    "build:ssr": "npm run build -- runtime-cjs,server-renderer",
    "build:types": "rimraf temp && tsc --declaration --emitDeclarationOnly --outDir temp && api-extractor run && api-extractor run -c packages/compiler-sfc/api-extractor.json",
    "test": "npm run ts-check && npm run test:types && npm run test:unit && npm run test:e2e && npm run test:ssr && npm run test:sfc",
    "test:unit": "vitest run test/unit",
    "test:ssr": "npm run build:ssr && vitest run server-renderer",
    "test:sfc": "vitest run compiler-sfc",
    "test:e2e": "npm run build -- full-prod,server-renderer-basic && vitest run test/e2e",
    "test:transition": "karma start test/transition/karma.conf.js",
    "test:types": "npm run build:types && tsc -p ./types/tsconfig.json",
    "format": "prettier --write --parser typescript \"(src|test|packages|types)/**/*.ts\"",
    "ts-check": "tsc -p tsconfig.json --noEmit",
    "ts-check:test": "tsc -p test/tsconfig.json --noEmit",
    "bench:ssr": "npm run build:ssr && node benchmarks/ssr/renderToString.js && node benchmarks/ssr/renderToStream.js",
    "release": "node scripts/release.js",
    "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s"
  }

根据上面的一些运行命令,我们可以看到 vue 的 dev 是使用rollup来进行打包的,这时候我们直接看dev命令对应的配置文件(scripts/config.js)里面有些什么。

初入 VUE | 寻找入口

  • 进入后我们根据命令参数full-dev进行搜索,会发现以下代码;
// Runtime+compiler development build (Browser)
  'full-dev': {
    entry: resolve('web/entry-runtime-with-compiler.ts'),
    dest: resolve('dist/vue.js'),
    format: 'umd',
    env: 'development',
    alias: { he: './entity-decoder' },
    banner
  },
  • 点击 resolve 进行跳转,跳转到 resolve 函数下;
const aliases = require('./alias')
const resolve = p => {
  const base = p.split('/')[0]
  if (aliases[base]) {
    return path.resolve(aliases[base], p.slice(base.length + 1))
  } else {
    return path.resolve(__dirname, '../', p)
  }
}
  • 根据上方的代码,我们再跳转到引入 alias 文件中,这时候不难发现 vue 对应的入口文件是src/platforms/web/entry-runtime-with-compiler;
const path = require('path')
const resolve = p => path.resolve(__dirname, '../', p)
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'),
  server: resolve('packages/server-renderer/src'),
  sfc: resolve('packages/compiler-sfc/src')
}
  • vue 入口代码内容
import Vue from './runtime-with-compiler'
import * as vca from 'v3'
import { extend } from 'shared/util'
extend(Vue, vca)
import { effect } from 'v3/reactivity/effect'
Vue.effect = effect
export default Vue

深入 VUE | 深度挖掘

既然都找到 vue 的入口文件,那我们肯定是要继续挖掘的!

  • 寻找根源

点击import Vue from './runtime-with-compiler'引入文件进行跳转,来到runtime-with-compiler.ts

import config from 'core/config'
import { warn, cached } from 'core/util/index'
import { mark, measure } from 'core/util/perf'
import Vue from './runtime/index'
import { query } from './util/index'
import { compileToFunctions } from './compiler/index'
import {
  shouldDecodeNewlines,
  shouldDecodeNewlinesForHref
} from './util/compat'
import type { Component } from 'types/component'
import type { GlobalAPI } from 'types/global-api'
  • 再次跳转

根据import Vue from './runtime/index'的引用,我们可以知道还需要再次跳转runtime/index.ts

import Vue from 'core/index'
import config from 'core/config'
import { extend, noop } from 'shared/util'
import { mountComponent } from 'core/instance/lifecycle'
import { devtools, inBrowser } from 'core/util/index'
  • 三次跳转

好东西果然藏得比较深,根据import Vue from 'core/index'的引用,跳转到core/index

import Vue from './instance/index'
import { initGlobalAPI } from './global-api/index'
import { isServerRendering } from 'core/util/env'
import { FunctionalRenderContext } from 'core/vdom/create-functional-component'
import { version } from 'v3'
  • 四次跳转

我感觉下面就是见证奇迹的时刻了,来吧! 根据import Vue from './instance/index'的引用,跳转到./instance/index.ts

import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'
import type { GlobalAPI } from 'types/global-api'
function Vue(options) {
  if (__DEV__ && !(this instanceof Vue)) {
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options)
}
//@ts-expect-error Vue has function type
//初始化混入 | _init
initMixin(Vue)
//@ts-expect-error Vue has function type
// 状态混入 | $set,$delete,$watch
stateMixin(Vue)
//@ts-expect-error Vue has function type
// 事件混入 | $on $once $off $emit
eventsMixin(Vue)
//@ts-expect-error Vue has function type
// 生命周期混入 | _update $forceUpdate $destroy
lifecycleMixin(Vue)
//@ts-expect-error Vue has function type
// 渲染混入 | $nextTick,_render
renderMixin(Vue)
export default Vue as unknown as GlobalAPI

经过了四次的跳转,我们终于到达了传说中的隐秘之地,首先判断如果是开发环境,且不是通过 new 关键字来进行调用的话,就会在控制台打印一个 warning,之后调用了 this._init(options)函数。

补充内容

global-api.ts

import { Config } from 'core/config'
import { Component } from './component'
/**
 * @internal
 */
export interface GlobalAPI {
  // new(options?: any): Component
  (options?: any): void
  // vue 实例唯一id
  cid: number
  // 选项参数
  options: Record<string, any>
  // 全局配置
  // https://v2.cn.vuejs.org/v2/api/#%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE
  config: Config
  // 工具函数 | warn extend mergeOptions defineReactive
  util: Object
  // 使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。
  // https://v2.cn.vuejs.org/v2/api/#Vue-extend
  extend: (options: typeof Component | object) => typeof Component
  // 向响应式对象中添加一个 property,并确保这个新 property
  // 同样是响应式的,且触发视图更新。
  // https://v2.cn.vuejs.org/v2/api/#Vue-set
  set: <T>(target: Object | Array<T>, key: string | number, value: T) => T
  // 删除对象的 property。如果对象是响应式的,确保删除能触发更新视图。
  // 这个方法主要用于避开 Vue 不能检测到 property 被删除的限制,但是你应该很少会使用它。
  // https://v2.cn.vuejs.org/v2/api/#Vue-delete
  delete: <T>(target: Object | Array<T>, key: string | number) => void
  // 在下次 DOM 更新循环结束之后执行延迟回调。
  // 在修改数据之后立即使用这个方法,获取更新后的 DOM。
  // https://v2.cn.vuejs.org/v2/api/#Vue-nextTick
  nextTick: (fn: Function, context?: Object) => void | Promise<any>
  // 安装 Vue.js 插件。
  // 如果插件是一个对象,必须提供 install 方法。
  // 如果插件是一个函数,它会被作为 install 方法。
  // install 方法调用时,会将 Vue 作为参数传入。
  // 该方法需要在调用 new Vue() 之前被调用。
  // https://v2.cn.vuejs.org/v2/api/#Vue-use
  use: (plugin: Function | Object) => GlobalAPI
  // 全局注册一个混入,影响注册之后所有创建的每个 Vue 实例。
  // 插件作者可以使用混入,向组件注入自定义的行为。不推荐在应用代码中使用。
  // https://v2.cn.vuejs.org/v2/api/#Vue-mixin
  mixin: (mixin: Object) => GlobalAPI
  // 将一个模板字符串编译成 render 函数。只在完整版时可用。
  // https://v2.cn.vuejs.org/v2/api/#Vue-compile
  compile: (template: string) => {
    render: Function
    staticRenderFns: Array<Function>
  }
  // 注册或获取全局指令。
  // https://v2.cn.vuejs.org/v2/api/#Vue-directive
  directive: (id: string, def?: Function | Object) => Function | Object | void
  // 注册或获取全局组件。注册还会自动使用给定的 id 设置组件的名称
  // https://v2.cn.vuejs.org/v2/api/#Vue-component
  component: (
    id: string,
    def?: typeof Component | Object
  ) => typeof Component | void
  // 注册或获取全局过滤器。
  // https://v2.cn.vuejs.org/v2/api/#Vue-filter
  filter: (id: string, def?: Function) => Function | void
  // 让一个对象可响应。Vue 内部会用它来处理 data 函数返回的对象
  // https://v2.cn.vuejs.org/v2/api/#Vue-observable
  observable: <T>(value: T) => T
  // allow dynamic method registration
  [key: string]: any
}

学无止境,谦卑而行.

目录
打赏
0
0
0
0
67
分享
相关文章
Vue实现动态数据透视表(交叉表)
Vue实现动态数据透视表(交叉表)
72 13
极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图
本文介绍了使用 Vue Flow 绘制流程图的方法与技巧。Vue Flow 是一个灵活强大的工具,适合自定义复杂的流程图。文章从环境要求(Node.js v20+ 和 Vue 3.3+)、基础入门案例、自定义功能(节点与连线的定制、事件处理)到实际案例全面解析其用法。重点强调了 Vue Flow 的高度灵活性,虽然预定义内容较少,但提供了丰富的 API 支持深度定制。同时,文中还分享了关于句柄(handles)的使用方法,以及如何解决官网复杂案例无法运行的问题。最后通过对比 mermaid,总结 Vue Flow 更适合需要高度自定义和复杂需求的场景,并附带多个相关技术博客链接供进一步学习。
属性描述符初探——Vue实现数据劫持的基础
属性描述符还有很多内容可以挖掘,比如defineProperty与Proxy的区别,比如vue2与vue3实现数据劫持的方式有什么不同,实现效果有哪些差异等,这篇博文只是入门,以后有时间再深挖。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
Vue Router 核心原理
Vue Router 是 Vue.js 的官方路由管理器,用于实现单页面应用(SPA)的路由功能。其核心原理包括路由配置、监听浏览器事件和组件渲染等。通过定义路径与组件的映射关系,Vue Router 将用户访问的路径与对应的组件关联,支持哈希和历史模式监听 URL 变化,确保页面导航时正确渲染组件。
Vue中的class和style绑定
在 Vue 中,class 和 style 绑定是基于数据驱动视图的强大功能。通过 class 绑定,可以动态更新元素的 class 属性,支持对象和数组语法,适用于普通元素和组件。style 绑定则允许以对象或数组形式动态设置内联样式,Vue 会根据数据变化自动更新 DOM。
Vue Router 简介
Vue Router 是 Vue.js 官方的路由管理库,用于构建单页面应用(SPA)。它将不同页面映射到对应组件,支持嵌套路由、路由参数和导航守卫等功能,简化复杂前端应用的开发。主要特性包括路由映射、嵌套路由、路由参数、导航守卫和路由懒加载,提升性能和开发效率。安装命令:`npm install vue-router`。
VUE文件的创建
第一步创建完VUE 项目之后 可以根据自己的需求 创建自己的文件目录(下图是我的文件目录,当然每个人的创建目录的风格也是不同的所以不做严格的规范) 模块文生成    components文件夹下创建  模块文件名字.
812 0
|
4月前
|
vue使用iconfont图标
vue使用iconfont图标
187 1
ry-vue-flowable-xg:震撼来袭!这款基于 Vue 和 Flowable 的企业级工程项目管理项目,你绝不能错过
基于 Vue 和 Flowable 的企业级工程项目管理平台,免费开源且高度定制化。它覆盖投标管理、进度控制、财务核算等全流程需求,提供流程设计、部署、监控和任务管理等功能,适用于企业办公、生产制造、金融服务等多个场景,助力企业提升效率与竞争力。
131 12

热门文章

最新文章