🎨 今日主菜:Vue 常用技巧全家桶
1. 响应式烹饪秘籍
<script setup>
// 🍳 精准控制响应式
const counter = ref(0); // 基本类型用ref
const user = reactive({ name: '小明', age: 18 }); // 对象用reactive
// 🔥 自动追踪依赖
watchEffect(() => {
console.log(`计数器变化:${counter.value}`);
});
// 🧊 深层监听对象
watch(() => user.age, (newVal, oldVal) => {
console.log(`年龄从 ${oldVal} → ${newVal}`);
}, { deep: true });
</script>
<template>
<button @click="counter++">{{ counter }}</button>
<input v-model="user.age" type="number">
</template>
🔔 核心要点:
ref
处理基本类型,用.value
访问reactive
处理对象/数组,可直接修改属性- 优先使用
watchEffect
自动追踪依赖
2. 组件通信の六脉神剑
🍙 Props/Emits(父子传值)
<!-- 父组件 -->
<Child :title="msg" @update="handleUpdate" />
<!-- 子组件 -->
<script setup>
defineProps(['title']);
const emit = defineEmits(['update']);
const send = () => {
emit('update', '新消息');
}
</script>
🍱 Provide/Inject(跨层传递)
// 祖先组件
provide('theme', { color: 'red' });
// 后代组件
const theme = inject('theme', { color: 'blue' }); // 默认值
🍔 模板引用(直接操作)
<ChildComponent ref="childRef" />
<script setup>
import { ref } from 'vue';
const childRef = ref(null);
// 调用子组件方法
childRef.value.someMethod();
</script>
3. 性能优化小烧烤
<!-- 🚀 静态内容缓存 -->
<div v-once>{{ neverChangeText }}</div>
<!-- 🎯 虚拟滚动优化 -->
<RecycleScroller
:items="bigList"
:item-size="50"
key-field="id"
>
<template #default="{ item }">
<div>{{ item.content }}</div>
</template>
</RecycleScroller>
<!-- 🔥 组件持久化 -->
<KeepAlive include="TabComponent">
<component :is="currentComponent" />
</KeepAlive>
❄️ 冷知识:Vue 3 魔法特性
// 🪄 动态CSS绑定
const color = ref('red');
<style scoped>
.text {
color: v-bind(color);
}
</style>
// 🧩 自动导入组件
// vite.config.js
import Components from 'unplugin-vue-components/vite';
export default {
plugins: [
Components({ /* 自动识别components目录 */ }),
]
}
🌟 实验室魔法厨房
实现智能搜索组件
<template>
<input v-model="keyword" @input="search" />
<div v-if="loading">🌀 加载中...</div>
<ul v-else>
<li v-for="item in results" :key="item.id">
{{ item.name }}
</li>
</ul>
</template>
<script setup>
import { ref, watchDebounced } from '@vueuse/core';
const keyword = ref('');
const results = ref([]);
const loading = ref(false);
watchDebounced(keyword, async (val) => {
if (!val.trim()) return;
loading.value = true;
results.value = await fetchResults(val);
loading.value = false;
}, { debounce: 300 });
</script>
明日秘技:《Vue 3 性能调优の火焰掌——内存泄漏排查指南》 🔥
(留言告诉我你遇到的Vue奇葩问题,本厨神在线诊断!💻)
🛎️ 本日避坑指南:
- v-if 与 v-for 的优先级
<!-- ❌ 错误用法 -->
<li v-for="item in list" v-if="item.visible"></li>
<!-- ✅ 正确姿势 -->
<template v-for="item in list">
<li v-if="item.visible" :key="item.id"></li>
</template>
- 响应式丢失问题
// ❌ 解构会丢失响应性
const { x, y } = reactive({ x: 1, y: 2 });
// ✅ 使用toRefs保持响应
const { x, y } = toRefs(reactiveObj);
- 事件内存泄漏
onMounted(() => {
window.addEventListener('resize', handleResize);
});
// 🚨 必须清理!
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
});