Skip to content

返回函数计算属性原理 ​

本节目标:理解“返回函数计算属性原理”的核心思路,并能把它用于实际开发或面试表达。 在 Vue 中,如果一个计算属性返回一个函数(如 computed(() => (param) => {...})),以下是关键点:

  1. 缓存的是函数本身:
    • 计算属性的缓存机制作用于返回的函数对象。当依赖(如 tradeType.value 或 props)不变时,Vue 缓存的是同一个函数实例,不会重新生成新的函数。
    • 例如,在你的例子中,getStyle 计算属性返回的函数对象在依赖不变时始终是同一个。
  2. 函数调用仍然会执行:
    • 每次在模板中调用 getStyle(type)(如在 v-for 中),函数的内部逻辑都会执行,因为函数调用本身不被缓存。计算属性的缓存只保证返回的函数是同一个实例,但调用函数时仍会根据传入的参数(type)重新计算结果。
    • 换句话说,缓存的是 getStyle 的返回值(即函数本身),而不是 getStyle(type) 的调用结果。
  3. 与普通方法的区别:
    • 如果你用普通方法(methods)定义 getStyle(type),每次调用都会完整执行逻辑,且没有缓存。
    • 用计算属性返回函数,虽然函数调用本身会执行,但函数的创建和依赖的响应式更新被缓存,适合依赖响应式数据的场景。

验证你的理解

  • 缓存:当 tradeType.value、props.askColor 或 props.bidColor 不变时,getStyle 返回的函数是缓存的同一个函数实例。
  • 执行:在模板渲染时,如 <div :style="getStyle(type)">,每次调用 getStyle(type) 都会执行函数内部逻辑,计算基于 type 的样式对象。

示例说明 <script setup lang="ts">import { computed } from 'vue'import { TradeType } from '@/enum' const tradeType = defineModel<TradeType>('tradeType')const props = defineProps<{ bidColor: string; askColor: string }>() const getStyle = computed(() => { console.log('getStyle computed ran') // 仅在依赖变化时触发 return (type: TradeType) => { console.log(getStyle called with ${type}) // 每次调用都会触发 const isSelected = type === tradeType.value return { color: isSelected ? 'white' : type === 'sell' ? props.askColor : props.bidColor, backgroundColor: isSelected ? (type === 'sell' ? props.askColor : props.bidColor) : 'white', } }})</script> <template> <div v-for="type in Object.values(TradeType)" :style="getStyle(type)"> {{ type }} </div></template> 运行时表现:

  • 初次渲染或依赖(如 tradeType.value)变化时,getStyle computed ran 打印一次,表明计算属性重新计算并返回新函数。
  • 每次 v-for 渲染时,getStyle called with ${type} 会为每个 type 打印,表明函数调用仍然执行。

如何进一步优化 如果你希望连函数调用的结果也缓存(而不仅是函数本身),可以改用对象形式的计算属性,如之前的 styleMap 示例: const styleMap = computed(() => { const result: Record<TradeType, { color: string; backgroundColor: string }> = {} as any Object.values(TradeType).forEach((type) => { const isSelected = type === tradeType.value result[type] = { color: isSelected ? 'white' : type === 'sell' ? props.askColor : props.bidColor, backgroundColor: isSelected ? (type === 'sell' ? props.askColor : props.bidColor) : 'white', } }) return result})

  • 模板使用::style="styleMap[type]"
  • 优势:styleMap 缓存了所有 type 的样式对象,调用 styleMap[type] 直接返回缓存结果,不需要每次执行函数逻辑。

本站总访问 — 次