Vue 3 高级编程技巧
1. 计算属性 (Computed Properties)
含义:计算属性在依赖变化时会自动更新。以下是一个示例,展示当 firstName 或 lastName 变化时,fullName 也会更新。
实例:
<script setup>
import { ref, computed } from 'vue';
const firstName = ref('John');
const lastName = ref('Doe');
// 计算属性
const fullName = computed(() => {
return `${firstName.value} ${lastName.value}`;
});
const reversedFullName = computed(() => {
return fullName.value.split('').reverse().join('');
});
const fullNameLength = computed(() => {
return fullName.value.length;
});
</script>
<template>
<div>
<input v-model="firstName" placeholder="First Name" />
<input v-model="lastName" placeholder="Last Name" />
<p>Full Name: {{ fullName }}</p>
<p>Reversed Full Name: {{ reversedFullName }}</p>
<p>Full Name Length: {{ fullNameLength }}</p>
</div>
</template>
2. 插槽 (Slots)
含义:插槽允许组件接收模板内容,并在组件内部渲染这些内容。它们提供了灵活的布局和内容分发机制。使用 #header 或 v-slot 语法来定义插槽内容。
实例:
<!-- ParentComponent.vue -->
<script setup>
import ChildComponent from './ChildComponent.vue';
</script>
<template>
<ChildComponent>
<template #header>
<h1>Header Content</h1>
</template>
<p>Default Slot Content</p>
</ChildComponent>
</template>
<!-- ChildComponent.vue -->
<script setup>
</script>
<template>
<div>
<slot name="header"></slot>
<slot></slot>
</div>
</template>
3. 动态组件 (Dynamic Components)
含义:动态组件允许在运行时根据需要切换不同的组件。结合 component
标签和 is
属性实现。
实例:
<script setup>
import { ref } from 'vue';
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';
const currentComponent = ref('ComponentA');
</script>
<template>
<component :is="currentComponent" />
<button @click="currentComponent = 'ComponentA'">Show Component A</button>
<button @click="currentComponent = 'ComponentB'">Show Component B</button>
</template>
4. 自定义指令 (Custom Directives)
含义:自定义指令用于直接操作 DOM 元素,可以用于添加事件监听器、修改样式等。
实例:
<script setup>
import { onMounted } from 'vue';
const vFocus = {
mounted(el) {
el.focus();
}
};
const vHighlight = {
mounted(el) {
el.style.backgroundColor = 'yellow';
}
};
const vLog = {
mounted(el) {
console.log('Element mounted:', el);
}
};
</script>
<template>
<input v-focus />
<div v-highlight>Highlighted Text</div>
<div v-log>This element logs to console on mount.</div>
</template>
5. watch
含义:watch
用于观察和响应 Vue 实例上的数据变动。当数据发生变化时,watch
可以执行异步操作或开销较大的操作,并获取变化前后的值。
实例:
<script setup>
import { ref, watch } from 'vue';
const message = ref('Hello Vue!');
const count = ref(0);
const items = ref(['apple', 'banana', 'cherry']);
const user = ref({ name: 'Alice', age: 30 });
// 监听单个响应式变量
watch(message, (newVal, oldVal) => {
console.log(`message changed from ${oldVal} to ${newVal}`);
});
// 监听对象属性
watch(
() => user.value.name,
(newName, oldName) => {
console.log(`user name changed from ${oldName} to ${newName}`);
}
);
// 监听数组的单个元素
watch(
() => items.value[0],
(newVal, oldVal) => {
console.log(`First item changed from ${oldVal} to ${newVal}`);
}
);
// 监听多个响应式变量
watch([message, count], ([newMessage, newCount], [oldMessage, oldCount]) => {
console.log(`message changed from ${oldMessage} to ${newMessage}`);
console.log(`count changed from ${oldCount} to ${newCount}`);
});
// 监听数组的多个元素
watch(
[() => items.value[0], () => items.value[1]],
([newFirst, newSecond], [oldFirst, oldSecond]) => {
console.log(`First item changed from ${oldFirst} to ${newFirst}`);
console.log(`Second item changed from ${oldSecond} to ${newSecond}`);
}
);
// 深度监听对象
watch(
user,
(newVal) => {
console.log('user changed:', newVal);
},
{ deep: true }
);
</script>
<template>
<div>
<input v-model="message" placeholder="Message" />
<button @click="count++">Increment Count: {{ count }}</button>
<button @click="items[0] = 'orange'">Change First Item</button>
<button @click="items[1] = 'grape'">Change Second Item</button>
<button @click="user.name = 'Bob'">Change User Name</button>
</div>
</template>
6. provide
+ inject
含义:provide
和 inject
用于在组件树中传递数据,适用父子组件,查找第一层父/子组件传递的数据
实例:
<!-- ParentComponent.vue -->
<script setup>
import { provide, ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const theme = ref('dark');
provide('theme', theme);
</script>
<template>
<ChildComponent />
</template>
<!-- ChildComponent.vue -->
<script setup>
import { inject } from 'vue';
const theme = inject('theme');
</script>
<template>
<div :class="theme">
Current theme: {{ theme }}
</div>
</template>