Skip to content

使用uniapp&Vue系开发小程序

创建项目

sh
// js
npx degit dcloudio/uni-preset-vue#vite uni-preset-vue
// ts
npx degit dcloudio/uni-preset-vue#vite-ts uni-preset-vue

也可直接clone模板

sh
// git clone -b 分支名 --single-branch <repository URL>
// js
git clone -b vite --single-branch https://github.com/dcloudio/uni-preset-vue.git
//ts
git clone -b vite-ts --single-branch https://github.com/dcloudio/uni-preset-vue.git

安装依赖

sh
cd uni-preset-vue
npm i
// yarn

运行项目

sh
npm run dev:mp-weixin
// yarn dev:mp-weixin

状态管理

使用pinia进行状态管理,安装pinia

sh
npm i pinia
// 如遇到安装依赖冲突时忽视冲突 npm i pinia --legacy-peer-deps
// yarn add pinia

使用pinia

js
// main.js
import App from './App'
import { createSSRApp } from 'vue';
import * as Pinia from 'pinia';
import util from './utils/util.js';

export function createApp() {
	const app = createSSRApp(App);
  const store = Pinia.createPinia();
	app.use(store);
	// app.config.globalProperties.$util = util;
	uni.$util = util;
  
	return {
		app,
		Pinia
	}
}

在src目录下创建store文件夹,创建相应的仓库,如user.js

js
// src/store/user.js
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';

export const useUserStore = defineStore('user', {
  // state
  const token = ref('');
  // getters
	const logged = computed( () => {
    return true
  })
  // actions
  const setToken = (token) => {
    token.value = token
  }
  retrun {
    token,
    logged,
    setToken
  }
})

pinia数据持久化

sh
npm i pinia-plugin-unistorage
// yarn add pinia-plugin-unistorage

修改main.js,增加以下代码

js
import { createUnistorage } from 'pinia-plugin-unistorage';
store.use(createUnistorage());

在页面中使用

vue
<script setup>
    import { useUserStore } from '@/store/user.js'
    const user = useUserStore()
    
    // 设置token
    const token = 'jwt-token';
    user.setToken(token)
    // 打印token
    console.log(user.token)
</script>

网络请求

axios或uni-request任选一种方式

使用axios进行网络请求

安装axios、小程序适配器插件axios-miniprogram-adapter

sh
npm i axios
// yarn add axios
npm i axios-miniprogram-adapter
// yarn add axios-miniprogram-adapter

在src目录下创建config目录,创建配置文件net.config.js

js
export const netConfig = {
    // axios 基础url地址
    baseURL: 'https://xxx.xx/api',
    // 为开发服务器配置 CORS。默认启用并允许任何源,传递一个 选项对象 来调整行为或设为 false 表示禁用
    cors: true,
    // 根据后端定义配置
    contentType: 'application/json;charset=UTF-8',
     // 回话密钥名称
    tokenName: 'Authorization',
    //消息框消失时间
    messageDuration: 3000,
    //最长请求时间
    requestTimeout: 60000,
    //操作正常code,支持String、Array、int多种类型
    successCode: [200, 0],
    //登录失效code
    invalidCode: -1,
    //无权限code
    noPermissionCode: -1,
  };

使用axios

js
// src/utils/request.js
import axios from 'axios';
import mpAdapter from "axios-miniprogram-adapter";
axios.defaults.adapter = mpAdapter;
import { netConfig } from '@/config/net.config';
const { baseURL, contentType, requestTimeout, successCode } = netConfig; 

let tokenLose = true;

const instance = axios.create({
  baseURL,
  timeout: requestTimeout,
  headers: {
    'Content-Type': contentType,
  },
});

// request interceptor
instance.interceptors.request.use(
  (config) => {
    // do something before request is sent
    return config;
  },
  (error) => {
    // do something with request error
    return Promise.reject(error);
  }
);

// response interceptor
instance.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
   */
  (response) => {
    const res = response.data;

    // 请求出错处理
    // -1 超时、token过期或者没有获得授权
    if (res.status === -1 && tokenLose) {
      tokenLose = false;
      uni.showToast({
        title: '服务器异常',
        duration: 2000
    });

      return Promise.reject(res);
    }
    if (successCode.indexOf(res.status) !== -1) {
      return Promise.reject(res);
    }
    return res;
  },
  (error) => {
    return Promise.reject(error);
  }
);

export default instance;

封装api,在src目录下创建api目录,创建不同模块请求集,如user.js

js
import request from '@/utils/request'
 
/**
 * @description 授权登录
 * @param {*} data 
 */
export function wxLogin(data) {
	return request({
		url: '/wx/code2Session',
		method: 'post',
		params: {},
		data
	})
}

/**
 * @description 获取手机号
 * @param {*} data 
 */
export function getPhoneNumber(data) {
	return request({
		url: '/wx/getPhoneNumber',
		method: 'post',
		params: {},
		data
	})
}

在页面中使用

vue
<script setup>
    import { wxLogin, getPhoneNumber } from '@/api/user.js'
      /**
     * @description 微信登录
     */
    const onWxLogin = async () => {
        uni.login({
            provider: 'weixin',
            success: loginRes => {
                state.wxInfo = loginRes
                const jsCode = loginRes.code
                wxLogin({jsCode}).then((res) => {
                    const { openId } = res.data
                    user.setUserInfo({ openId })
                })
            }
        })
    }
</script>

使用uni-request封装网络请求

js
// src/utils/request.js
import { baseURL, HEADER, TOKENNAME } from '@/config/app';
import { useUserStore } from '../store/user.js';

//发送请求
function baseRequest(url, method, data, auth = false) {
	let header = {
    
  };

	const userStore = useUserStore();
	if (!auth) {
		//登录过期自动登录
		if (!userStore.logged && !uni.$util.checkLogin()) {
			return uni.$util.toast('token过期,请重新登录', 'error', 800, () => {
				setTimeout(() => {
					uni.reLaunch({
						url: '/pages/login/index'
					})
				}, 800)
			})
		}
	}
	if (userStore.userToken.accessToken) header[TOKENNAME] = `Bearer ${userStore.userToken.accessToken}`;

	return new Promise((reslove, reject) => {
		uni.showLoading({
			title: '加载中'
		})
		uni.request({
			url: baseURL + url,
			method: method || 'GET',
			header: header,
			data: data || {},
			success: (res) => {
				// console.log('-----请求url-----', url)
				// console.log('-----请求res-----', res)
				if (res.statusCode == 200 && res.data.code == 200) {
					reslove(res.data);
				} else if (res.statusCode == 200 && res.data.code == 401) {
					uni.showModal({
						title: '错误提示',
						content: res.data.message || '登录过期,请重新登录',
						showCancel: false,
						confirmText: '重新登录',
						success(op) {
							if (op.confirm) {
								userStore.logout()
								uni.reLaunch({
									url: '/pages/login/index'
								})
							}
						}
					})
				} else {
					uni.showModal({
						title: '错误说明',
						content: res.data.message || '未知错误',
						showCancel: false,
						confirmText: '知道了'
					})
					reject(res.data.message || '系统错误');
				}
			},
			fail: (err) => {
				console.log(err);
				uni.showModal({
					title: '错误说明',
					content: JSON.stringify(err) || '未知错误',
					showCancel: false,
					confirmText: '知道了'
				})
				reject(JSON.stringify(err))
			},
			complete() {
				uni.hideLoading()
			}
		})
	})
}

const request = {};

['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => {
	request[method] = (api, data, auth) => baseRequest(api, method, data, auth)
})

export default request;

在src/api目录下创建模块请求集,如user.js

import request from "@/utils/request.js";

/**
 * 获取用户信息
 */
export function getUserInfo() {
	return request.get('sysUser/baseInfo', {}, true);
}

相关配置

安装vue自动导入插件

sh
npm i unplugin-auto-import
// yarn add unplugin-auto-import

修改vite.config.js

js
import AutoImport from 'unplugin-auto-import/vite'
 plugins: [
    AutoImport({
      imports: ["vue"]
    })
  ]

使用组件

使用vant UI组件,在src目录下创建wxcomponents,拷贝vant文件夹(npm i vant后拷贝dist目录下vant)

json
// pages.json
// 全局引入
"globalStyle": {
		"usingComponents": {
			"van-button": "/wxcomponents/vant/button/index"
		}
	}
// 局部引入
{
			"path": "pages/index/index",
			"usingComponents": {
			"van-button": "/wxcomponents/vant/button/index"
		}
}

在页面中直接使用

vue
<template>
	<view>
  	<van-button type="default">默认按钮</van-button>
  </view>
</template>