概念:生命周期钩子是 Vue 组件在其生命周期内不同阶段触发的函数,允许开发者在这些关键时刻插入自定义逻辑。
规律:
生命周期整体分为四个阶段,分别是:创建、挂载、更新、销毁,每个阶段都有两个钩子,一前一后。
Vue2 生命周期钩子
创建阶段
挂载阶段
更新阶段
销毁阶段
Vue3 生命周期钩子
创建阶段
挂载阶段
更新阶段
卸载阶段
常用的钩子:onMounted(挂载完毕)、onUpdated(更新完毕)、onBeforeUnmount(卸载之前)
示例代码:
当前求和为:{{ sum }}
在 Vue3 中,自定义钩子(或称为自定义组合函数)是一个函数,利用了 Vue 的组合式 API(Composition API),它封装了逻辑并允许在多个组件之间共享和复用这些逻辑。这与 Vue2 中的 mixin 类似,但自定义钩子更具灵活性和可维护性。
示例代码:
useSum.ts - 自定义 hook 用于管理计数器逻辑。
import { ref, onMounted } from 'vue';
/**
* 用于管理一个累加器的钩子函数
*
* 提供累加、累减操作以及当前累加和的获取
*/
export default function useSum() {
// 定义一个响应式变量 sum,用于存储当前的累加和
let sum = ref(0);
/**
* 累加操作
* 将 sum 的值增加 1
*/
const increment = () => {
sum.value += 1;
};
/**
* 累减操作
* 将 sum 的值减少 1
*/
const decrement = () => {
sum.value -= 1;
};
// 在组件挂载后调用 increment,对 sum 进行初始累加
onMounted(() => {
increment();
});
// 返回当前的累加和以及改变累加和的方法
return { sum, increment, decrement };
}
useDog.ts - 自定义 hook 用于管理狗狗图片的获取和加载。
import { reactive, onMounted } from 'vue';
import axios, { AxiosError } from 'axios';
/**
* 用于获取狗狗图片的自定义钩子
*
* 该钩子提供了一个函数用于获取狗狗图片,并管理图片加载状态和图片URL列表
*/
export default function useDog() {
// 状态管理对象,用于存储狗狗图片的URL列表和加载状态
let dogList = reactive<{ urlList: string[], isLoading: boolean }>({
urlList: [],
isLoading: false
});
/**
* 异步获取狗狗图片
*
* 该函数通过调用API获取狗狗图片的URL,并将其添加到urlList中
* 在获取图片前后更新isLoading状态,以反映加载状态
*/
const getDog = async () => {
dogList.isLoading = true;
try {
const { data } = await axios.get('https://dog.ceo/api/breed/pembroke/images/random');
dogList.urlList.push(data.message);
} catch (error) {
const err = error;
console.log(err.message);
} finally {
dogList.isLoading = false;
}
};
// 在组件挂载时自动调用getDog函数以获取狗狗图片
onMounted(() => {
getDog();
});
// 返回包含dogList状态和getDog函数的对象,供外部使用
return { dogList, getDog };
}
组件使用 - 使用这两个自定义钩子。
当前求和为:{{ sum }}
加载中......
Vue 3 的路由处理主要通过 Vue Router 库来实现。
Vue Router 是 Vue.js 的官方路由库,用于实现单页应用中的路由功能。它允许开发者定义 URL 与视图之间的映射,使得应用能够根据不同的 URL 显示不同的组件或页面,而不需要重新加载整个页面。
要在 Vue 3 项目中使用 Vue Router,首先需要安装它:
npm install vue-router@4
然后,在项目中创建和配置路由。以下是一个简单的配置示例:
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router';
import HomeView from '../views/HomeView.vue';
import AboutView from '../views/AboutView.vue';
const routes = [
{ path: '/', component: HomeView },
{ path: '/about', component: AboutView }
];
const router = createRouter({
history: createWebHistory(), // 使用 HTML5 History API
routes
});
export default router;
在 src/main.ts 中将路由实例添加到 Vue 应用中:
// src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
const app = createApp(App);
app.use(router);
app.mount('#app');
在 Vue Router 中,路由通常通过以下组件来显示:
两个注意点
哈希模式:使用 createWebHashHistory() 来创建路由实例,URL 会包含一个 # 符号。适用于一些不支持 HTML5 History API 的环境。
历史模式:使用 createWebHistory() 来创建路由实例,它提供更自然的 URL 结构。需要服务器配置,以便能够处理所有的 URL 请求。
const router = createRouter({
history: createWebHistory(), // 或者 createWebHashHistory()
routes
});
在模板中使用
命名路由是 Vue Router 提供的一种功能,它允许我们为路由定义一个名称,从而在导航时可以使用这个名称而不是路径。这种方式特别适用于大型应用,能提高代码的可维护性和灵活性。
如何定义命名路由
在路由配置中,可以为每个路由定义一个 name 属性。以下是一个示例:
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router';
import HomeView from '../views/HomeView.vue';
import AboutView from '../views/AboutView.vue';
const routes = [
{
path: '/',
name: 'home', // 命名路由
component: HomeView
},
{
path: '/about',
name: 'about', // 命名路由
component: AboutView
}
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
使用命名路由进行导航
可以在
命名路由的好处
Vue Router 支持嵌套路由,使得可以在一个页面内展示子页面。例如,一个博客文章页面可以有评论作为嵌套的子路由:
const routes = [
{
path: '/post/:id',
component: PostView,
children: [
{
path: 'comments',
component: CommentsView
}
]
}
];
在 Vue Router 中,可以通过多种方式传递参数到路由。常见的方式包括路径参数、查询参数和路由元数据。
路径参数
路径参数是路由定义中的动态部分。例如,定义一个用户详情页面路由时,可以在路径中使用占位符:
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router';
import UserProfile from '../views/UserProfile.vue';
const routes = [
{
path: '/user/:id',
name: 'user-profile',
component: UserProfile
}
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
在组件中,可以通过 this.$route.params 访问这些参数:
User ID: {{ userId }}
查询参数
查询参数附加在 URL 的末尾,以 ? 开始,多个参数时,例如 :“/news/detail?a=1&b=2&content=欢迎你”。可以通过 :to 属性传递查询参数:
User Profile
在组件中,使用 this.$route.query 访问查询参数:
Query ID: {{ queryId }}
路由元数据
虽然不直接用于导航,但路由元数据(meta 字段)可以用于存储其他信息,如访问权限或页面标题:
const routes = [
{
path: '/profile',
name: 'profile',
component: UserProfile,
meta: { requiresAuth: true }
}
];
在导航守卫中可以访问这些元数据:
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !isAuthenticated) {
next('/login');
} else {
next();
}
});
总结
在 Vue Router 中,props 配置允许将路由参数直接作为组件的 props 传递,这样可以使组件更具可重用性和测试性。
在路由定义中,可以通过 props 属性将路由参数传递给组件。可以配置为 true、false 或一个函数:
布尔值 true
const routes = [
{
path: '/user/:id',
name: 'user-profile',
component: UserProfile,
props: true // 将路由参数作为 props 传递
}
];
在 UserProfile 组件中,可以直接使用 id prop:
User ID: {{ id }}
函数
const routes = [
{
path: '/user/:id',
name: 'user-profile',
component: UserProfile,
props: route => ({ id: route.params.id }) // 自定义 props
}
];
在 UserProfile 组件中,同样可以使用 id prop:
User ID: {{ id }}
为什么使用 props
作用
replace 属性用于控制路由跳转时如何操作浏览器的历史记录。它决定了是否在历史记录中替换当前条目,而不是新增一个条目。
浏览器的历史记录写入方式
开启 replace 模式
在
Go to User Profile
在编程式导航中使用
在编程式导航中,可以通过将 replace 选项设置为 true 来替换当前的历史记录条目:
// 使用 replace 进行编程式导航
this.$router.push({ name: 'user-profile', params: { id: 123 }, replace: true });
在这种情况下,replace: true 确保了当前的历史记录条目被新的条目替换,而不是在历史记录中添加新的条目。
何时使用 replace 属性
编程式导航允许你在代码中控制路由跳转,而不是仅仅依赖于
基本用法
在 Vue 组件中,可以使用 this.$router 对象进行编程式导航。例如,跳转到某个路径:
this.$router.push('/new-path');
带参数的导航
可以在导航时传递参数,例如:
this.$router.push({ name: 'user-profile', params: { id: 123 } });
重定向与 replace 属性
使用 replace 选项来替换当前历史记录条目,而不是添加新条目:
this.$router.replace('/new-path');
处理导航错误
可以使用 catch 处理导航错误,例如路由不存在的情况:
this.$router.push('/unknown-path').catch(err => {
console.error(err);
});
使用导航守卫
路由守卫用于在路由导航前或后执行特定的逻辑。Vue Router 提供了多种类型的路由守卫:
beforeRouteEnter(to, from, next) {
if (to.meta.requiresAuth) {
// 需要认证的逻辑
next('/login');
} else {
next();
}
}
在 Vue Router 中,重定向用于将用户自动导航到另一个路由。当某个特定的路径被访问时,可以使用重定向将用户引导到预定的路径。
基本重定向
可以在路由配置中使用 redirect 属性来设置重定向。例如,当访问 /old-path 时,将自动重定向到 /new-path:
const routes = [
{ path: '/old-path', redirect: '/new-path' },
{ path: '/new-path', component: NewPathComponent },
];
动态重定向
可以使用函数动态决定重定向的目标。例如,根据某个条件决定重定向的路径:
const routes = [
{
path: '/redirect-me',
redirect: to => {
return to.query.loggedIn ? '/home' : '/login';
}
},
{ path: '/home', component: HomeComponent },
{ path: '/login', component: LoginComponent },
];
重定向与 replace 属性
在编程式导航中,可以结合 replace 属性来控制是否在历史记录中创建新的条目。例如,在重定向后使用 replace 属性来避免在历史记录中添加新条目:
// 使用 replace 进行编程式重定向
this.$router.replace('/home');
总结