跟着AI学习vue3第二章
第二阶段:深入核心
1. Composition API
理解 Composition API 是啥
在 Vue 2 里,咱们写组件逻辑的时候,是把不同功能的代码分散在 data
、methods
、computed
这些不同的选项里。就好比你有一个工具箱,锤子、螺丝刀、扳手都被放在不同的小格子里。当组件逻辑越来越复杂,要找某个功能的代码就很麻烦。
而 Composition API 就像是给你一个新的整理方式,它可以把相关的逻辑都打包在一起。比如你要做一个跟表单验证相关的功能,用 Composition API 就可以把验证的代码都写在一个地方,方便管理和复用。
学会创建和使用组合函数
组合函数就是把一些逻辑封装起来的函数。举个例子,咱们要做一个计数器功能,每次点击按钮数字就加 1。
// 这是一个组合函数,专门用来处理计数器逻辑
import { ref } from 'vue';
export function useCounter() {
// 创建一个响应式的变量 count,初始值为 0
const count = ref(0);
// 定义一个函数,用来让 count 的值加 1
const increment = () => {
count.value++;
};
// 把 count 和 increment 函数返回出去,这样其他地方就能用了
return {
count,
increment
};
}
然后在组件里使用这个组合函数:
<template>
<div>
<!-- 显示 count 的值 -->
<p>{{ count }}</p>
<!-- 点击按钮调用 increment 函数 -->
<button @click="increment">增加</button>
</div>
</template>
<script setup>
// 引入组合函数
import { useCounter } from './useCounter.js';
// 使用组合函数,得到 count 和 increment
const { count, increment } = useCounter();
</script>
这样,计数器的逻辑就被封装在 useCounter
函数里,以后其他组件也能用这个函数,实现代码复用。
掌握 setup
函数
setup
函数是 Composition API 的入口。当组件创建的时候,setup
函数就会先执行。在 setup
函数里,咱们可以使用响应式数据、生命周期钩子等。
<template>
<div>
<p>{{ message }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
// 创建一个响应式的 message 变量
const message = ref('Hello from setup!');
</script>
2. 生命周期钩子
生命周期钩子就像是组件的不同“人生阶段”,在这些阶段我们可以执行一些特定的代码。
认识各个生命周期钩子
onBeforeMount
:在组件挂载到页面之前触发。就好比你要搬家,在东西还没搬到新家之前,你可以做一些准备工作,比如检查新家的水电是否正常。
<template>
<div></div>
</template>
<script setup>
import { onBeforeMount } from 'vue';
onBeforeMount(() => {
console.log('组件马上要挂载了,先做些准备');
});
</script>
onMounted
:组件已经挂载到页面之后触发。就像你已经把东西搬到新家,并且都摆放好了,这时候可以开始在新家生活啦。
<template>
<div></div>
</template>
<script setup>
import { onMounted } from 'vue';
onMounted(() => {
console.log('组件已经挂载好,可以开始干活啦');
});
</script>
onBeforeUpdate
:在组件数据更新之前触发。比如你要修改家里的家具摆放,在动手之前先计划一下怎么改。onUpdated
:组件数据更新之后触发。就像你已经把家具摆放好了,看看效果怎么样。onBeforeUnmount
:在组件销毁之前触发。就像你要搬离这个家,在走之前把东西整理一下。onUnmounted
:组件销毁之后触发。就像你已经搬离了这个家,这个家跟你没关系了。
3. 组件化开发
学会创建和使用组件
组件就像是一个个小零件,我们可以把一个大的页面拆分成很多小的组件,这样代码会更清晰,也更容易维护。
创建一个组件很简单,比如创建一个 HelloWorld
组件:
<!-- HelloWorld.vue -->
<template>
<div>
<h1>{{ message }}</h1>
</div>
</template>
<script setup>
import { ref } from 'vue';
const message = ref('Hello, World!');
</script>
<style scoped>
h1 {
color: blue;
}
</style>
然后在另一个组件里使用它:
<template>
<div>
<!-- 使用 HelloWorld 组件 -->
<HelloWorld />
</div>
</template>
<script setup>
// 引入 HelloWorld 组件
import HelloWorld from './HelloWorld.vue';
</script>
掌握组件之间的通信方式
props
:就像是给组件传递参数。比如你有一个UserInfo
组件,用来显示用户信息,你可以通过props
把用户的姓名、年龄等信息传递给它。
<!-- UserInfo.vue -->
<template>
<div>
<p>姓名: {{ name }}</p>
<p>年龄: {{ age }}</p>
</div>
</template>
<script setup>
import { defineProps } from 'vue';
// 定义 props
const props = defineProps({
name: String,
age: Number
});
</script>
在使用 UserInfo
组件的时候传递参数:
<template>
<div>
<!-- 传递 name 和 age 参数 -->
<UserInfo :name="userName" :age="userAge" />
</div>
</template>
<script setup>
import { ref } from 'vue';
import UserInfo from './UserInfo.vue';
const userName = ref('张三');
const userAge = ref(25);
</script>
emit
:子组件可以通过emit
向父组件发送消息。比如子组件里有一个按钮,点击按钮时通知父组件做一些事情。
<!-- ChildComponent.vue -->
<template>
<div>
<button @click="sendMessage">点击我通知父组件</button>
</div>
</template>
<script setup>
import { defineEmits } from 'vue';
// 定义可以触发的事件
const emits = defineEmits(['messageSent']);
const sendMessage = () => {
// 触发 messageSent 事件,并传递数据
emits('messageSent', '这是子组件发来的消息');
};
</script>
在父组件里监听这个事件:
<template>
<div>
<ChildComponent @messageSent="handleMessage" />
</div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue';
const handleMessage = (message) => {
console.log('收到子组件的消息:', message);
};
</script>
v-model
:这是一种更简洁的双向数据绑定方式。比如有一个InputComponent
组件,用来输入内容,使用v-model
可以让父组件和子组件的数据保持同步。
<!-- InputComponent.vue -->
<template>
<div>
<input v-model="localValue" @input="updateValue">
</div>
</template>
<script setup>
import { defineProps, defineEmits, ref } from 'vue';
const props = defineProps({
modelValue: String
});
const emits = defineEmits(['update:modelValue']);
const localValue = ref(props.modelValue);
const updateValue = () => {
emits('update:modelValue', localValue.value);
};
</script>
在父组件里使用:
<template>
<div>
<InputComponent v-model="inputText" />
<p>输入的内容是: {{ inputText }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
import InputComponent from './InputComponent.vue';
const inputText = ref('');
</script>
通过组件化开发,我们可以把一个复杂的项目拆分成一个个小的组件,每个组件负责自己的功能,这样代码的可维护性就大大提高了。