vue面试之Composition-API响应式包装对象原理

本文深入解读Vue Composition API的响应式对象包装原理,从reactive.ts入口函数开始,介绍如何创建响应式对象,包括参数检验、对象类型判断、不可拓展对象处理,以及核心的__ob__属性和proxy的创建。同时,文章探讨了ref.ts中的ref API,讲解如何创建可观察对象,以及如何保证对象的安全性和防止不必要的代理。最后,总结了Vue Composition API在提升开发者体验方面的设计思路。
摘要由CSDN通过智能技术生成

本文主要分以下两个部分对 Composition API 的原理进行解读:

  • reactive API 原理
  • ref API 原理

reactive API 原理

打开源码可以找到reactive的入口,在composition-api/src/reactivity/reactive.ts,我们先从函数入口开始分析reactive发生了什么事情,通过之前的学习我们知道,reactive用于创建响应式对象,需要传递一个普通对象作为参数。

export function reactive<T = any>(obj: T): UnwrapRef<T> {
   
  if (process.env.NODE_ENV !== 'production' && !obj) {
   
    warn('"reactive()" is called without provide an "object".');
    // @ts-ignore
    return;
  }

  if (!isPlainObject(obj) || isReactive(obj) || isNonReactive(obj) || !Object.isExtensible(obj)) {
   
    return obj as any;
  }
  // 创建一个响应式对象
  const observed = observe(obj);
  // 标记一个对象为响应式对象
  def(observed, ReactiveIdentifierKey, ReactiveIdentifier);
  // 初始化对象的访问控制,便于访问ref属性时自动解包装
  setupAccessControl(observed);
  return observed as UnwrapRef<T>;
}

首先,在开发环境下,会进行传参检验,如果没有传递对应的obj参数,开发环境下会给予开发者一个警告,在这种情况,为了不影响生产环境,生产环境下会将警告放过。

函数入口会检查类型,首先调用isPlainObject检查是否是对象。如果不是对象,将会直接返回该参数,因为非对象类型并不可观察。

然后调用isReactive判断对象是否已经是响应式对象,下面是isReactive原型:

import {
   
  AccessControlIdentifierKey,
  ReactiveIdentifierKey,
  NonReactiveIdentifierKey,
  RefKey,
} from '../symbols';
// ...
export function isReactive(obj: any): boolean {
   
  return hasOwn(obj, ReactiveIdentifierKey) && obj[ReactiveIdentifierKey] === ReactiveIdentifier;
}

通过上面的代码我们知道,ReactiveIdentifierKeyReactiveIdentifier都是一个Symbol,打开composition-api/src/symbols.ts可以看到,ReactiveIdentifierKeyReactiveIdentifier是已经定义好的Symbol

import {
    hasSymbol } from './utils';

function createSymbol(name: string): string {
   
  return hasSymbol ? (Symbol.for(name) as any) : name;
}

export const WatcherPreFlushQueueKey = createSymbol('vfa.key.preFlushQueue');
export const WatcherPostFlushQueueKey = createSymbol('vfa.key.postFlushQueue');
export const AccessControlIdentifierKey = createSymbol('vfa.key.accessControlIdentifier');
export const ReactiveIdentifierKey = createSymbol('vfa.key.reactiveIdentifier');
export const NonReactiveIdentifierKey = createSymbol('vfa.key.nonReactiveIdentifier');

// must be a string, symbol key i
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值