本文包含:
json-server 的安装 配置 验证
json-server-auth 的安装 配置 验证
注册和登录页面
涉及知识点:axios,router,http请求,跨域,vue3,ts 等等
欢迎小伙伴,加入微信群,在文末,如果二维码过期,可以在公众号里获取。
json-server
安装配置 json-server
安装
pnpm add json-server -D
配置
// 直接看下面验证的时候如何使用,以及使用的时候遇到的问题
验证
一、基本使用大家参考 json-server Github
简单来说分了三步
- 创建一个 json 文件当作你要访问的数据库,在你安装好
json-server
的时候会默认生成一个db.json, - 启动 json-server 服务器,直接运行
json-server --watch db.json
,终端会提示现在这个数据库存在的资源 - 在浏览器地址输入启动终端中提示你拥有的资源地址,如:
http://localhost:3000/posts/1
,就可以访问到一组json数据。这里的数据是真实的数据,可以在开发者工具的 network 中访问到,不像 mock 的数据会被劫持,在浏览器开发者工具中看不到请求的数据。
二、项目中的简单使用
- 准备一个项目放在项目中的 json 文件,作为我们项目的数据库 database,这里我创建在
./src/service/json-server/data.json
,下面是我加的测试数据,名字是testdata
。
{
"testdata": {
"status": 200,
"message": "请求成功!",
"data": [
{
"id": 1,
"title": "json-server",
"author": "typicode"
},
{
"id": 2,
"title": "json-server",
"author": "typicode"
}
]
}
}
- 在 package.json 中配置启动 json-server 的命令,只需更改我们存放数据的 json 文件地址就可以了。
"scripts": {
"jsondb": "json-server --watch ./src/service/json-server/data.json"
}
- 理解项目 API 的访问机制
-
我们启动 json-server,
npm jsondb
,我这里项目一直使用的pnpm
作为包管理器,所以使用pnpm jsondb
来启动, -
Home可以理解为后端服务器的地址,当我们直接在输入http://localhost:3000/users,
-
现在我们ctrl+c停止,json-server 的服务,让后启动我的使用vite搭建的 Vue 项目,发现默认地址,也是 http://localhost:3000,现在我的页面是在访问http://localhost:3000时,重定向到
/home
页面。我们在访问浏览器地址的时候一方面,我要通过路由转跳到当前页面,还需要当前页面能够获取到数据,但是同时启动 vue 项目和 json-server 两个地址就冲突,后启动的地址会被默认更改到http://localhost:3001,但是我们要通过访问http://localhost:3000/users 来获取到用户信息,这个时候就和我们实际工作中项目的开发非常类似了。
我们一般把前端项目部署到nginx,访问前端页面,获取数据又是从另一个服务器来获取,这个时候两个域名不一样,但是我们要拿到我们想要的数据,就需要规定好接口的地址、参数等一些信息,通过本地跨域,或者nginx转发来访问服务器。
启动 json-server 图
浏览器中访问数据库图
启动项目图
- 前端跨域代理的配置,在
vite.config.ts
中- 这里我们更改项目等启动端口到3030
- 现在我们前端项目路径为
http://localhost:3030
,需要代理所有以/api
开头的 API 请求,把它转发到http://localhost:3000
,并且后端的 API 路径中不带/api
前缀,需要自动去掉/api
前缀
server: {
// host: 'localhost',
port: 3030,
proxy: {
//这里是通过请求/api 来转发到 https://api.pingping6.com/
//假如你要请求https://api.*.com/a/b
//那么axios的url,可以配置为 /api/a/b
'^/api': {
target: 'http://localhost:3000/',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
// configure: (proxy, options) => {
// // proxy 是 'http-proxy' 的实例
// }
}
}
},
- 下面我们配置一下 API ,axios 的配置,可以到 Gitee 代码里看一下 /service/index.ts 文件,里面有注释,写的也通俗易懂。
/**
* * 在具体模块中导入具体的 config 类型,配置通用的 config 类型,方便复用
*/
import http from '@/service'
enum Api {
testData = '/api/testdata',
testPost = '/api/postTestList',
testPatch = '/api/patchTestList',
testPut = '/api/putTestList',
testDelete = '/api/deleteTestList'
}
export const testData = (params?: any) => {
return http.get<any>(Api.testData, params)
}
export const testPost = (data: any) => {
return http.post<any>(Api.testPost, data)
}
- 下面写个页面,测试一下,src/modules/components/test/json-server.vue
<template>
<h1>通过测试页面通过json-server,获取数据</h1>
</template>
<script lang="ts">
import { defineComponent, onMounted } from 'vue'
import { testData } from '@/api/test/index'
export default defineComponent({
name: 'json-server',
components: {},
setup() {
const testJsonServer = () => {
testData().then((res) => {
console.log('testData', res.data.data)
})
}
onMounted(() => {
console.log('mounted')
testJsonServer()
})
return {
testJsonServer
}
}
})
</script>
<style lang="less" scoped></style>
- 打开页面可以访问到数据
安装配置 json-server-auth
安装
pnpm add json-server-auth -D
配置
// 直接进入验证
验证
1. 注册
POST /register
POST /signup
POST /users
email
和 password
必填,且在请求体中,除了必填之外,自己也可以根据需要添加其他的数据username,age等等
POST /register
{
"email": "olivier@mail.com",
"password": "bestPassw0rd"
}
返回结果
// 201 Created
{
"accessToken": "xxx.xxx.xxx",
"user": {
"id": 1,
"email": "olivier@mail.com"
}
}
2. 登录
-
POST /login
// 我用login的时候Apifox可以请求到,在项目中就login
就不行,换成signin
就可以请求通,很奇怪 POST /signin
POST /login
{
"email": "olivier@mail.com",
"password": "bestPassw0rd"
}
返回结果
200 OK
{
"accessToken": "xxx.xxx.xxx",
"user": {
"id": 1,
"email": "olivier@mail.com",
"firstname": "Olivier",
"lastname": "Monge"
}
}
3. 使用 postman 或者 Apifox,配置之后,测试一下,register添加两组数据,再使用这两组数据登录,可以之后就在项目中继续
4. 具体代码中实践,顺便巩固一下 Vue3、 TS 和 Ant Design Vue 3.0
下面是简单写的注册和登录页面,切换注册的时候,还有一点问题,后面我再看一下,大家也可以看一下代码,可以一起交流,
目前登录功能是可以测试的,接口也是通的
下面的代码没有样式,样式有很多行,影响阅读,大家可以 clone Gitee 代码下来看。
<template>
<div class="login">
<div class="content">
<a-tabs animated :tabBarGutter="-1" type="card" v-model:activeKey="activeKey">
<a-tab-pane key="login" tab="账号密码登录">
<div class="login-form">
<a-form
ref="formRef"
:model="formState"
:rules="rules"
layout="vertical"
labelAlign="right"
>
<a-form-item label="" name="email">
<a-input
size="large"
v-model:value="formState.email"
placeholder="请输入邮箱"
allowClear
/>
</a-form-item>
<a-form-item label="" name="password">
<a-input
size="large"
v-model:value="formState.password"
type="password"
placeholder="请输入密码"
allowClear
/>
</a-form-item>
</a-form>
<div class="login-button">
<a-button v-if="switchBtn" size="large" type="primary" @click="login">登录</a-button>
<a-button v-else size="large" type="primary" @click="register">注册</a-button>
</div>
<div class="login-footer">
<a-button type="link" @click="handleChange">{{ buttonTitle }}</a-button>
</div>
</div>
</a-tab-pane>
<a-tab-pane key="register" tab="扫码登录">
<div class="login-form">
<div class="login-qrcode">
<div class="qrcode-image"></div>
</div>
<div class="login-footer">
<div class="primary-color">二维码失效时间 5 秒</div>
</div>
</div>
</a-tab-pane>
</a-tabs>
</div>
<!-- <div class="login-button">-->
<!-- <a-button type="primary" @click="register">注册</a-button>-->
<!-- <a-button type="primary" @click="login">登录</a-button>-->
<!-- </div>-->
<!-- <div>-->
<!-- <a>忘记密码?</a>-->
<!-- </div>-->
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, UnwrapRef, ref, toRaw } from 'vue'
import { toLogin, toRegister } from '@/api/login/index'
import { ValidateErrorEntity } from 'ant-design-vue/es/form/interface'
import { message } from 'ant-design-vue'
interface FormState {
email: string
password: string
}
export default defineComponent({
name: 'login',
components: {},
setup() {
// tab 栏默认选择 login
const activeKey = ref('login')
// 登录与注册切换
let switchBtn = ref(true)
let buttonTitle = ref<string>('新用户注册')
const handleChange = () => {
switchBtn = ref(!switchBtn.value)
buttonTitle = ref(switchBtn.value ? '新用户注册' : '已有账号登录')
console.log('change', switchBtn.value)
console.log('text', buttonTitle)
}
// form 表单部分
const formRef = ref()
// UnwrapRef 单层解包, https://juejin.cn/post/6844904126283776014
const formState: UnwrapRef<FormState> = reactive({
email: '',
password: ''
})
const rules = {
email: [{ required: true, message: '请输入正确的邮箱格式', trigger: 'blur' }],
password: [
{ required: true, message: '请输入密码!', trigger: 'blur' },
{
min: 8,
max: 16,
message: '密码长度需8-16位密码!',
trigger: 'blur'
}
]
}
const validFlag = ref(false)
const register = () => {
valid()
if (validFlag) {
toRegister(formState)
.then((res) => {
console.log(res)
validFlag.value = false
})
.catch((err) => {
console.log(err)
validFlag.value = false
})
}
return
}
const login = () => {
console.log('登录')
valid()
if (validFlag) {
toLogin(formState)
.then((res) => {
console.log(res)
validFlag.value = false
})
.catch((err) => {
console.log(err)
validFlag.value = false
// message.warn('请输入用户名或密码!')
})
}
return
}
const valid = () => {
formRef.value
.validate()
.then(() => {
console.log('values', formState, toRaw(formState))
validFlag.value = true
console.log('validFlag', validFlag)
})
.catch((error: ValidateErrorEntity<FormState>) => {
validFlag.value = false
console.log('error', error)
message.warn('请输入用户名或密码!')
})
}
const resetForm = () => {
formRef.value.resetFields()
}
return {
activeKey,
switchBtn,
buttonTitle,
handleChange,
formRef,
formState,
rules,
validFlag,
login,
register,
valid,
resetForm
}
}
})
</script>
Find me
Gitee:https://gitee.com/heyhaiyon/vite-vue-ts-antd.git
微信公众号:heyhaiyang
掘金:heyhaiyang
博客园:heyhaiyang
头条号:heyhaiyang
微信群:欢迎小伙伴加入