Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
uniapp封装api_uniapp请求后端接口数据,希望能够帮助你!!!。
现在我们来快速搭建一个开箱即用的小程序、H5开发框架 (vue3 + ts)
一、我们先来快速预览一下我们的框架结构
二、使用以下命令快速创建项目
npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project //或者直接下载 https://gitee.com/dcloud/uni-preset-vue/repository/archive/vite-ts.zip
三、首先处理全局配置和axiso封装
在src下创建utils 、config文件,(注意:我们把上述的 api 文件移入utils)
1、首先在我们创建的 config 文件下面创建 app.ts 文件,为方便复制代码如下:
export const APP_NAME = '开箱及用小程序、H5' export const IMAGE_URL = 'xxxxx' // 静态资源的地址 export const HTTP_REQUEST_URL = 'xxxxx' export const HEADER = { 'content-type': 'application/json', } export const HEADERPARAMS = { 'content-type': 'application/x-www-form-urlencoded', } export const TOKENNAME = 'Authorization'
2、接下来创建 requestClass.ts 文件,代码如下
const config = Symbol('config') const isCompleteURL = Symbol('isCompleteURL') const requestBefore = Symbol('requestBefore') const requestAfter = Symbol('requestAfter') class requestClass { // 默认配置 [config]: { baseURL?: string } & UniApp.RequestOptions = { baseURL: '', url: '', header: { 'content-type': 'application/x-www-form-urlencoded', }, method: 'GET', timeout: 3000, dataType: 'json', responseType: 'text' } // 拦截器 interceptors = { request: (func: Fn) => { if (func) { requestClass[requestBefore] = func } else { requestClass[requestBefore] = (request) => request } }, response: (func: Fn) => { if (func) { requestClass[requestAfter] = func } else { requestClass[requestAfter] = (response) => response } }, } static [requestBefore](config: UniApp.RequestOptions) { return config } static [requestAfter](response: any) { return response } static [isCompleteURL](url: string) { return /(http|https):\/\/([\w.]+\/?)\S*/.test(url) } request(options: UniApp.RequestOptions & { baseURL?: string }) { options.baseURL = options.baseURL || this[config].baseURL options.dataType = options.dataType || this[config].dataType options.url = requestClass[isCompleteURL](options.url) ? options.url : (options.baseURL + options.url) options.data = options.data options.header = { ...options.header, ...this[config].header } options.method = options.method || this[config].method options = { ...options, ...requestClass[requestBefore](options) } return new Promise((resolve, reject) => { options.success = function (res) { resolve(requestClass[requestAfter](res)) } options.fail = function (err) { reject(requestClass[requestAfter](err)) } uni.request(options) let obj: any = {} obj[request.url] = uni.request(options) abortRequest() { for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { const element = obj[key]; element.abort() } } } }) } get(url: string, data: any = {}, options: Recordable = {}) { return this.request({ ...options, url, data, method: 'GET' }) } post(url: string, data: any = {}, options: Recordable = {}) { return this.request({ ...options, url, data, method: 'POST' }) } put(url: string, data: any = {}, options: Recordable = {}) { return this.request({ ...options, url, data, method: 'PUT' }) } delete(url: string, data: any = {}, options: Recordable = {}) { return this.request({ ...options, url, data, method: 'DELETE' }) } getConfig() { return this[config] } // 修改默认配置的一个方法,可以修改请求地址,请求方式等等.. setConfig(func: Fn) { this[config] = func(this[config]) } } export default requestClass
3、下面创建 request.ts,代码如下
import requestClass from './requestClass' import { HEADER, HEADERPARAMS, TOKENNAME, HTTP_REQUEST_URL } from '@/config/app' import qs from 'qs' const Request = new requestClass() // 请求拦截器 Request.interceptors.request((request: any) => { if (request.header.contentType) { request.header['content-type'] = request.header.contentType delete request.header.contentType } if (request.method === 'GET') { request.data = qs.stringify(request.data) request.url = request.url + '?' + request.data } return request }) // 响应拦截器 Request.interceptors.response((response: any) => { const token = uni.getStorageSync('userDate').token // if (response.data.code === 403) { // uni.showToast({ // title: token ? '请重新登录' : '请先登录', // icon: 'none', // duration: 2000, // }) // uni.removeStorageSync('token') // uni.removeStorageSync('userInfo') // } return response }) // 设置默认配置 Request.setConfig((config: any) => { config.baseURL = HTTP_REQUEST_URL if (uni.getStorageSync('userDate').token) { config.header['Authorization'] = 'Bearer ' + uni.getStorageSync('token') config.header['token'] = uni.getStorageSync('userDate').token } return config }) export default Request
4、最后我们创建我们的 api.ts, 代码如下
import request from '@/utils/request' const options = { header: { 'content-type': 'application/x-www-form-urlencoded'}, token: uni.getStorageSync('userDate').token } /** * @method 测试接口 */ export function testGet(data :any) { return request.get('/api/kecheng/getchargekechenginfo', data) } export function testPost(data :any) { return request.post('/api/kecheng/getlistsuddenstudy', data, options) } export function testPut(data :any) { return request.post('/testPut', data) } export function testDelete(data :any) { return request.delete('/testDelete', data) }
四、处理我们的vuex,在src下创建store文件(在store 下创建 index.ts 、gettres.ts 和modules文件夹)
1、index.ts,代码如下
import { InjectionKey} from 'vue' import { createStore } from 'vuex' import { store as app, AppState, AppStore } from '@/store/modules/app' import getters from './getters' export const key: InjectionKey<Store> = Symbol() export interface RootState { app: AppState } export type Store = AppStore<Pick<RootState, 'app'>> export const store = createStore<RootState>({ modules: { app }, getters }) export function useStore(): Store { return store as Store }
2、gettres.ts,代码如下
import { RootState } from '@/store' export default { token: (state: RootState) => state.app.token, }
3、在modules 下创建app文件夹(在 app 文件夹创建以下文件夹)
1、index.ts,代码如下:
import { Store as VuexStore, CommitOptions, DispatchOptions, Module } from 'vuex' import { RootState } from '@/store' import { state } from './state' import { actions, Actions } from './actions' import { mutations, Mutations } from './mutations' import type { AppState } from './state' export { AppState } export type AppStore<S = AppState> = Omit<VuexStore<S>, 'getters' | 'commit' | 'dispatch'> & { commit<K extends keyof Mutations, P extends Parameters<Mutations[K]>[1]>( key: K, payload: P, options?: CommitOptions ): ReturnType<Mutations[K]> } & { dispatch<K extends keyof Actions>( key: K, payload: Parameters<Actions[K]>[1], options?: DispatchOptions ): ReturnType<Actions[K]> } export const store: Module<AppState, RootState> = { state, actions, mutations, }
2、state.ts,代码如下:
import {reactive} from 'vue' export interface AppState { token: string, userData: object } export const state: AppState = reactive({ token: '', userData:[] })
3、mutations.ts,代码如下:
import { MutationTree } from 'vuex' import { AppState } from './state' import { AppMutationTypes } from './mutation-types' export type Mutations<S = AppState> = { // [AppMutationTypes.SET_TOKEN](state: S, token: string): void } export const mutations: MutationTree<AppState> & Mutations = { [AppMutationTypes.SET_USER_MSG](state: AppState, userData: object) { state.userData = userData } }
4、mutation-types.ts,代码如下:
export enum AppMutationTypes { SET_USER_MSG = 'SET_USER_MSG', //SET_TOKEN = 'SET_TOKEN', }
5、actions.ts,代码如下:
import { ActionTree, ActionContext } from 'vuex' import { RootState } from '@/store' import { AppState } from './state' import { Mutations } from './mutations' import { AppActionTypes } from './action-types' import { AppMutationTypes } from './mutation-types' type AugmentedActionContext = { commit<K extends keyof Mutations>(key: K, payload: Parameters<Mutations[K]>[1]): ReturnType<Mutations[K]> } & Omit<ActionContext<AppState, RootState>, 'commit'> export interface Actions { // [AppActionTypes.ACTION_RESET_TOKEN]({ commit }: AugmentedActionContext): void } export const actions: ActionTree<AppState, RootState> & Actions = { [AppActionTypes.ACTION_LOGIN]({ commit }: AugmentedActionContext, userData: object) { commit(AppMutationTypes.SET_USER_MSG, userData) }, // [AppActionTypes.ACTION_RESET_TOKEN]({ commit }: AugmentedActionContext) { // commit(AppMutationTypes.SET_TOKEN, '') // } }
6、action-types.ts,代码如下:
export enum AppActionTypes { ACTION_LOGIN = 'ACTION_LOGIN', ACTION_RESET_TOKEN = 'ACTION_RESET_TOKEN', }
五、其他配置
1、main.ts ( 小程序默认顶部状态栏高度处理,全局变量配置等)
import { createSSRApp } from 'vue' import App from './App.vue' import { store } from './store' export function createApp() { const app = createSSRApp(App) //获取顶部状态栏高度 uni.getSystemInfo({ success: function (e: any) { // #ifndef MP app.config.globalProperties.$StatusBar = e.statusBarHeight if (e.platform == 'android') { app.config.globalProperties.$CustomBar = e.statusBarHeight + 50 } else { app.config.globalProperties.$CustomBar = e.statusBarHeight + 45 } // #endif // #ifdef MP-WEIXIN app.config.globalProperties.$StatusBar = e.statusBarHeight const custom = wx.getMenuButtonBoundingClientRect() app.config.globalProperties.$Custom = custom app.config.globalProperties.$CustomBar = custom.bottom + custom.top - e.statusBarHeight // #endif //窗口高度 app.config.globalProperties.$windowHeight = e.windowHeight //获取导航高度 app.config.globalProperties.$navHeight = e.statusBarHeight * (750 / e.windowWidth) + 91 app.config.globalProperties.$SystemInfo = e }, }) app.use(store) return { app, } }
2、小程序分包(pages.json) 例如(根据需要删减,但保持结构不变)
{ "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages { "path": "pages/template/index", "style": { "navigationBarTitleText": "开箱及用小程序、H5", "navigationStyle": "custom" } }, { "path": "pages/template/settled", "style": { "navigationBarTitleText": "开箱及用小程序、H5", "navigationBarTextStyle": "black", "navigationBarBackgroundColor": "#fff", "backgroundColor": "#f7f7f7" } }, { "path": "pages/template/user", "style": { "navigationBarTitleText": "开箱及用小程序、H5", "navigationBarTextStyle": "black", "navigationBarBackgroundColor": "#fff", "backgroundColor": "#f7f7f7" } } ], //分包 "subPackages": [ { "root":"pages/teachers", "pages":[{ "path":"teacherdetail", "style": { "navigationBarTitleText": "开箱及用小程序、H5", "navigationBarTextStyle": "black", "navigationBarBackgroundColor": "#fff", "backgroundColor": "#f7f7f7" } }] },{ "root":"pages/user", "pages":[{ "path":"collection", "style": { "navigationBarTitleText": "开箱及用小程序、H5", "navigationBarTextStyle": "black", "navigationBarBackgroundColor": "#fff", "backgroundColor": "#f7f7f7" } },{ "path":"appointment", "style": { "navigationBarTitleText": "开箱及用小程序、H5", "navigationBarTextStyle": "black", "navigationBarBackgroundColor": "#fff", "backgroundColor": "#f7f7f7" } }] }], "tabBar": { "color": "#7a7e83", "selectedColor": "#1296db", "backgroundColor": "#ffffff", "list": [{ "pagePath": "pages/template/index", "text": "首页", "iconPath": "static/img/index.png", "selectedIconPath": "static/img/index_ed.png" }, { "pagePath": "pages/template/settled", "text": "你的", "iconPath": "static/img/learn.png", "selectedIconPath": "static/img/learn_ed.png" }, { "pagePath": "pages/template/user", "text": "我的", "iconPath": "static/img/user.png", "selectedIconPath": "static/img/user_ed.png" }] }, "globalStyle": { "navigationBarTextStyle": "black", "navigationBarTitleText": "uni-app", "navigationBarBackgroundColor": "#F8F8F8", "backgroundColor": "#F8F8F8" } }
2、注意封装接口的引入和vuex的使用,例如
1、接口调用
//例如在页面引入 三 4 下面的 testPost方法 import { testPost} from '@/utils/index' //使用 const data = { 'token':'', 'workType':1 } testPost(data).then((res:any):void => { console.log(state.workTypeList ) }) .catch((err) => { })
2、vuex调用
注意:vue3调用状态管理和Vue2不同(三步走)
//引入 useStore import { useStore } from 'vuex' //调用 const store = useStore() //通过 store 调用 actions 我们的用户登录方法 store.dispatch(AppActionTypes.ACTION_LOGIN, xxx)
最后我们看一下vue3 setup() 方法,我们可能看到两种不同的写法
//个人推荐组件封装使用这种 <script lang="ts"> import {defineComponent} from 'vue' export default defineComponent({ name: "xxx", setup(props, context){ } }) </script>
<script setup lang="ts"> //引入 useStore import { useStore } from 'vuex' //调用 const store = useStore() //通过 store 调用 actions 我们的用户登录方法 store.dispatch(AppActionTypes.ACTION_LOGIN, xxx) </script>
接下来我们就可以快速开始我们的开发了
今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
下一篇
已是最新文章