VUE项目搭建2

VUE项目搭建2

组件自动注册

使用第三方组件,如果不使用全局注册每次使用需要单独引入组件,这样比较麻烦,可以使用组件自动注册的方式(非全局注册),也就是不需要再script setup中导入就可以直接使用

  1. 安装 pnpm add unplugin-vue-components -D

  2. vite.config.ts中进行配置

    image-20240728123738221

dts:false 表示不自动生成组件类型文件,导入包就能识别

importStyle:false 表示不自动导入样式,因为已经在main.ts中导入

添加全局组件类型

注意:使用上面这种方式,工程目录下components目录下的组件也会自动注册,但是需要添加全局组件类型

在types目录下新建components.d.ts文件

1
2
3
4
5
6
7
8
9
10
//自己定义的组件
import type CpIcon from '@/components/CpIcon.vue'
import type CpNavBar from '@/components/CpNavBar.vue'
//固定写法
declare module 'vue' {
interface GlobalComponents {
CpNavBar: typeof CpNavBar
CpIcon: typeof CpIcon
}
}

image-20240728124626024

router信息

Vue Router的信息会保存在history.state

image-20240728124242303

1
2
3
4
5
6
7
const onClickLeft = () => {
if (history.state?.back) {
router.back()
} else {
router.push('/')
}
}

打包SVG地图

图片格式为svg的,SVG地图是xml格式,可通过ID来使用,一次加载动态使用,图片也无需import

image-20240728125025507

  1. 安装 pnpm install vite-plugin-svg-icons -D
  2. 配置vite.config.ts
  3. image-20240728125215864
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'node:path'

export default defineConfig({
plugins: [
vue(),
createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/icons')]
})
],
base: '/',
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
  1. 导入mian.ts

import 'virtual:svg-icons-register'

  1. 使用

image-20240728125438487

image-20240728125447269

其中#icon为固定写法,后面写文件夹和名称,其中图片要放在src下的icons目录

访问权限控制

image-20240728131122633

1
2
3
4
5
6
router.beforeEach((to) => {
const store = useUserStore()
const whiteList = ['/login', 'login/callback']
//没有用户信息也没有在白名单则最直接跳转到login
if (!store.user?.token && !whiteList.includes(to.path)) return '/login'
})

修改页面标题

可以在配置元信息meta中定义标题

路由全局后置守卫设置标题给页面,扩展原信息类型,因为需要等页面全部加载完成再去改标题比较合适

1
2
3
4
5
{
path: '/home',
component: () => import('@/views/Home/index.vue'),
meta: { title: '主页面' }
}
1
2
3
router.afterEach((to) => {
document.title = `${to.meta.title || '默认标题'}`
})

加载进度条

  1. 安装pnpm i nprogress 和 pnpm i @types/nprogress -D
  2. 设置router.ts中设置
1
2
3
4
5
6
import nProgress from 'nprogress'
import 'nprogress/nprogress.css'

nProgress.configure({
showSpinner: false //不显示小圆圈
})
  1. 在路由前置守卫增加NProgress.start(),在后置守卫增加NProgress.done()

VueUse

VuewUse是一个组合式API的工具库,支持网页常用的功能,如窗口宽度、滚动距离、进入可视区、倒计时等

  1. 安装:pnpm i @vueuse/core

  2. 使用

1
2
3
4
5
6
7
8
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()

<van-swipe
:width="(150 / 375) * width" //直接来适配比例
:showIndicators="false"
:loop="false"
>

如果不用VueUse,自己实现可以这样

image-20240728172825372

composables组合函数

在vue概念中,组合函数是一个利用vue的组合式API来封装和复用有状态的逻辑函数,一般使用use开头来命名,表示使用某功能,例如下面这个就是一个组合函数,里面既有loading数据,又含有函数

image-20240728173255022

上传图片

1
2
3
4
5
6
export const uploadImage = (file: File) => {
const fd = new FormData()
fd.append('file', file)
//需要FormData数据 ,作为输入
return request<Image>('upload', 'POST', fd)
}

支付流程

image-20240729193607685

路由器独享守卫

image-20240729195215803

WebSocket

http/https只能是客户端向服务端发送请求,而服务端不能主动向客户端发送请求,所以引入WebSocket实现双向通信

image-20240730140241482

websocekt的直接使用

image-20240730140340399

在实际开发项目中,一般使用socket.io-client来实现客户端功能,他是基于webSocket的js库

需要提前安装pnpm i socket.io-client,socket.io的常规使用

image-20240730140518421

发送信息使用emit方法,关闭连接使用close方法,事件监听用on方法,监听的事件名称需要和后端来协定

nextTick

在更新数据后,vue是异步更新,Dom可能还没有更新完成,所以使用nextTick来确保数据更新完成,然后再调用与Dom相关的操作

1
2
3
4
5
6
//可以直接使用await 来操作,因为nextTick返回的是promise
await nextTick()
window.scrollto(....)

//可以直接在nextTick()中设置函数
nextTick(()=>{window.scrollto(...)})

第三方登录

常见的第三方登录流程

image-20240731091004924

需要准备的东西:

  1. QQ互联实名认证,必须要拥有合法域名
  2. 创建web引用,配置回调地址
  3. 得到appid和回调地址

使用openId登录

第三方登录成功后,会有一个openid,这时需要根据官方文档获取相应的api,实现登录

image-20240731091433731

因为QC是外部引用的,所以需要进行类型定义,在global.d.ts中声明

image-20240731091521382

配置好后,ESlint还是会提示错误,这时需要再上面使用/*global QC*/来告诉ESLint,QC是一个全局声明变量

开发环境和生产环境

pnpm dev开发环境

pnpm build生产环境

因为生产环境和开发环境有一些地址或者变量会有不同,所以要区别对待

建立开发和生产环境变量

分别在项目目录下建立.env.development和.env.production文件,里面的变量要大写VITE_开头

image-20240731092052615

声明变量

我们在之前使用过import.meta.env.BASE_URL但是在上一步声明的变量目前还没有定义,所以需要进行扩展,可以发现import.meta.env.BASE_URL等都是定义在ImportMetaEnv接口中,所以在该接口中进行扩展(接口重复定义实现扩展),这时就可以正常使用

image-20240731092509551

html模板页面区别环境

上边的变量都是在组件中使用,如果在html中想要区分怎么办,可以使用vite-plugin-html插件

安装:pnpm i vite-plugin-html

在vite.config.ts中进行配置

image-20240731092839309

在html中使用变量

image-20240731092915818

真机调试

手机端是没有开发者环境的,可以使用eruda来实现,不过需要仅仅在开发环境中使用,在index.html中引入

image-20240731093048790

mock数据

开发过程中如果后端没有提供好接口,可以mock数据

安装pnpm i vite-plugin-mock mockjs -Dnpm i --save-dev @types/mockjs

需要在vite-env.d.ts文件中,添加declare module 'mockjs'

在vite.config.ts中增加配置

1
2
3
4
5
6
7
8
9
import { viteMockServe } from 'vite-plugin-mock'
plugins: [
viteMockServe({
// 在哪个文件夹下编写模拟接口的代码
mockPath: './src/mock',
// 在开发环境开启mock
enabled: true
}),
]

新建mock/index.ts

1
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
32
33
34
import Mock from 'mockjs'

export default [
// 模块接口
{
url: '/patient/message/sys/list',
method: 'GET',
timeout: '500',
response: () => {
const data = []

for (let i = 0; i < 10; i++) {
data.push(
Mock.mock({
id: '@id',
title: '@ctitle(5,10)',
content: '@ctitle(10,20)',
avatar: '@image("100x100")',
createTime: '@datetime()',
status: '@integer(0,1)',
type: '@integer(1,3)'
})
)
}

// 返回模拟的数据
return {
code: 10000,
message: '模拟数据成功',
data
}
}
}
]

调用mock

1
2
3
4
5
request(import.meta.env.VITE_APP_CALLBACK + '/patient/message/sys/list').then(
(res) => {
console.log(res)
}
)

单元测试

安装pnpm i vitest -D

在package.json中设置

image-20240731111651810

创建test目录,创建测试名称需为test.ts结尾

image-20240731111701980

作者

步步为营

发布于

2024-07-28

更新于

2025-03-15

许可协议