Vue中的 VueComponent

VueComponent

组件的本质

  • Vue 组件是一个可复用的 Vue 实例。
  • 每个组件本质上就是通过 Vue.extend() 创建的构造函数,或者在 Vue 3 中是由函数式 API(Composition API)创建的。
html 复制代码
// Vue 2
const MyComponent = Vue.extend({
  template: '<div>Hello</div>'
});

组件注册

  • 全局注册:Vue.component('MyComponent', {...})
  • 局部注册:
html 复制代码
export default {
  components: {
    MyComponent
  }
}

Props 和事件

  • props:父传子,用于组件参数传递。
  • 自定义事件 $emit:子传父。
html 复制代码
// 子组件
this.$emit('update:value', newValue);

插槽 Slot

  • 默认插槽、具名插槽、作用域插槽。
javascript 复制代码
<slot name="header"></slot>

生命周期钩子

  • beforeCreate → created → beforeMount → mounted → beforeUpdate → updated → beforeDestroy → destroyed

深入理解 VueComponent

VueComponent 的创建过程(以 Vue 2 为例)

Vue 执行 new Vue({...}) 时会走如下过程:

a. Vue.extend() 创建组件构造器

function VueComponent (options) {

this._init(options);

}

b. _init() 方法中合并配置、初始化生命周期、事件、render、data 等。

c. 渲染和挂载:调用 vm.$mount() → 创建 VNode → patch → 转换为真实 DOM。

组件更新机制

  • 响应式依赖收集(Dep 和 Watcher)
  • 数据变动触发组件局部更新(通过虚拟 DOM 的 diff 算法)。

🧩 VueComponent 源码解读(以 Vue 2.x 为主)

我们从组件创建 → 渲染 → 响应更新 → 销毁 全流程解读。

组件的创建过程

🔧 Vue.component() 注册组件

js 复制代码
Vue.component('MyComp', {
  props: ['msg'],
  template: '<div>{{ msg }}</div>'
});

注册后,内部通过 Vue.options.components['MyComp'] 存储组件定义,等待使用。

注册本质:调用 extend 创建一个组件构造器(子类):

js 复制代码
function initGlobalAPI (Vue) {
  Vue.component = function (id, definition) {
    if (typeof definition === 'object') {
      definition = Vue.extend(definition); // 核心!
    }
    Vue.options.components[id] = definition;
  }
}

🏗️ Vue.extend 组件构造器

源码位置:src/core/global-api/extend.js

javascript 复制代码
Vue.extend = function (extendOptions) {
  const Sub = function VueComponent(options) {
    this._init(options);
  };
  Sub.prototype = Object.create(Vue.prototype); // 原型继承
  Sub.prototype.constructor = Sub;
  Sub.options = mergeOptions(Vue.options, extendOptions);
  return Sub;
};

重点:

  • 每个组件都是 Vue 的子类。
  • 合并父 Vue 的选项和当前组件的选项。

组件实例的初始化

当我们在模板中写 ,Vue 解析 VNode 时会进入 createComponent() → createComponentInstanceForVnode() → new VNode.componentOptions.Ctor()。

🔄 调用 vm._init()

位置:src/core/instance/init.js

javascript 复制代码
Vue.prototype._init = function (options) {
  vm.$options = mergeOptions(resolveConstructorOptions(vm.constructor), options);
  initLifecycle(vm);
  initEvents(vm);
  initRender(vm);
  callHook(vm, 'beforeCreate');
  initState(vm); // 初始化 props、methods、data、computed、watch
  callHook(vm, 'created');

  if (vm.$options.el) {
    vm.$mount(vm.$options.el);
  }
}

组件的挂载与渲染

🔨 vm.$mount() → 编译模板 → 生成 render 函数

位置:src/platforms/web/entry-runtime-with-compiler.js

javascript 复制代码
const mount = Vue.prototype.$mount;
Vue.prototype.$mount = function (el) {
  el = document.querySelector(el);
  if (!this.$options.render) {
    const template = this.$options.template;
    const render = compileToFunctions(template);
    this.$options.render = render;
  }
  return mount.call(this, el);
}

🧱 渲染流程:render() → vnode → patch()

位置:src/core/instance/lifecycle.js

vm._update(vm._render());

复制代码
•	_render() 执行 render 函数,返回 vnode。
•	_update() 使用 patch 将 vnode 转为真实 DOM。

响应式更新机制

🔁 组件的响应式核心依赖于:Observer、Dep、Watcher

  • data 中的数据会被劫持(defineReactive)
  • 每个组件对应一个渲染 watcher。
  • 数据更新时通知 Dep → 触发 watcher → 重新执行 render → 生成新 vnode → diff patch。
js 复制代码
new Watcher(vm, updateComponent, noop);

组件销毁过程

调用 $destroy():

js 复制代码
Vue.prototype.$destroy = function () {
  callHook(vm, 'beforeDestroy');
  // 删除 watcher
  // 解绑事件
  // 从 DOM 移除
  callHook(vm, 'destroyed');
}

🧬 源码主线流程总结(Vue 2)

Vue.component(...) → Vue.extend(...) → 组件构造函数 Sub

渲染 →

createComponent() →

new Sub(options) →

_init() →

mergeOptions → initState →

created → $mount()

$mount() →

compile(template) → render →

render() → vnode →

patch(vnode) → 挂载 DOM

数据更新 → Observer 触发 Dep.notify →

Watcher.update() → 重新 render → patch → 更新 DOM

📘 推荐文件入口

功能 文件 描述
全局 API 初始化 src/core/global-api/index.js 包括 Vue.component
组件构造器 src/core/global-api/extend.js 实现 Vue.extend
Vue 初始化 src/core/instance/init.js 实现 _init()
生命周期 src/core/instance/lifecycle.js created、mounted 等钩子
渲染函数 src/core/instance/render.js vm._render()
虚拟 DOM → DOM src/core/vdom/patch.js diff 算法
响应式系统 src/core/observer/ 包含 Dep、Watcher、Observer
相关推荐
pianmian14 小时前
3D Tiles高级样式设置与条件渲染(3)
linux·服务器·前端
资深前端之路4 小时前
vue+threeJs 绘制3D圆形
前端·javascript·vue.js
Nymph_Zhu5 小时前
vue3+element-plus el-date-picker日期、年份筛选设置本周、本月、近3年等快捷筛选
前端·vue.js·elementui
极客密码5 小时前
DeepSeek-R1-0528,官方的端午节特别献礼
前端·ai编程·deepseek
打小就很皮...5 小时前
npm、pnpm、yarn使用以及区别
前端·npm·yarn
FungLeo5 小时前
vue2 + webpack 老项目升级 node v22 + vite + vue2 实战全记录
前端·webpack·vue2·vie·webpack 升级 vite
西洼工作室6 小时前
使用原生前端技术封装一个组件
前端·js
xiaofann_6 小时前
【数据结构】单链表练习
linux·前端·数据结构
烛阴6 小时前
为什么选择Day.js?比Moment.js更轻更快的日期处理神器
前端·javascript
XiaoLeisj6 小时前
【JUC】深入解析 JUC 并发编程:单例模式、懒汉模式、饿汉模式、及懒汉模式线程安全问题解析和使用 volatile 解决内存可见性问题与指令重排序问题
javascript·安全·单例模式