|Vue.js源码全方位深入解析,快人一步进名企-完结

|Vue.js源码全方位深入解析,快人一步进名企-完结

Download:
一、前言:
Vue.js 3.0 设计了一个很强大的 API —— Composition API , 它主要用来优化代码逻辑的组织和复用 。 从语法上看 , 它提供了一个 setup 启动函数作为逻辑组织的入口 , 暴露了响应式 API 为用户所用 , 也提供了生命周期函数以及依赖注入的接口 , 这让我们不依托于 Options API 也可以完成一个组件的开发 , 并且更有利于代码逻辑的组织和复用 。 但是我们要明确一点 , Composition API 属于 API 的增强 , 它并不是 Vue.js 3.0 组件开发的范式 , 如果你的组件足够简单 , 你还是可以使用 Options API 。
二、初始化
Vue.js 3.0 允许我们在编写组件的时候添加一个 setup 启动函数 , 它是 Composition API 逻辑组织的入口 , 我们先通过一段代码认识它 , 在这里编写一个 button 组件:
<template>
<button @click=\"increment\">
Count is: < state.count > double is: < state.double >
</button>
</template>
<script>
import { reactive computedfrom 'vue'
export default <{p>
setup() <{p>
const state = reactive(<{p>
count: 0
double: computed(() => state.count * 2)
)
function increment() <{p>
state.count++

return <{p>
state
increment



</script>
可以看到 , 这段代码和 Vue.js 2.x 组件的写法相比 , 多了一个 setup 启动函数 , 另外组件中也没有定义 props、data、computed 这些 options 。 在 setup 函数内部 , 定义了一个响应式对象 state , 它是通过 reactive API 创建的 。 state 对象有 count 和 double 两个属性 , 其中 count 对应一个数字属性的值;而double 通过 computed API 创建 , 对应一个计算属性的值 。 reactive API 和 computed API 不是我们关注的重点 , 在后续响应式章节我会详细介绍 。
这里需要注意的是 , 模板中引用到的变量 state 和 increment 包含在 setup 函数的返回对象中 , 那么它们是如何建立联系的呢?
我们先来回想一下 Vue.js 2.x 编写组件的时候 , 会在 props、data、methods、computed 等 options 中定义一些变量 。 在组件初始化阶段 , Vue.js 内部会处理这些 options , 即把定义的变量添加到了组件实例上 。 等模板编译成 render 函数的时候 , 内部通过 with(this){ 的语法去访问在组件实例中的变量 。 那么到了 Vue.js 3.0 , 既支持组件定义 setup 函数 , 而且在模板 render 的时候 , 又可以访问到 setup 函数返回的值 , 这是如何实现的?我们来一探究竟 。
1.创建组件实例
首先 , 我们来回顾一下组件的渲染流程:创建 vnode 、渲染 vnode 和生成 DOM 。 其中渲染 vnode 的过程主要就是在挂载组件:
const mountComponent = (initialVNode container anchor parentComponent parentSuspense isSVG optimized) => <{p>
// 创建组件实例
const instance = (initialVNode.component = createComponentInstance(initialVNode parentComponent parentSuspense))
// 设置组件实例
setupComponent(instance)
// 设置并运行带副作用的渲染函数
setupRenderEffect(instance initialVNode container anchor parentSuspense isSVG optimized)

可以看到 , 这段挂载组件的代码主要做了三件事情:创建组件实例、设置组件实例和设置并运行带副作用的渲染函数 。 前两个流程就跟我们今天提到的问题息息相关 。
2.createComponentInstance 方法的实现:
function createComponentInstance (vnode parent suspense) <{p>
// 继承父组件实例上的 appContext , 如果是根组件 , 则直接从根 vnode 中取 。