Vue3源码 第四篇-Vue3 setup

系列文章目录

Vue3源码 第一篇-总览
Vue3源码 第二篇-Reactive API
Vue3源码 第三篇-Vue3是如何实现响应性
Vue3源码 第五篇-Vue3 模版compile AST生成篇

前言

setup作为Vue3的组合式API的重要特性,改变了之前OptionAPI的写代码方式,setup函数让Vue3对逻辑的封装更为简单,那么他又是在Vue3上如何挂载,如何访问的呢?我们接下来一起阅读源码,从源码中深入了解setup函数。话不多说,直接开冲!!!
在这里插入图片描述

一、源码阅读

1.setup函数的创建

要找到setup的挂载,第一步找到在哪里执行setup函数,我们知道setup函数肯定在组件挂载的时候执行,所以我们在组件挂载的代码中找到了setupStatefulComponent函数,该函数中包含了组件各个部分的挂载,自然也包含了setup函数的挂载,我们来阅读下这个函数中setup函数相关的代码。

function setupStatefulComponent(instance, isSSR) {
    // ...省略其他代码
    // 2. call setup() 组件中存在setup函数,挂载过程中,最先开始挂载的就是setup函数,之后才是optionApi的挂载
    const { setup } = Component;
    if (setup) {
    	// 创建setup函数的上下文
        const setupContext = (instance.setupContext =
            setup.length > 1 ? createSetupContext(instance) : null);
        currentInstance = instance;
        pauseTracking();
        // 获取setup结果,外层包裹函数错误处理函数callWithErrorHandling
        const setupResult = callWithErrorHandling(setup, instance, 0 /* SETUP_FUNCTION */, [shallowReadonly(instance.props) , setupContext]);
        resetTracking();
        currentInstance = null;
        // 对不同的结果进行处理
        // 如果结果是promise
        if (isPromise(setupResult)) {
            if (isSSR) { // 当前是SSR 服务器端渲染
                // return the promise so server-renderer can wait on it
                return setupResult
                    .then((resolvedResult) => {// 等待服务器返回结果在进行处理
                        handleSetupResult(instance, resolvedResult, isSSR);
                    })
                    .catch(e => {
                        handleError(e, instance, 0 /* SETUP_FUNCTION */);
                    });
            }
            else {
                // async setup returned Promise. 如果只是单纯的异步,就直接赋值暂时跳过
                // bail here and wait for re-entry.
                instance.asyncDep = setupResult;
            }
        }
        else {// 如果不是promise,直接处理返回结果
            handleSetupResult(instance, setupResult, isSSR);
        }
    }
    else {
    	// 如果不存在setup函数就直接进行下面optionApi的挂载,
    	// 不包括props的执行,在Vue3中,props最先执行,之后是setup,最后是其他optionAPI
        finishComponentSetup(instance, isSSR);
    }
}

我们先整体的了解的setup的挂载过程,接下来我们仔细将setup函数挂载分为:setup函数上下文的创建,setup的执行,setup返回的处理3个具体步骤来仔细阅读其中的代码。

1.1 setup函数上下文(context)创建

createSetupContext函数创建setup函数的上下文,包含了一些在setup函数中可能会用到的属性和方法等。

function createSetupContext(instance) {
   const expose = exposed => {
   		 // exopose函数,当setup返回渲染函数时会用到,因为返回渲染函数时无法暴露其他东西,所以可以通过expose函数暴露
   		 // 具体可以查看官网 https://v3.cn.vuejs.org/guide/composition-api-setup.html#使用渲染函数
         if (instance.exposed) {
             warn(`expose() should be called only once per setup().`);
         }
         instance.exposed = proxyRefs(exposed);
     };
     {
         // We use getters in dev in case libs like test-utils overwrite instance
         // properties (overwrites should not be done in prod)
         return Object.freeze({
             get attrs() { // $attrs 组件上的属性
                 return new Proxy(instance.attrs, attrHandlers);
             },
             get slots() { // $slots 插槽
                 return shallowReadonly(instance.slots);
             },
             get emit() { // $emit 触发事件的方法
                 return (event, ...args) => instance.emit(event, ...args);
             },
             expose
         });
     }
 }

1.2 setup函数执行

callWithErrorHandling方法在Vue2和3版本中都很常见,主要是对执行函数进行错误处理的封装。对执行的函数进行try-catch处理。

const setupResult = callWithErrorHandling(setup, instance, 0 /* SETUP_FUNCTION */, 
											[shallowReadonly(instance.props) , setupContext]);
// 第一个参数是setup函数本身
// 第二个参数是组件实例
// 第三个参数是标志执行函数类型
// 第四个参数是由props和刚才执行的上下文组成的参数
function callWithErrorHandling(fn, instance, type, args) {
    let res;
    try {
        res = args ? fn(...args) : fn();
    }
    catch (err) {
        handleError(err, instance, type);
    }
    return res;
}

通过setup函数的执行代码,我们可以知道,在执行setup函数中,我们能获取到的是props和之前提到的上下文参数,有一点也特别重要,我们在执行setup函数的时候并没有传入instance对象,也就是无法获取实例对象,并且在context中也没有传入data,method等信息(其实这里是因为这些的创建在setup函数之后)所以官网也指出:
你将无法在setup函数中访问以下组件选项:
data
computed
methods
refs (模板 ref)

还有一点setup函数的this,也没有绑定instance,所以setup的this无法获取到vue实例。这样就验证了官网所说的:
在 setup() 内部,this 不是该活跃实例的引用

1.3 setup函数执行结果处理

handleSetupResult处理setup返回结果,将结果绑定到instance上方便其他函数调用

function handleSetupResult(instance, setupResult, isSSR) {
	 // 如果返回的是函数,就是渲染函数,设置实例上的render函数为该函数
     if (isFunction(setupResult)) {
         // setup returned an inline render function
         {
             instance.render = setupResult;
         }
     }
     else if (isObject(setupResult)) { // 返回对象
         if (isVNode(setupResult)) {
             warn(`setup() should not return VNodes directly - ` +
                 `return a render function instead.`);
         }
         // setup returned bindings.
         // assuming a render function compiled from template is present.
         {
             instance.devtoolsRawSetupState = setupResult;
         }
         // 将返回结果转换成reactive对象,并且放入到实例的setupState上
         instance.setupState = proxyRefs(setupResult);
         {
             exposeSetupStateOnRenderContext(instance);
         }
     }
     else if (setupResult !== undefined) {
         warn(`setup() should return an object. Received: ${setupResult === null ? 'null' : typeof setupResult}`);
     }
     finishComponentSetup(instance, isSSR);
 }

总结

今天对setup函数的创建过程进行了源码阅读,包括他的上下文创建,setup函数的执行还有对setup结果的处理,个人理解有限,若有不好的地方希望大家多多斧正,最后拜托大家给个三连吧~~~
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Vue3的setup代码是在组件中定义的一个函数,用于替代Vue2中的created、mounted等生命周期钩子函数。该函数在组件实例创建之前执行,并且接收两个参数:props和context。在setup函数中,可以进行一些初始化工作,例如设置响应式数据、定义方法等。 下面是一个示例的Vue3组件的setup代码: ```javascript import { reactive } from 'vue'; export default { setup(props, context) { // 响应式数据 const data = reactive({ message: 'Hello, Vue3!' }); // 方法 function showMessage() { console.log(data.message); } // 在模板中使用的变量和方法可以通过返回对象进行暴露 return { data, showMessage }; } } ``` 在上面的代码中,我们使用`reactive`函数创建了一个响应式的`data`对象,并定义了一个`showMessage`方法。最后,通过返回一个对象,将`data`和`showMessage`暴露给模板中使用。 需要注意的是,由于setup函数在组件实例创建之前执行,因此无法直接访问实例对象(`this`),也无法访问组件选项如`data`、`computed`、`methods`等。此外,setup函数的`this`也未绑定到组件实例上。 总结起来,Vue3的setup代码是用于在组件实例创建之前进行初始化工作的函数,在其中可以定义响应式数据和方法,并通过返回对象将它们暴露给模板中使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Vue3源码 第四篇-Vue3 setup](https://blog.csdn.net/qq_26626113/article/details/120657470)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小疯疯0413

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值