vue3中setup
# 在 Vue 3 中,useStore()
和 useRouter()
是 Composition API 中的两个钩子函数,分别用于访问 Vuex store 和 Vue Router 实例。
# 为什么需要在组件中使用 const store = useStore()
和 const router = useRouter()
?
Composition API 的设计原则: Vue 3 引入了 Composition API,这是一个更灵活、模块化的 API 设计,它允许开发者在组件的
setup()
函数中组织逻辑。这种设计能够将组件的逻辑和状态管理分离,使得组件逻辑更加清晰且易于复用。useStore()
和useRouter()
钩子是 Vue 3 中对 Vuex 和 Vue Router 的访问接口,配合 Composition API 使用。与 Vue 2 中的选项式 API 相比,这种方式更加灵活、明确。访问 Vuex 和 Vue Router 实例: 在 Vue 2 中,你可以直接在组件中通过
this.$store
和this.$router
访问 Vuex 和 Vue Router 实例。然而,Vue 3 中的 Composition API 不使用this
,而是通过函数来访问响应式数据和实例。useStore()
:访问 Vuex store 实例,允许你在setup()
函数中使用 Vuex 状态、getter、mutation 和 action。useRouter()
:访问 Vue Router 实例,允许你在setup()
函数中进行路由跳转、获取路由信息等操作。
响应式与组件状态的解耦: 在 Vue 3 中,
useStore()
和useRouter()
使得你能够在setup()
函数内直接引用 Vuex 和 Vue Router 实例,这样能确保这些实例在组件内是响应式的,并且能够和组件中的其他响应式数据结合使用。例如,你可以使用store
来直接响应数据变化,或者使用router
来执行路由跳转,而无需依赖this
上的任何属性。增强可读性和测试性: 使用
useStore()
和useRouter()
使得你的组件逻辑更加清晰,易于组织。它不仅能避免this
的困扰,还能让你更容易地进行单元测试,因为你可以在测试中直接 mock 或模拟 Vuex 和 Vue Router 的实例,而不依赖于全局的 Vue 实例。
# 示例:在 setup()
中使用 useStore()
和 useRouter()
<template>
<div>
<h1>{{ user }}</h1>
<button @click="goToProfile">Go to Profile</button>
</div>
</template>
<script>
import { useStore } from 'vuex'; // 导入 useStore 钩子
import { useRouter } from 'vue-router'; // 导入 useRouter 钩子
export default {
setup() {
const store = useStore(); // 获取 Vuex store 实例
const router = useRouter(); // 获取 Vue Router 实例
// 通过 Vuex store 获取数据
const user = store.state.user;
// 路由跳转函数
const goToProfile = () => {
router.push('/profile'); // 跳转到用户的个人页面
};
return {
user,
goToProfile,
};
},
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 关键点:
使用
useStore()
访问 Vuex:useStore()
返回 Vuex store 实例,你可以通过它访问 store 的状态、获取器(getters)、变更(mutations)和分发(actions)等。- 例如:
const user = store.state.user
,这里从 Vuex 中获取了user
状态。
使用
useRouter()
访问 Vue Router:useRouter()
返回 Vue Router 实例,你可以通过它执行路由跳转(router.push()
)或访问当前路由的信息(router.currentRoute
)。- 例如:
router.push('/profile')
,这里实现了路由跳转。
# 为什么 setup()
中要使用这些钩子?
组件的逻辑集中: 在
setup()
中,你可以集中管理和初始化所有与组件相关的逻辑,例如响应式数据、计算属性、事件处理、外部实例(如 Vuex 和 Vue Router)。无
this
访问: Vue 3 的 Composition API 去除了this
的使用,让代码更加清晰和易于理解。通过useStore()
和useRouter()
,你可以在setup()
中直接访问它们,而不需要依赖this.$store
或this.$router
。更好的测试性: 通过钩子访问
store
和router
,使得组件更加独立、模块化。这意味着你可以轻松地对组件进行单元测试,而不依赖于全局的this
。
# 总结
在 Vue 3 中,useStore()
和 useRouter()
是 Composition API 的一部分,提供了访问 Vuex 和 Vue Router 实例的方式。它们替代了 Vue 2 中通过 this.$store
和 this.$router
的访问方式,允许你在 setup()
中使用这些实例,帮助你更灵活、更清晰地组织组件逻辑,并且增强了代码的可测试性。
# Vue 3 的 Composition API 是一种新的组织组件逻辑的方式,它使得代码更易于组织、复用和维护。
# 1. Vue 2 的选项式 API(传统方式)
在 Vue 2 中,我们通常通过在组件的不同选项中定义逻辑来组织代码:
data
:用于定义响应式数据methods
:定义组件中的方法computed
:计算属性watch
:监听属性变化mounted
等生命周期钩子
例如:
export default {
data() {
return {
count: 0
};
},
methods: {
increment() {
this.count++;
}
},
mounted() {
console.log("组件已挂载");
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这种方式在简单的组件中很好用,但随着组件逻辑复杂度的增加(例如多个功能、多个状态管理),代码会变得很难组织和维护。
# 2. Composition API 的核心思想
Composition API 的核心思想是:将相关的逻辑组合在一起,而不是将它们拆散到不同的选项里。通过这种方式,逻辑更加集中,代码结构更加清晰,特别是当组件有多个功能时。
# 2.1 setup()
函数:组件的入口
setup()
是 Composition API 的核心,它在组件实例化之前执行,主要用于初始化数据、响应式状态、方法、计算属性等。你在 setup()
内部定义的内容会自动被 Vue 3 处理为响应式,并可以在模板中直接使用。
例如,你可以在 setup()
函数中定义数据、方法和生命周期钩子,所有逻辑都可以在这里组合。
import { ref, onMounted } from 'vue';
export default {
setup() {
// 定义响应式数据
const count = ref(0);
// 定义方法
const increment = () => {
count.value++;
};
// 使用生命周期钩子
onMounted(() => {
console.log("组件已挂载");
});
// 返回这些数据和方法,供模板使用
return {
count,
increment
};
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 2.2 响应式数据:ref
和 reactive
在 Composition API 中,响应式数据是通过 ref()
和 reactive()
来创建的。
ref()
:用来创建基本类型的响应式数据。reactive()
:用来创建对象或数组的响应式数据。
import { ref, reactive } from 'vue';
export default {
setup() {
// 创建基本类型的响应式数据
const count = ref(0);
// 创建对象的响应式数据
const user = reactive({ name: 'Alice', age: 25 });
return {
count,
user
};
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 2.3 计算属性:computed()
computed()
用来创建计算属性,它根据其他响应式数据的变化来动态计算值。
import { computed } from 'vue';
export default {
setup() {
const count = ref(0);
// 使用 computed 创建计算属性
const doubledCount = computed(() => count.value * 2);
return {
count,
doubledCount
};
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 2.4 生命周期钩子
在 Composition API 中,生命周期钩子也被移到了 setup()
内部。我们通过一些函数(如 onMounted
、onBeforeUnmount
等)来使用生命周期钩子,而不再使用 Vue 2 中的选项式 API。
import { onMounted, onBeforeUnmount } from 'vue';
export default {
setup() {
onMounted(() => {
console.log('组件已挂载');
});
onBeforeUnmount(() => {
console.log('组件即将销毁');
});
}
};
2
3
4
5
6
7
8
9
10
11
12
13
# 3. Composition API 的优点
逻辑复用性:你可以将相关的逻辑提取成函数,使其在多个组件间复用,而不需要像 Vue 2 中那样通过混入(mixin)或者继承来复用逻辑。
例如,你可以创建一个自定义组合式函数(composable),专门处理组件的某一部分逻辑:
// useCounter.js import { ref } from 'vue'; export function useCounter() { const count = ref(0); const increment = () => count.value++; return { count, increment }; }
1
2
3
4
5
6
7
8然后在组件中复用:
import { useCounter } from './useCounter'; export default { setup() { const { count, increment } = useCounter(); return { count, increment }; } };
1
2
3
4
5
6
7
8
9更好的代码组织:在
setup()
中,你可以将所有的逻辑组织在一起,比如状态管理、计算属性、方法、生命周期钩子等。这比 Vue 2 中需要分别放在data
、methods
、computed
和watch
中要直观得多。更强的类型推导(TypeScript 支持):由于 Composition API 使用了函数式编程的方式,它可以更好地支持 TypeScript,提供更精确的类型推导。
避免
this
:在 Vue 3 中,this
不再用于访问组件的状态和方法,这使得组件的逻辑更容易理解和测试。
# 4. 总结
Composition API 的核心理念是将 相关的功能逻辑组合到一起,而不是将它们分散在不同的选项中。这种方式使得组件更加灵活、易于复用和维护。通过 setup()
、ref()
、reactive()
等函数,我们可以在同一地方集中定义响应式数据、方法、计算属性和生命周期钩子。
对于开发者来说,Composition API 使得逻辑更容易拆分、复用,尤其是在大型应用中,代码的结构和可维护性都得到了提升。