项目基础搭建流程
〇、接口文档
管理后台: http://121.89.205.189:3001/admindoc/#api-Banner-GetBannerList
一、项目创建
1. vite创建项目
# npm 6.x
npm init vite@latest xxx --template vue
# npm 7+, 需要额外的双横线:
npm init vite@latest xxx -- --template vue
2. 安装依赖
cd xxx
npm install
3. 运行项目查看
npm run dev
二、创建api层
1. 接口文档地址
2. 安装axios
npm install axios -S
3. axios封装
3.1 service/axios.js
import axios from 'axios';
// 给axios设置一些默认行为
switch (process.env.NODE_ENV) {
case 'production':
axios.defaults.baseURL = 'http://121.89.205.189:3001/admin';
break;
case 'development':
axios.defaults.baseURL = '/admin';
break;
}
// 设置超时时间
axios.defaults.timeout = 5000;
// 设置跨域是否需要携带凭证
axios.defaults.withCredentials = false
// 设置判断是否响应成功的校验,3开头的代码一般都不在接口里面返回,一般都是资源类数据会返回
axios.defaults.validateStatus = status => {
return /^2|3\d{2}$/.test(status)
}
// 设置请求拦截器,
axios.interceptors.request.use((config) => {
// 进行token校验(JWT):接收服务器返回的token,存储到本地,每次发送请求,都需要带上token
// token && (config.headers.Authorization = token)
// config需要返回
const token = localStorage.getItem('token')
token && (config.headers.token = token)
return config
}, error => {
// 请求错误的操作,返回报错信息
return Promise.reject(error)
})
// 设置响应拦截器
/**
* response 包含内容:
* response: {
* data: 响应主体内容,一般都是后端返回的数据
* status: 服务器相应的状态码
* statusText: 响应状态码的描述,
* headers:服务器响应头
* config: 之前发送请求是发送给服务器的配置对象
* request: 原生的ajax对象
* }
*
*/
axios.interceptors.response.use(response => {
if(response.data?.data?.token) {
localStorage.setItem('token', response.data.data.token)
}
ElMessage({
message: response?.data?.message,
type: response.data.code === '200' ? 'success' : 'error',
})
return response.data
}, error => {
const {response} = error
// 如果返回了response,证明服务器返回了结果,可以通过返回的状态码判断
if (response) {
switch (response.status) {
// 当前请求用户需要验证,一般为需要验证用户(未登录)
case 401:
break;
// 服务器接收到请求,但拒绝处理,一般为登录状态过期(token失效)
case 403:
localStorage.removeItem('token')
break;
// 找不到资源,
case 404:
break;
}
} else {
// 说明服务器连结果都没有返回,可能的原因有两种:
/**
* 1. 服务器崩掉了
* 2. 前端客户端断网状态
*/
if (!window.navigator.onLine) {
// 判断为断网,可以跳转到断网页面
return
} else {
return Promise.reject(error)
}
}
})
export default axios
3.2 service/index.js
// 使用封装好的 axios (已设置默认选项)
import axios from './axios'
// 不缓存接口地址白名单
const whiteList = ['/banner/list', '/admin/list']
class Xhr {
// 单例模式
static getInstance() {
if (!this.instance) {
this.instance = new Xhr()
}
return this.instance
}
// 设置请求缓存
constructor() {
this.cache = new Map()
}
/**
* 请求方法:
* get类型options携带params参数作为数据对象,
* post类型options携带data参数作为数据对象
*/
request(options) {
// 对get请求做一层缓存,允许post请求添加相同的数据
const {
method,
url,
params
} = options
let accessKey = url
// 如果是get请求且有参数,要换缓存到参数,
// 否则所有该url的请求都返回同一数据
// post 请求是添加数据不需要缓存
if (method === 'get' && params) {
for (let key in params) {
accessKey += key + params[key]
}
}
// 这里借鉴了vue源码的watcher
if (this.cache.has(accessKey)) {
return Promise.resolve(this.cache.get(accessKey))
}
return axios(options).then((res) => {
if (method === 'get' && whiteList.indexOf(url) === -1) {
this.cache.set(accessKey, res)
}
return res
})
}
}
export default Xhr.getInstance()
3.3 api/demo.js
组件内引用请求接口函数,传入数据对象{},使用.then接收返回值
import fetch from '../service'
// post请求
export function docheckphone(data) {
return fetch.request({
url: "/user/docheckphone",
method: 'post',
data
})
}
// get请求
export function cartGetRecommendlist(data) {
return fetch.request({
url: "/pro/recommendlist",
method: 'get',
params: {
...data
}
})
}
三、引入vue-router@4
1. 依赖安装
npm install vue-router@4 -S
2. 创建文件目录 src/router/index.js(ts)
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
import HomeView from '@/views/HomeView.vue'
const routes: Array<RouteRecordRaw> = [
{ path: '/', component: HomeView },
{ path: '/other', component: () => import('../views/OtherView.vue') },
]
const router = createRouter({
// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
history: createWebHashHistory(),
routes, // `routes: routes` 的缩写
})
export default router
3. 入口文件导入
// main.js
// ...
import router from "./router/index"
createApp(App).use(router).use(...).mount('#app')
四、引入vuex
1. 依赖安装
npm install vuex@4 -S
2. 创建文件目录src/store/index.js(ts)
import { createStore } from 'vuex'
interface State{
count: number
}
// 创建一个新的 store 实例
const store = createStore<State>({
state() {
return {
count: 0
}
},
mutations: {
increment(state) {
state.count++
}
}
})
export default store
3. 入口文件导入
// main.js
import store from './store/index'
createApp(App).use(router).use(store).mount('#app')
4. 实现vuex数据持久化
安装插件
npm i vuex-persistedstate -S
修改store/index.js
import { createStore } from 'vuex'
// ++++++++++++
import createPersistedState from "vuex-persistedstate";
// 创建一个新的 store 实例
const store = createStore({
state () {
return {
userInfo: {},
currentMenuIndex: ''
}
},
mutations: {
updateUserInfo (state, payload) {
state.userInfo = payload
},
updateCurrentMenuIndex (state, payload) {
console.log(state.currentMenuIndex)
state.currentMenuIndex = payload
}
},
// ++++++++++++++
plugins: [
createPersistedState({
// 设置要持久化的数据
reducer: state => {
return {
currentMenuIndex: state.currentMenuIndex
}
}
})
]
})
export default store
五、 引入组件库element-plus
1. 依赖安装
npm install element-plus --save
2. 自动按需导入
这种方式不需要导入任何组件,可以直接使用
npm install -D unplugin-vue-components unplugin-auto-import
3. 配置文件配置
// vite.config.ts
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
// ...
plugins: [
// ...
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
})
4. 引入样式文件
// main.js
import 'element-plus/dist/index.css'
六、项目样式重置
1. 依赖安装
npm install normalize.css -S
2. 入口文件引入
// main.js
import 'normalize.css'