学习目标:
-
掌握 luch-request 网络请求的用法
-
能够对 Pinia 进行初始化操作
-
掌握创建 Store 及数据操作的步骤
-
能够对 Pinia 数据进行持久化的处理
-
掌握用户登录的实现方法
一、项目启动
从零起步创建项目,完整的静态页面可以从 gitee 仓库获取。
1.1 创建项目
以 HBuilder X 的方式创建项目:
-
项目名称:优医咨询
-
Vue 版本:Vue3
-
模板:默认模板
1.1.1 .prettierrc
在项目根目录下创建 .prettierrc 文件,然后添加下述配置选项:
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": false,
"singleQuote": true,
"vueIndentScriptAndStyle": true,
}
上述配置内容是关于 Prettier 的常用的配置项,以后实际开发过程中可以根据需要逐步完善。
1.1.2 配置 tabBar
根据设计稿的要求配置 tabBar,首先通过 HBuilder X 新建 3 个页面,然后再配置 pages.json 文件。
共有4个页面,分别为:首页、健康百科、消息通知、我的,在课堂上统一约束目录的名称:首页对应 index、健康百科对应 wiki、消息通知对应 notify、我的对应 my 。
tabBar 用的图片在课程资料中可以找到,将其拷贝到项目的根目录下,然后在 pages.json 中进行配置:
{
"pages": [{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "优医咨询"
}
}, {
"path": "pages/my/index",
"style": {
"navigationBarTitleText": "我的",
"enablePullDownRefresh": false
}
}, {
"path": "pages/notify/index",
"style": {
"navigationBarTitleText": "消息通知",
"enablePullDownRefresh": false
}
}, {
"path": "pages/wiki/index",
"style": {
"navigationBarTitleText": "健康百科",
"enablePullDownRefresh": false
}
}],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "优医咨询",
"navigationBarBackgroundColor": "#fff",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"color": "#6F6F6F",
"selectedColor": "#6F6F6F",
"borderStyle": "white",
"list": [{
"text": "首页",
"pagePath": "pages/index/index",
"iconPath": "static/tabbar/home-default.png",
"selectedIconPath": "static/tabbar/home-active.png"
},
{
"text": "健康百科",
"pagePath": "pages/wiki/index",
"iconPath": "static/tabbar/wiki-default.png",
"selectedIconPath": "static/tabbar/wiki-active.png"
},
{
"text": "消息通知",
"pagePath": "pages/notify/index",
"iconPath": "static/tabbar/notify-default.png",
"selectedIconPath": "static/tabbar/notify-active.png"
},
{
"text": "我的",
"pagePath": "pages/my/index",
"iconPath": "static/tabbar/my-default.png",
"selectedIconPath": "static/tabbar/my-active.png"
}
]
},
"uniIdRouter": {}
}
除了配置 tabBar 外,还要配置每个页面的导航栏的标题 navigationBarTitleText 及全局导航栏背景颜色 navigationBarBackgroundColor 为白色。
1.1.3 公共样式
在 App.vue 中配置公共 css 代码,不仅能精简代码,将来样式的维护也会更方便,这些公共样式是由开发者根据不同的项目需要自定义的,因此不同的项目或者不同开发者定义的公共样式是不一致的,本项目中我定义了以下部分的公共样式:
<!-- App.vue -->
<script>
// 省略这里的代码...
</script>
<style lang="scss">
image {
vertical-align: middle;
}
button:after {
display: none;
}
.uni-button {
height: 88rpx;
text-align: center;
line-height: 88rpx;
border-radius: 88rpx;
color: #fff;
font-size: 32rpx;
background-color: #20c6b2;
&[disabled],
&.disabled {
color: #fff !important;
background-color: #ace8e0 !important;
}
}
</style>
关于 scss 本项目定义了一个变量和一个混入,这个混入是用来处理文字溢出的,溢出的部分会显示 ... 来代替。
// uni.scss
// 省略了默认生成的 scss 代码...
$line: 2;
@mixin text-overflow($line) {
display: -webkit-box;
-webkit-line-clamp: $line;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
overflow: hidden;
}
1.1.4 引入字体图标
项目中即用到了单色图标,也用到了多色图标:
-
单色图标,将字体图标文件解压缩到 static/fonts 目录中,将 iconfont.css 重命名为 iconfont.scss
@font-face {
font-family: 'iconfont';
src: url('/static/fonts/iconfont.ttf') format('truetype');
}
.iconfont {
font-family: 'iconfont' !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-done:before {
content: '\ea54';
}
.icon-location:before {
content: '\e6ea';
}
.icon-edit:before {
content: '\e6e9';
}
.icon-shield:before {
content: '\e6e8';
}
.icon-checked:before {
content: '\e6e5';
}
.icon-box:before {
content: '\e6e6';
}
.icon-truck:before {
content: '\e6e7';
}
图标成功导入项目后,在 App.vue 中导入自定义图标的样式文件
<!-- App.vue -->
<script>
// 省略这里的代码...
</script>
<style lang="scss">
// 单色图标
@import '@/static/fonts/iconfont.scss'
// 以下部分代码省略...
</style>
字体图标导入成功后要到页面测试一下图标是否能正常显示。
-
关于多色图标的使用在前面课程中已经介绍过了,关于图标的转换部分就不再演示了,我们直接将转换后代码引入项目中
先将生成的多色图标文件 color-fonts.scss 放到项目的根目录中,然后在 App.vue 中导入该文件
<!-- App.vue -->
<script>
// 省略这里的代码...
</script>
<style lang="scss">
// 单色图标
@import '@/static/fonts/iconfont.scss';
// 多色图标
@import './color-fonts.scss';
// 以下部分代码省略...
</style>
字体图标导入成功后要到页面测试一下图标是否能正常显示。
1.1.5 网站图标
浏览器在加载网页时会在标签页位置展示一个小图标,我们来指定一下这个图标:
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<!-- 这里省略了部分代码... -->
<!-- 这行代码用来指定网站图标 -->
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/main.js"></script>
</body>
</html>
1.2 公共封装
封装一系列的公共的方法,如网络请求、轻提示、日期时间处理等。
1.2.1 网络请求
小程序或 uni-app 提供了专门用于网络请求的 API ,但结合实际开发还需要扩展一些与业务相关的逻辑,如基地址、拦截器等功能,通常会对 uni.request 进行封装,luch-request 就是这样一个工具模块,它仿照 axios 的用法对 uni.request 进行二次封装,扩展了基地址、拦截器等业务相关的功能。
-
安装
luch-request
npm install luch-request
-
实例化并配置基地址,项目根目录新建 utils/http.js
// utils/http.js
// 导入模块
import Request from 'luch-request'
// 实例化网络请求
const http = new Request({
// 接口基地址
baseURL: 'https://t1ps66c7na.hk.aircode.run',
})
// 导出配置好的模网络模块
export { http }
<!-- pages/test/index.vue -->
<script setup>
import { http } from '@/utils/http.js'
function onButtonClick() {
// 1. 普通用法
http.request({
url: '/echo',
method: 'GET',
header: {
customHeader: '22222222'
}
})
}
</script>
<template>
<view class="content">
<button @click="onButtonClick" type="primary">luch-request 测试</button>
</view>
</template>
-
配置请求拦截器
在请求之前执行一些逻辑,例如检测登录状态,添加自定义头信息等。
// utils/http.js
// 导入模块
import Request from 'luch-request'
// 实例化网络请求
const http = new Request({
// 接口基地址
baseURL: 'https://t1ps66c7na.hk.aircode.run',
})
// 请求拦截器
http.interceptors.request.use(
function (config) {
// 定义头信息,并保证接口调用传递的头信息
// 能够覆盖在拦截器定义的头信息
config.header = {
Authorization: '11111111',
...config.header,
}
return config
},
function (error) {
return Promise.reject(error)
}
)
// 导出配置好的模网络模块
export { http }
以上代码中要注意拦截器中配置的头信息不要将原有的头信息覆盖。
-
配置响应拦截器
// utils/http.js
// 导入模块
import Request from 'luch-request'
// 实例化网络请求
const http = new Request({
// 接口基地址
baseURL: 'https://t1ps66c7na.hk.aircode.run',
})
// 请求拦截器
http.interceptors.request.use(
function (config) {
// 定义头信息,并保证接口调用传递的头信息
// 能够覆盖在拦截器定义的头信息
config.header = {
Authorization: '11111111',
...config.header,
}
return config
},
function (error) {
return Promise.reject(error)
}
)
// 响应拦截器
http.interceptors.response.use(
function ({ statusCode, data, config }) {
// 解构出响应主体
return data
},
function (error) {
return Promise.reject(error)
}
)
// 导出配置好的模网络模块
export { http }
<!-- pages/test/index.vue -->
<script setup>
import { http } from '@/utils/http.js'
async function onButtonClick() {
// 1. 普通用法
const result = await http.request({
url: '/echo',
method: 'GET',
header: {
customHeader: '22222222'
}
})
console.log(result)
}
</script>
<template>
<view class="content">
<button @click="onButtonClick" type="primary">luch-request 测试</button>
</view>
</template>
-
请求加载状态
在发请求之前展示一个加载提示框,请求结束后隐藏这个提示框,该部分的逻辑分别对应请求拦截器和响应拦截器,在请求拦截器中调用 uni.showLoading 在响应拦截器中调用 uni.hideLoading。
在设置加载提示框之前先来了解一下 luch-request 提供的自定义配置参数的功能,即 custom 属性,该属性的用法如下:
// utils/http.js
// 导入模块
import Request from 'luch-request'
// 实例化网络请求
const http = new Request({
// 接口基地址
baseURL: 'https://t1ps66c7na.hk.aircode.run',
custom: {
abc: 123,
loading: true
}
})
// 省略以下部分代码...
局部配置了相同的自定义参数时会覆盖全局配置的自定义参数
<!-- pages/test/index -->
<script setup>
import { http } from '@/utils/http.js'
async function onButtonClick() {
// 1. 普通用法
const result = await http.request({
// 省略部分代码...
// 局部配置自定义参数
custom: {
abc: 123,
},
// 省略部分代码...
})
console.log(result)
}
</script>
在了解自定义参数的使用后,我们来自定义一个能控制是否需要 loading 提示框的属性,全局默认为 true 。
// utils/http.js
// 导入模块
import Request from 'luch-request'
// 实例化网络请求
const http = new Request({
// 接口基地址
baseURL: 'https://t1ps66c7na.hk.aircode.run',
custom: {
loading: true
}
})
// 请求拦截器
http.interceptors.request.use(
function (config) {
// 显示加载状态提示
if (config.custom.loading) {
uni.showLoading({ title: '正在加载...', mask: true })
}
// 定义头信息,并保证接口调用传递的头信息
// 能够覆盖在拦截器定义的头信息
config.header = {
Authorization: '11111111',
...config.header,
}
return config
},
function (error) {
return Promise.reject(error)
}
)
// 响应拦截器
http.interceptors.response.use(
function ({ statusCode, data, config }) {
// 隐藏加载状态提示
uni.hideLoading()
// 解构出响应主体
return data
},
function (error) {
return Promise.reject(error)
}
)
// 导出配置好的模网络模块
export { http }
到此关于网络请求的基本用法就封装完毕了,后续会补充登录权限检测的业务逻辑。
1.2.2 轻提示
uni-app 提供了 uni.showToast API 用于轻提示,但其传的参数比较复杂,通过封装来简化参数的传递。
新建 utils/utils.js
/** * 项目中会用的一系列的工具方法 */ u










