h5制作软件app有哪些(h5打包app)

现在我们来快速搭建一个开箱即用的小程序、H5开发框架 (vue3 + ts)

一、我们先来快速预览一下我们的框架结构

h5制作软件app有哪些(h5打包app)

二、使用以下命令快速创建项目

 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、接口调用

h5制作软件app有哪些(h5打包app)

//例如在页面引入 三 4 下面的 testPost方法import { testPost} from '@/utils/index'//使用const data = {	'token':'23232321121',  'workType':1}testPost(data).then((res:any):void => {	console.log(state.workTypeList )}).catch((err) => {})

2、vuex调用

注意:vue3调用状态管理和Vue2不同(三步走)

h5制作软件app有哪些(h5打包app)

//引入 useStoreimport { 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>
  
  

接下来我们就可以快速开始我们的开发了

本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 sumchina520@foxmail.com 举报,一经查实,本站将立刻删除。
如若转载,请注明出处:https://www.sumedu.com/faq/164007.html