跳到主要内容

· 阅读需 3 分钟
JaguarJack

为什么使用 mock

在日常开发中,后端接口和前端开发的进度一般会不一致,有时候前端因为一个接口没有对接完成,就会卡住,无法进行下去,所以这个时候需要进行数据 mock,使得业务能正常开发下去,当然首要的前提是,需要前后端对接口的数据定义要统一。

安装

yarn add mockjs

yarn add @types/mockjs -D

yarn add vite-plugin-mock -D

使用

找到 vite.config.js

import { viteMockServe } from 'vite-plugin-mock'


// 然后在 plugins 中添加 viteMockServe
return {
plugins: [
viteMockServe({
// mock 数据的文件夹
mockPath: './src/mock',
// 根据实际情况,是否需要开启 mock
localEnabled: command === 'serve',
watchFiles: true // 监视文件夹中的文件更改。 并实时同步到请求结果
}),
}

创建 mock 数据

mkdir ./src/mock

touch login.ts

添加一个 loginmock 数据

import { MockMethod } from 'vite-plugin-mock'

export default [
{
url: '/api/login',
method: 'post',
response: ({ query }) => {
return {
code: 10000,
data: {
token: 'adminislogined'
}
}
}
},

{
url: '/api/logout',
method: 'post',
response: ({ query }) => {
return {
code: 10000,
data: {
}
}
}
}
] as MockMethod[]

注意,这里的 mock 实际是会通过浏览器发送真实请求的,所以在业务开发中,后端可以先定义好接口返回的数据格式,前端按照接口数据格式模拟数据。一旦后端开发完成之后,通过关闭 mock-serve,可以迅速完成业务接口交接。 目前 catchadmin vue3 的后台,正是使用这样的方式开发,所以可以通过查看 mock 的数据接口,就可以了解接口的数据定义了

· 阅读需 4 分钟
JaguarJack

Piniavue3 新推的状态管理,当然你也可以使用 vuex, 但是不是很建议,因为这个 plugin 就相当于 vuex5 了。

为什么使用它

引用官方文档的内容 PiniaVue 的存储库,它允许您跨组件/页面共享状态。 如果您熟悉 Composition API,您可能会认为您已经可以通过一个简单的 export const state = reactive({}). 这对于单页应用程序来说是正确的,但如果它是服务器端呈现的,会使您的应用程序暴露于安全漏洞。 但即使在小型单页应用程序中,您也可以从使用 Pinia 中获得很多好处:

  • dev-tools 支持
    • 跟踪动作、突变的时间线
    • Store 出现在使用它们的组件中
    • time travel 和 更容易的调试
  • 热模块更换
    • 在不重新加载页面的情况下修改您的 Store
    • 在开发时保持任何现有状态
  • 插件:使用插件扩展 Pinia 功能
  • JS 用户提供适当的 TypeScript 支持或 autocompletion
  • 服务器端渲染支持

安装

yarn add pinia
# 或者使用 npm
npm install pinia

使用

找到 utils/catchadmin.ts, 全局引入

import { createPinia } from 'pinia'

protected usePinia () : CatchAdmin {
this.app.use(createPinia())

return this
}

创建 store 文件夹

mkdir src/store

// then

touch index.ts

// 保留主入口

创建模块

cd src/store && mkdir modules

创建 app Store

cd modules && mkdir app

// then

touch index.ts

内容如下

import { defineStore } from 'pinia'

const initSize = 'small'

const initLocale = 'zh'

/**
* app
*/
type app = {
size: 'small' | 'medium' | 'large',

isExpand: boolean,

locale: 'zh' | 'en',

isMobile: boolean
}

export const useAppStore = defineStore('app', {
state: () : app => ({
size: initSize,
isExpand: true,
locale: initLocale,
isMobile: false
}),

actions: {
changeSize (size: 'small' | 'medium' | 'large') {
this.size = size
},

changeLocale (locale: 'zh' | 'en') {
this.locale = locale
},

changeExpaned () {
this.isExpand = !this.isExpand
}
}
})

这里还是用的 optional api,本人体验了下 composition api 写法,似乎很麻烦,然后参考了下相关的项目的写法,都是使用的 optional api 写法。

为什么要使用

在项目中有一些状态需要在组件之间流转,例如,目前在写这个 blog 文章的时候,项目遇到的菜单「展开关闭」这个状态值,这个值需要在 header 组件,Slide 组件及其子组件之间不停的流转,就很麻烦,不仅需要 props 还需要 emit 这样的操作无疑增加了代码的复杂度以及维护的难度,使用状态管理之后,因为状态管理是响应式的,所以可以通过一个接口,就可以对状态进行操作,很方便。

找到 layout/componetns/header/index.vue

import { useAppStore } from '@/stores/modules/app'

const store = useAppStore()

const { changeExpaned } = store

就可以直接在组件中使用了 changeExpaned 方法,对应的状态也可以改变

· 阅读需 1 分钟
JaguarJack

更新依赖版本

查看依赖版本

npm outdated

// 可以看到项目依赖的版本情况
Package Current Wanted Latest Location Depended by
@element-plus/icons-vue 1.1.4 1.1.4 2.0.6 node_modules/@element-plus/icons-vue catchadmin-pro
@types/node 17.0.45 17.0.45 18.0.4 node_modules/@types/node catchadmin-pro
@vitejs/plugin-vue 2.3.3 2.3.3 3.0.0 node_modules/@vitejs/plugin-vue catchadmin-pro
@vitejs/plugin-vue-jsx 1.3.10 1.3.10 2.0.0 node_modules/@vitejs/plugin-vue-jsx catchadmin-pro
unplugin-auto-import 0.7.2 0.7.2 0.9.3 node_modules/unplugin-auto-import catchadmin-pro
unplugin-vue-components 0.19.9 0.19.9 0.21.1 node_modules/unplugin-vue-components catchadmin-pro
vite 2.9.14 2.9.14 3.0.0 node_modules/vite catchadmin-pro
vue-tsc 0.34.17 0.34.17 0.38.5 node_modules/vue-tsc catchadmin-pro

更新依赖

yarn upgrade

通过该命令可以升级依赖,然后通过上面的命令继续查看下,如果发现devDependencies没有更新的话,可以根据latest手动修改版本之后,再执行命令

yarn

就可以完成项目的依赖升级了

· 阅读需 2 分钟
JaguarJack

原因

为什么要使用第三方的图标?因为 ElementPlusicon 实在是太少了,不够用。hreIcons 感觉还可以,并且可以很好的和 tailwindcss 集合,图标数量也有 230+ ,感觉能满足后台需求。所以整个项目为了 icon 统一,就去除了 ElementPlus Icon 了,统一使用 heroIcons

安装

yarn add @heroicons/vue  

使用

为了统一使用,并且为了之后的动态 icon 做铺垫,所以这里需要二次封装下。创建 src/icon/index.vue 组件。

<template>
<component :is="icon" class="ct-w-5 ct-h-5"/>
</template>

<script>
import { defineComponent } from 'vue'
import * as heroIcons from '@heroicons/vue/outline'
export default defineComponent({
name: 'icon',
props: {
name: {
type: String,
required: true
}
},
setup (props, ctx) {
let name = ''

props.name.split('-').forEach(v => {
name += v[0].toUpperCase() + v.substr(1)
})

const icon = heroIcons[name + 'Icon']

return {
icon
}
}
})
</script>

创建完成之后,为了可以全局使用,需要注册在 vue 中注册下,还是找到后台的入口 utils/catchadmin.ts

import icon from '@/components/icon/index.vue'


// 找到 registerComponents 方法,注册
protected registerComponent () : CatchAdmin {
this.app.component('icon', icon)

return this
}

注册完成之后,就可以全局使用了,例如这样

<Icon name="logout"/>

当然这个使用是有一个小小弊端,修改之后无法立即刷新图标,但是这个应该不是什么大问题,因为图标是静态的。 当然如果你不喜欢这样,也可以直接在页面中引入 heroIcons

<template>
<div>
<BeakerIcon class="h-5 w-5 text-blue-500"/>
<p>...</p>
</div>
</template>

<script>
import { BeakerIcon } from '@heroicons/vue/solid'

export default {
components: { BeakerIcon }
}
</script>

· 阅读需 3 分钟
JaguarJack

介绍

本篇文章主要介绍在catchadmin V3 中如何实现国际化多语言这个功能。由于后台是基于ElementPlus进行开发,所以国际化也分为两个部分。

  • vue-i18n国际化,用于项目中自定义
  • ElementPlus国际化,用于 ElementPlus UI 组件语言切换

安装 i18n

首先需要安装 i18n 组件。

yarn add vue-i18n@9
提示

vue3 需要安装 9.0+ 版本

ElementPlus 多语言

找到 src/utils/CatchAdmin.ts, 引入多语言

import zh from 'element-plus/es/locale/lang/zh-cn'

在使用 ElementPlus 的地方加入下面的代码

this.app.use(ElementPlus, {
// 本地语言切换
locale: LocalStorage.get('language') === 'zh' && zh
})

i18n 多语言

src 目录下建立 i18n 文件夹,创建 index.ts 之后引入 i18n

import LocalStorage from '@/utils/LocalStorage'
import { createI18n } from 'vue-i18n'
import en from './languages/en'
import zh from './languages/zh'

const messages = {
en,
zh
}

const i18n = createI18n({
locale: LocalStorage.get('language') || 'zh',
messages,
// 全局可以使用 $t 函数
globalInjection: true
})

export default i18n

然后在 i18n 文件夹下建立 languages 文件夹,分别是

  • en.ts
  • zh.ts 以 zh 为例,内容如下
const zh = {
system: {
login: '登录',
register: '注册',
chinese: '中文',
english: '英文'
}
}

export default zh

在项目使用 i18n

还是找到 src/utils/CatchAdmin.ts, 引入 i18n

import i18n from '@/i18n'

this.app.use(i18n) // 即可

多语言切换组件

找到 layout/components/header/lang.vue 组件,内容如下

<template>
<div class="ct-flex hover:ct-cursor-pointer ct-pl-1 ct-pr-1">
<el-dropdown size="large" class="ct-flex ct-items-center ct-justify-center hover:ct-cursor-pointer ct-w-full" @command="selectLanguage">
<TranslateIcon class="ct-h-5 ct-w-5"/>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="lang in langs"
:key="lang.value"
:command="lang.value"
:disabled="lang.value == defaultLang">
{{ $t('system.' + lang.label) }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>

<script lang="ts" setup>
import LocalStorage from '@/utils/LocalStorage'
import { computed } from '@vue/reactivity'
import { reactive } from 'vue'

const langs = reactive([
{ label: 'chinese', value: 'zh' },
{ label: 'english', value: 'en' }
])

const defaultLang = computed(() => {
return LocalStorage.get('language') || 'zh'
})

const selectLanguage = (value: string | number | object) => { LocalStorage.set('language', value);
location.reload()
}
</script>

在项目的任何位置引入该组件即可实现中英文切换,当然如果你需要其他语言的,可以根据自行在 i18n 文件夹下添加