每次上官网查阅资料就很累,所以从官网cv了点下来
常用中间件
Vue-Router 路由
安装
npm install vue-router@4
yarn add vue-router@4
pnpm add vue-router@4使用
import { createRouter } from 'vue-router'router.ts
路由一般配置在src/router/index.ts文件下
import { createMemoryHistory, createRouter } from 'vue-router'
import HomeView from './HomeView.vue'
import AboutView from './AboutView.vue'
const routes = [
{ path: '/', component: HomeView },
{ path: '/about', component: AboutView },
]
const router = createRouter({
history: createMemoryHistory(),
routes,
})
export default router然后在src/main.ts中使用注册
// const app = createApp(App)
app.use(router)
// app.mount('#app')在页面中使用
父元素
<template>
<router-link to="/home">Home</router-link>
<router-view />
</template>在router.ts中注册
const routes = [{ path: '/path', component: Comp }]如果嵌套
const routes = [
{
path: '/user/:id', // 可以在{{ $route.params.id }}匹配到(string类型)
component: User,
children: [
{
// 当 /user/:id/profile 匹配成功
// UserProfile 将被渲染到 User 的 <router-view> 内部
path: 'profile',
component: UserProfile,
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 将被渲染到 User 的 <router-view> 内部
path: 'posts',
component: UserPosts,
},
],
},
]
const routes = [
{
path: '/user/:id',
component: User, // 父组件component其实可以去掉
// 请注意,只有子路由具有名称
children: [{ path: '', name: 'user', component: UserHome }],
},
]导航守卫
不登陆不给看
const router = createRouter({ ... })
router.beforeEach((to, from) => {
// ...
// 返回 false 以取消导航
return false
})可以返回的值如下:
false: 取消当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到from路由对应的地址。一个路由地址: 通过一个路由地址重定向到一个不同的地址,如同调用
router.push(),且可以传入诸如replace: true或name: 'home'之类的选项。它会中断当前的导航,同时用相同的from创建一个新导航。
router.beforeEach(async (to, from) => {
if (!isAuthenticated && to.name !== 'Login') return { name: 'Login' }
return false;
})路由元信息
定义
const routes = [
{
path: '/posts',
component: PostsLayout,
children: [
{
path: 'new',
component: PostsNew,
// 只有经过身份验证的用户才能创建帖子
meta: { requiresAuth: true },
},
{
path: ':id',
component: PostsDetail
// 任何人都可以阅读文章
meta: { requiresAuth: false },
}
]
}
]使用
router.beforeEach((to, from) => {
if (to.meta.requiresAuth && !auth.isLoggedIn()) {
// 此路由需要授权,请检查是否已登录
// 如果没有,则重定向到登录页面
return {
path: '/login',
// 保存我们所在的位置,以便以后再来
query: { redirect: to.fullPath },
}
}
})ts声明类型(.d.ts)
// 这段可以直接添加到你的任何 `.ts` 文件中,例如 `router.ts`
// 也可以添加到一个 `.d.ts` 文件中。确保这个文件包含在
// 项目的 `tsconfig.json` 中的 "file" 字段内。
import 'vue-router'
// 为了确保这个文件被当作一个模块,添加至少一个 `export` 声明
export {}
declare module 'vue-router' {
interface RouteMeta {
// 是可选的
isAdmin?: boolean
// 每个路由都必须声明
requiresAuth: boolean
}
}Pinia 状态存储
又想全局存储登录用户的信息,又不想写规范点而不是单纯的
export defult {},这个时候就需要状态存储
安装
npm install pinia
pnpm i pinia
# Vue 版本低于 2.7
npm i @vue/composition-api创建实例(Vue3)
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
app.mount('#app')定义store
文件一般保存在src/store/目录下(单一状态存储用index.ts命名即可)
import { defineStore } from 'pinia';
// 选项式 更容易使用
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0
}),
getters: {
func_a: (state) => state.count * 2,
func_b(state) {},
},
actions: {
increment(/* 这里当然可以加参数 */) {
this.count++
},
},
})
// 组合式 更灵活和强大
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
// 这里假定 `app.provide('appProvided', 'value')` 已经调用过
const appProvided = inject('appProvided')
return { count, doubleCount, increment, appProvided }
})组合式api注意事项:
要让 pinia 正确识别
state,你必须在 setup store 中返回state的所有属性。这意味着,你不能在 store 中使用**私有**属性。不完整返回会影响 SSRhttps://pinia.vuejs.org/zh/cookbook/composables.html ,开发工具和其他插件的正常运行。——pinia官网
使用store
<script setup>
import { storeToRefs } from 'pinia'
import { useCounterStore } from '@/stores/counter'
const store = useCounterStore()
const { name, doubleCount } = storeToRefs(store)
const { increment } = store
</script>
<template>
<!-- 直接从 store 中访问 state -->
<div>Current Count: {{ store.count }}</div>
</template>你可以定义任意多的 store,但为了让使用 pinia 的益处最大化 (比如允许构建工具自动进行代码分割以及 TypeScript 推断),你应该在不同的文件中去定义 store。
一旦 store 被实例化,你可以直接访问在 store 的
state、getters和actions中定义的任何属性。我们将在后续章节继续了解这些细节,目前自动补全将帮助你使用相关属性。请注意,
store是一个用reactive包装的对象,这意味着不需要在 getters 后面写.value。就像setup中的props一样,我们不能对它进行解构为了从 store 中提取属性时保持其响应性,你需要使用
storeToRefs()。它将为每一个响应式属性创建引用。当你只使用 store 的状态而不调用任何 action 时,它会非常有用。请注意,你可以直接从 store 中解构 action,因为它们也被绑定到 store 上
state操作
重置
store.$reset()替换
store.$patch({ count: 24 })
pinia插件
核心是pinia.use(xxx)
示例:
import { createPinia } from 'pinia'
// 创建的每个 store 中都会添加一个名为 `secret` 的属性。
// 在安装此插件后,插件可以保存在不同的文件中
function SecretPiniaPlugin() {
return { secret: 'the cake is a lie' }
}
const pinia = createPinia()
// 将该插件交给 Pinia
pinia.use(SecretPiniaPlugin)
// 在另一个文件中
const store = useStore()
store.secret // 'the cake is a lie'Pinia 插件是一个函数,可以选择性地返回要添加到 store 的属性。它接收一个可选参数,即 context。
export function myPiniaPlugin(context) {
context.pinia // 用 `createPinia()` 创建的 pinia。
context.app // 用 `createApp()` 创建的当前应用(仅 Vue 3)。
context.store // 该插件想扩展的 store
context.options // 定义传给 `defineStore()` 的 store 的可选对象。
// ...
}然后用 pinia.use() 将这个函数传给 pinia:
pinia.use(myPiniaPlugin)插件只会应用于在 pinia 传递给应用后创建的 store,否则它们不会生效。
vue-i18n 国际化
安装
npm i vue-i18n作为vue插件
import { createApp } from 'vue'
import { createI18n } from 'vue-i18n'
const app = createApp({
// something vue options here ...
})
const i18n = createI18n({
// something vue-i18n options here ...
})
app.use(i18n)
app.mount('#app')例子
App.vue
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>
<template>
<h1>{{ $t("message.hello") }}</h1>
</template>main.ts
const i18n = createI18n({
legacy: false, // you must set `false`, to use Composition API
locale: 'ja',
fallbackLocale: 'en',
messages: {
en: {
message: {
hello: 'hello world'
}
},
ja: {
message: {
hello: 'こんにちは、世界'
}
}
}
})组合包
// 1、创建中文语言包对象
const zh = {
username: '用户名',
email: '邮箱',
mobile: '手机'
}
// 2、创建英文语言包对象
const en = {
username: 'Username',
email: 'Email',
mobile: 'Mobile'
}
// 3、组合语言包对象
const messages = {
zh,
en
}
// 4、创建 VueI18n 实例,并为 messages 和 locale 属性赋值
const i18n = new VueI18n({
messages,
locale: 'en'
})变量
定义
const messages = {
en: {
message: {
hello: '{msg} world'
}
}
}使用
<p>{{ $t('message.hello', { msg: 'hello' }) }}</p>另一种方式:
const messages = {
en: {
message: {
hello: '{0} world'
}
}
}
// <p>{{ $t('message.hello', ['hello']) }}</p>结合v-html
<p v-html="$t('message.hello')"></p>