想到啥写啥的Vue小技巧

33 阅读2分钟

一、组件通信妙招

1. 深层透传属性

<!-- Parent.vue -->
<Child v-bind="$attrs" />

<!-- Child.vue -->
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
console.log(attrs.class) // 获取透传的class
</script>

场景:跨多层组件传递属性时避免逐层声明
亮点:自动继承未声明props,保持组件纯净


2. 依赖注入类型安全

// types.ts
interface UserInfo {
  name: string
  age: number
}

// Parent.vue
provide<UserInfo>('userInfo', { name: 'Alice', age: 28 })

// Child.vue
const user = inject<UserInfo>('userInfo')!

优势:配合TypeScript实现类型安全的provide/inject

二、性能优化技巧

1. 列表渲染优化

<template>
  <div v-for="item in list" :key="item.id" v-memo="[item.id]">
    {{ item.content }}
  </div>
</template>

效果:当item.id不变时跳过虚拟DOM比对
适用:大型静态列表或复杂组件


2. 组件懒加载

<script setup>
import { defineAsyncComponent } from 'vue'

const HeavyComponent = defineAsyncComponent(() =>
  import('./HeavyComponent.vue'), {
    loadingComponent: LoadingSpinner,
    delay: 200 // 延迟显示loading
  }
)
</script>

优势:按需加载减少首包体积

三、组合式API进阶

1. 智能Ref类型

import { ref } from 'vue'

// 自动推断类型为Ref<number>
const count = ref(0)

// 显式声明复杂类型
const user = ref<{ name?: string }>({})

亮点:类型提示 + 响应式统一管理


2. 状态共享Hook

// useCounter.ts
export default function useCounter(initial = 0) {
  const count = ref(initial)
  
  const increment = () => count.value++
  const decrement = () => count.value--

  return { 
    count,
    increment,
    decrement
  }
}

// 组件中使用
const { count, increment } = useCounter()

优势:逻辑复用且保持响应式隔离

四、模板黑科技

1. 动态组件缓存

<template>
  <component :is="currentComponent" v-bind="props" />
</template>

<script setup>
import { shallowRef } from 'vue'

const components = {
  Home: defineAsyncComponent(() => import('./Home.vue')),
  Profile: defineAsyncComponent(() => import('./Profile.vue'))
}

const currentComponent = shallowRef(components.Home)
</script>

技巧:使用shallowRef避免不必要的响应式开销


2. 指令复用策略

<template>
  <div v-auth:edit @click="handleEdit">编辑</div>
</template>

<script setup>
// 权限指令
const vAuth = {
  mounted(el, binding) {
    const hasPermission = checkAuth(binding.arg)
    if (!hasPermission) el.style.display = 'none'
  }
}
</script>

场景:统一权限控制逻辑

五、状态管理优化

1. Pinia自动持久化

// store/user.ts
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    token: localStorage.getItem('token') || ''
  }),
  persist: {
    paths: ['token'],
    storage: sessionStorage // 按需切换存储方式
  }
})

效果:状态关闭浏览器后依然保留


2. Getters动态计算

// store/product.ts
export const useProductStore = defineStore('product', {
  state: () => ({
    items: [] as Product[],
    filter: ''
  }),
  getters: {
    filteredItems: (state) => {
      return state.items.filter(item =>
        item.name.includes(state.filter)
    }
  }
})

优势:带缓存的计算属性式获取

六、调试技巧

1. 组件注入调试信息

<script setup>
import { useDevtools } from '@vue/devtools'

if (process.env.NODE_ENV === 'development') {
  const devtools = useDevtools()
  devtools.inspectState('Custom State', {
    debugValue: 'Vue3 rocks!'
  })
}
</script>

效果:在Vue Devtools中显示自定义调试信息


2. 性能标记

<script setup>
import { startMeasure, stopMeasure } from 'vue-performance-measure'

onMounted(() => {
  startMeasure('ComponentInit')
  // 初始化逻辑...
  stopMeasure('ComponentInit')
})
</script>

输出:在控制台查看组件初始化耗时

七、工程化实践

1. 自动导入组件

// vite.config.js
import Components from 'unplugin-vue-components/vite'

export default defineConfig({
  plugins: [
    Components({
      dts: true, // 生成类型声明
      resolvers: [
        // 自动导入Element Plus组件
        ElementPlusResolver()
      ]
    })
  ]
})

优势:无需手动import组件


2. 路由元信息验证

// router.ts
import { defineRouteMeta } from 'vue-router/auto'

defineRouteMeta({
  auth: true,
  transition: 'fade'
})

// 路由守卫中访问
router.beforeEach((to) => {
  if (to.meta.auth && !isLoggedIn()) return '/login'
})

亮点:类型安全的元数据管理