Vue.js源码解析——new Vue()做了什么事情

本文探讨了Vue.js中`new Vue()`操作背后的原理。它首先检查是否在生产环境中正确使用`new`关键字,然后调用`_init`方法初始化各种属性,如"data"、"methods"、"props"、"computed"和"watch"。`initState`方法负责初始化用户定义的属性,特别是`initData`对"data"进行处理,通过`Object.defineProperty`创建getter和setter,并通过`observer`实现数据绑定。最后,如果存在`el`属性,将调用`$mount`进行挂载和渲染。整个实例化过程涉及组件生命周期和数据绑定的关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Vue.js中我们可以用以下的语法来声明式渲染数据

<div id="app">
	{
   {
   message}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
	const app = new Vue({
   
		el:"#app",
		data:{
   
			message:"Hellp Vue!"
		}
	})
</script>

在页面上能看到Hellp Vue!,那么new Vue()做了什么呢?
首先找到Vue()这个类,在src/core/instance/index.js中

function Vue (options) {
   
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
   
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options)
}

initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)

export default Vue

首先判断当前的环境是不是生产环境,且在调用Vue的时候,有没有用new操作符,如果没有就会调用warn,抛出一个警告告诉我们Vue是一个构造函数,需要用new操作符去调用
接着调用_init方法,传递的参数便是我们在new Vue时传进去的对象

{
   
	el:"#app",
	data:{
   
		message:"Hellp Vue!"
	}
}

_init方法是 initMixin 封装到vue函数原型中的,此方法在src/core/instance/init.js

let uid = 0//每个Vue实例都有一个id

export function initMixin (Vue: Class
### Vue3 响应式机制源码分析 #### 构造函数与初始化过程 Vue3 的核心仍然基于 `new` 操作符创建实例,这表明 Vue 是一个构造函数[^1]。当使用 `new Vue()` 创建一个新的应用实例时,传入的对象作为配置项被传递到内部处理。 ```javascript const app = new Vue({ data() { return { message: 'Hello' } }, }); ``` #### Proxy 对象用于属性拦截 不同于 Vue2 使用 Object.defineProperty 来劫持对象属性的变化,Vue3 利用了 ES6 中引入的 Proxy API 实现更强大的响应式特性[^2]。每当访问或修改由 reactive 函数包裹的数据结构内的任何键值对时,Proxy 就会触发相应的 getter 和 setter 方法: ```typescript function createReactiveObject(target) { const handler = { get(target, key, receiver) { track(target, key); // 收集依赖 return Reflect.get(target, key, receiver); }, set(target, key, value, receiver) { let oldValue = target[key]; let result = Reflect.set(target, key, value, receiver); if (oldValue !== value && !Object.is(oldValue, value)) { trigger(target, key); // 触发更新 } return result; } }; return new Proxy(target, handler); } ``` 这段代码展示了如何利用 JavaScript 的代理机制来监听目标对象上的读写操作,并相应地通知视图层出改变。 #### Effect 与 Dep 关联机制 在 Vue3 中,effect 取代了 Vue2 中 Wather 的角色,成为新的副作用管理工具[^4]。每次执行 setup 钩子内定义的效果函数时,都会自动追踪所使用的状态变量并注册回调以便后续同步变化。这种设计使得开发者能够更容易理解和控制程序的行为流程。 ```typescript let activeEffect; export function effect(fn) { const _effect = () => { cleanup(_effect); activeEffect = _effect; fn(); activeEffect = null; }; _effect.deps = []; _effect(); return _effect; } // 清理旧依赖关系 function cleanup(effectFn) { for (let i = 0; i < effectFn.deps.length; i++) { const deps = effectFn.deps[i]; deps.delete(effectFn); } effectFn.deps.length = 0; } ``` 上述片段揭示了 effect 如何工作以及它是怎样与其他部分交互完成整个生命周期的过程。 #### 组件挂载逻辑 最后来看一下组件是如何被渲染出来的。通过 mount 函数接收两个参数——一个是代表应用程序上下文环境的 instance ,另一个是指定 DOM 容器位置的 el 。在这个过程中不仅设置了初始数据还完成了首次页面绘制任务[^5]。 ```javascript export function mount(instance, el){ // 执行effect effect(function(){ instance.$data && update(instance, el) }) // 初始化setup返回的结果赋值给$data instance.$data = instance.setup() // 更新节点 update(instance, el) function update(instance, el){ // 设置容器的内容为render方法产生的HTML字符串 el.innerHTML = instance.render() } } ``` 此段实现了从虚拟DOM树构建到最后实际显示于浏览器窗口之间必要的转换步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值