考察点分析

本题主要考核以下核心能力维度:

  1. 组合式API机制理解:考察对Vue3组合式API设计理念的掌握,包括逻辑拆分与复用策略
  2. 响应式系统运用:检验ref/reactive等响应式API的正确使用,及在组合函数中的值传递
  3. 生命周期整合:评估在自定义hook中正确绑定/清除副作用(如事件监听、异步请求)
  4. 代码抽象能力:验证业务逻辑解耦能力,包括参数处理、状态暴露、错误边界等工程化实践

具体技术评估点:

  • 组合函数的命名规范与结构
  • 响应式数据在组件间的状态保持
  • 生命周期钩子的正确绑定
  • 异步操作的竞态处理(如请求取消)
  • TypeScript类型支持实现

技术解析

关键知识点

Composition API Design > 响应式系统 > 生命周期管理 > TypeScript类型推导

原理剖析

组合函数本质是返回响应式状态+函数的闭包封装,利用Vue的setup()执行上下文实现逻辑复用。通过ref维持响应式引用,在onMounted等钩子中绑定原生事件或异步操作,通过onUnmounted进行资源清理,避免内存泄漏。

典型错误包括:

  1. 直接返回解构对象导致响应式丢失
  2. 未在卸载阶段移除事件监听
  3. 异步回调中使用过期状态

常见误区

  • 在组合函数内直接修改DOM(违反响应式原则)
  • 忘记处理异步操作的错误状态
  • 多个组件实例共享同一响应式引用(未使用函数式返回)

问题解答

通过组合函数封装逻辑需遵循以下步骤:

  1. 创建以use开头的函数,使用ref/reactive封装状态
  2. 在setup阶段执行副作用(如事件绑定)
  3. 返回组件可用的响应式状态与方法
  4. 使用toRefs保持解构后响应式

鼠标跟踪器示例

  import { ref, onMounted, onUnmounted } from 'vue'

export function useMouse() {
  const x = ref(0)
  const y = ref(0)
  
  const update = (e) => {
    x.value = e.pageX
    y.value = e.pageY
  }

  onMounted(() => {
    window.addEventListener('mousemove', update)
  })

  onUnmounted(() => {
    window.removeEventListener('mousemove', update)
  })

  return { x, y }
}
  

API请求示例

  import { ref } from 'vue'

export function useFetch<T>(url: string) {
  const data = ref<T | null>(null)
  const error = ref<Error | null>(null)
  const loading = ref(false)
  
  const fetchData = async () => {
    try {
      loading.value = true
      const response = await fetch(url)
      data.value = await response.json()
    } catch (err) {
      error.value = err as Error
    } finally {
      loading.value = false
    }
  }

  return {
    data,
    error,
    loading,
    fetchData
  }
}
  

解决方案

编码优化

  1. 防抖处理:为鼠标跟踪添加移动节流

      import { throttle } from 'lodash-es'
    
    const update = throttle((e) => {
      //...原有逻辑
    }, 50)
      
  2. 请求竞态处理

      let controller: AbortController | null = null
    
    const fetchData = async () => {
      if (controller) {
        controller.abort()
      }
      controller = new AbortController()
    
      try {
        const response = await fetch(url, {
          signal: controller.signal
        })
        //...
      } finally {
        controller = null
      }
    }
      

可扩展性建议

  • SSR兼容:在组合函数内判断window对象存在性
  • 缓存策略:为API请求添加SWR(Stale While Revalidate)逻辑
  • 类型扩展:通过泛型支持多样化返回类型
  • 低端设备优化:降低鼠标采样频率

深度追问

  1. 组合函数与mixins的主要区别?

    作用域隔离:组合函数使用显式返回,mixins易导致属性冲突

  2. 如何在组合函数中使用生命周期?

    直接引入钩子函数,执行时机与组件生命周期同步

  3. TypeScript类型声明最佳实践?

    使用泛型约束返回类型,定义明确的接口类型

Last updated 06 Mar 2025, 13:07 +0800 . history