网站js效果,游戏代理公司,青岛建设监理协会网站,广东中国移动网站Computed: Vue 3 计算属性深入解析 1.计算属性的基本用法2. ComputedRefImpl 类深入解析JavaScript 中的 getter 函数 3. 计算属性的创建#xff1a;computed 方法解析3.1 源码解析3.2 使用示例 4. 计算属性的工作原理5. 手动实现简化的计算属性6. 结语 在 Vue 3 的响应式系统… Computed: Vue 3 计算属性深入解析 1.计算属性的基本用法2. ComputedRefImpl 类深入解析JavaScript 中的 getter 函数 3. 计算属性的创建computed 方法解析3.1 源码解析3.2 使用示例 4. 计算属性的工作原理5. 手动实现简化的计算属性6. 结语 在 Vue 3 的响应式系统中计算属性computed扮演着重要的角色。它们基于响应式依赖进行缓存并仅在依赖项变化时重新计算。这意味着计算属性能够提供高效的数据处理方式因为只有当实际需要时计算属性的值才会更新。下面我们将详细探讨 Vue 3 中计算属性的实现细节及其用法。 1.计算属性的基本用法
计算属性依赖于其他响应式数据并且仅在这些依赖数据发生变化时才重新计算其值。这种机制保证了性能的优化避免了不必要的计算。
import { reactive, computed } from vue;const state reactive({count: 1,
});const plusOne computed(() state.count 1);console.log(plusOne.value); // 2
state.count;
console.log(plusOne.value); // 32. ComputedRefImpl 类深入解析
ComputedRefImpl 类是计算属性在 Vue 3 中的实现基础。它负责把用户定义的 getter 函数封装成响应式引用并且管理计算结果的缓存。该类的关键实现如下
export class ComputedRefImplT {//用于存储与此计算属性相关的依赖副作用函数。public dep?: Dep undefined//用于存储计算属性的当前值private _value!: T//一个 ReactiveEffect 实例用于封装计算属性的 getter 函数。这个副作用函数会在依赖的响应式数据变化时重新执行以更新计算属性的值public readonly effect: ReactiveEffectT//内部标志用于标记这个对象是一个 Ref 类型并且指示其只读状态。public readonly __v_isRef truepublic readonly [ReactiveFlags.IS_READONLY]: boolean falsepublic _cacheable: boolean/*** Dev only*/_warnRecursive?: boolean/*** 构造函数接收四个参数* getter: 用户定义的计算属性的获取函数。* _setter: 用户定义的计算属性的设置函数用于允许计算属性被赋新值。* isReadonly: 表明这个计算属性是否是只读的。* isSSR: 标记是否在服务器端渲染环境中使用影响是否缓存计算结果。*/constructor(private getter: ComputedGetterT,private readonly _setter: ComputedSetterT,isReadonly: boolean,isSSR: boolean,) {//ReactiveEffect 被用于封装 getter 函数确保每当依赖的数据变化时都能够自动重新计算值并缓存结果以提高性能。this.effect new ReactiveEffect(() getter(this._value),() triggerRefValue(this,this.effect._dirtyLevel DirtyLevels.MaybeDirty_ComputedSideEffect? DirtyLevels.MaybeDirty_ComputedSideEffect: DirtyLevels.MaybeDirty,),)this.effect.computed thisthis.effect.active this._cacheable !isSSRthis[ReactiveFlags.IS_READONLY] isReadonly}/*** 当访问计算属性的 value 时会执行这个 getter 函数。* 这个函数首先检查是否需要重新计算计算属性的值基于缓存逻辑和依赖数据的变化。* 如果需要它会运行封装的 getter 函数来更新 _value。* 然后它会注册当前活动的副作用函数为这个计算属性的依赖以便将来数据变化时能触发更新*/get value() {// the computed ref may get wrapped by other proxies e.g. readonly() #3376//“获取当前计算属性实例this背后的原始对象并将其赋值给 self 变量”const self toRaw(this)if ((!self._cacheable || self.effect.dirty) hasChanged(self._value, (self._value self.effect.run()!))) {triggerRefValue(self, DirtyLevels.Dirty)}trackRefValue(self)if (self.effect._dirtyLevel DirtyLevels.MaybeDirty_ComputedSideEffect) {if (__DEV__ (__TEST__ || this._warnRecursive)) {warn(COMPUTED_SIDE_EFFECT_WARN, \n\ngetter: , this.getter)}triggerRefValue(self, DirtyLevels.MaybeDirty_ComputedSideEffect)}return self._value}set value(newValue: T) {this._setter(newValue)}// #region polyfill _dirty for backward compatibility third party code for Vue 3.3.xget _dirty() {return this.effect.dirty}set _dirty(v) {this.effect.dirty v}// #endregion
}这个类通过 ReactiveEffect 封装 getter 函数使计算属性能够响应依赖数据的变化。同时通过缓存机制保证了性能的优化。
JavaScript 中的 getter 函数
get value() {} 是 JavaScript 中的一个 getter 函数的写法它是对象属性访问器的语法之一。Getter 函数允许你定义一个对象属性该属性在被访问时会自动执行一个函数来返回值而不是直接返回一个值。这使得在对象属性被访问时可以执行更复杂的操作或计算而对于使用者来说这种访问看起来就像访问一个普通属性一样。
const person {firstName: John,lastName: Doe,get fullName() {return ${this.firstName} ${this.lastName};}
};console.log(person.fullName); // 输出: John Doe
3. 计算属性的创建computed 方法解析
Vue 3 提供了 computed 函数用于创建计算属性。这个函数既可以接受一个简单的 getter 函数也可以接受一个包含 get 和 set 方法的对象允许创建可读写的计算属性。
3.1 源码解析
/*** 接受一个 getter 函数作为参数。这个 getter 函数定义了计算属性的计算逻辑* 当依赖的响应式数据变化时这个函数会被重新执行来更新计算属性的值。* 在这种情况下计算属性是只读的尝试写入会导致警告在开发模式下。*/
export function computedT(getter: ComputedGetterT,debugOptions?: DebuggerOptions,
): ComputedRefT/*** 接受一个包含 get 和 set 方法的对象 options 作为参数* 这允许你创建一个可写的计算属性。get 方法定义了计算逻辑和只读计算属性一样。* set 方法允许你自定义当尝试修改计算属性的值时的行为这在需要基于计算属性的值反向更新其依赖的响应式数据时非常有用。*/
export function computedT(options: WritableComputedOptionsT,debugOptions?: DebuggerOptions,
): WritableComputedRefTexport function computedT(getterOrOptions: ComputedGetterT | WritableComputedOptionsT,debugOptions?: DebuggerOptions,isSSR false,
) {let getter: ComputedGetterTlet setter: ComputedSetterTconst onlyGetter isFunction(getterOrOptions)if (onlyGetter) {getter getterOrOptionssetter __DEV__? () {warn(Write operation failed: computed value is readonly)}: NOOP} else {getter getterOrOptions.getsetter getterOrOptions.set}//使用 ComputedRefImpl 类来实际创建计算属性const cRef new ComputedRefImpl(getter, setter, onlyGetter || !setter, isSSR)if (__DEV__ debugOptions !isSSR) {cRef.effect.onTrack debugOptions.onTrackcRef.effect.onTrigger debugOptions.onTrigger}return cRef as any
}3.2 使用示例
import { computed } from vue;// 创建只读计算属性
const readOnlyComputed computed(() someReactiveData.value 1);// 创建可写计算属性
const writableComputed computed({get: () someReactiveData.value 1,set: (newValue) { someReactiveData.value newValue - 1; }
});4. 计算属性的工作原理
计算属性背后的核心是其延迟计算和缓存机制。ComputedRefImpl 类中的 effect 通过跟踪响应式依赖自动管理这些逻辑保证了数据的实时性和性能的优化。当依赖数据变化时计算属性会重新计算否则将直接使用缓存的结果。
5. 手动实现简化的计算属性
理解计算属性的实现机制后我们可以尝试手动实现一个简化版本以加深对其原理的理解。 function computedManual(getter){const result ref(); // 用于存储计算属性的结果const runner effect(getter,{lazy:true, // 让 effect 不会立即执行scheduler:(){// 当依赖变化时重新计算并更新 result 的值result.value runner();}})// 立即执行一次 effect初始化 result 的值result.value runner();return {// 返回一个具有 value 属性的对象模拟 ComputedRef 接口get value(){return result.value;},// 提供一个停止响应式依赖更新的方法stop:()stop(runner)}
}// 使用示例
const count ref(1);
const doubled computedManual(() count.value * 2);console.log(doubled.value); // 输出: 2
count.value 2;
console.log(doubled.value); // 输出: 4这个简化的实现利用了 Vue 的 effect 和 ref通过设定 lazy 选项来控制副作用函数的执行同时使用调度器更新计算结果。
6. 结语
计算属性是 Vue 3 响应式系统中不可或缺的一部分它通过缓存和自动更新机制有效地优化了数据处理的性能。通过深入理解其背后的实现原理我们能更好地利用 Vue 提供的响应式功能构建高效的应用。