uniapp的通用页面及组件基本封装

1.基本布局页面

适用于自定义Navbar头部

html 复制代码
<template>
  <view class="bar" :style="{height : systemInfo.statusBarHeight + 'px', background: param.barBgColor }"></view>
  <view class="headBox" 
        :style="{ 
          height: param.headHight + 'px',
          background: param.headBgColor,
        }">
    <view class="leftBox">
      <slot name="left">
        <view class="back" v-if="autoBack" @click="uni.navigateBack({ delta: 1 })">
			<XIcon name="back" blod></XIcon>
		</view>
      </slot>
    </view>

    <view class="centerBox">
      <slot name="center">
        <view class="title">{{param.title}}</view>
      </slot>
    </view>
	
	<view class="rightBox" :style="{ paddingRight: !slots.right ? 0 + 'px' : (menuButton.width + 12) + 'px' }">
	  <slot name="right"></slot>
	</view>
  </view>
  <slot name="topBox"></slot>
  <scroll-view @scrolltolower="emits('tolower',true)" scroll-y id="calcPoint" :style="`height:${ rollHight }px;overflow-y: auto;`">
  	<slot name="container"></slot>
  </scroll-view>
</template>

<script setup lang="ts">
	import { onMounted , ref , useSlots } from "vue";
	import { getPageResidueDIST } from "@/utils/common";
	import XIcon from "@/element/XIcon.vue"
	
	const param = withDefaults(defineProps<{
	  barBgColor: string;
	  headHight: number;
	  headBgColor: string;
	  autoBack: boolean;
	  title: string;
	}>(),{
		headHight: 44,
		headBgColor: '#ffffff',
		barBgColor: '#ffffff',
		autoBack: true,
		title: '基本页面'
	})
	
	const emits = defineEmits<{
		( e: 'tolower' , status : boolean ) : void
	}>();
	
	
	const slots = useSlots();

	const systemInfo = ref<any>({});
	const menuButton = ref<any>({ width: 0 });


	const init = async () => {
	  systemInfo.value = await uni.getSystemInfo();
	  // #ifndef APP || H5
			menuButton.value = uni.getMenuButtonBoundingClientRect();
	  // #endif
	};

	onMounted(() => {
	  init();
	  setRollHight();
	});
	
	
	
	let rollHight = ref<number>(0);
	
	async function setRollHight() {
		let calcPoint = await getPageResidueDIST('#calcPoint');
		rollHight.value = calcPoint - (systemInfo.value?.safeAreaInsets?.bottom == 0 ?  10 : systemInfo.value?.safeAreaInsets?.bottom);
	}
	
</script>

<style scoped lang="scss">
	.headBox {
	  display: flex;
	  align-items: center;
	  justify-content: space-between;
	  padding: 0 12px;
	  width: 100%;
	  box-sizing: border-box;

	  .leftBox {
		flex: 1;
		display: flex;
		justify-content: flex-start;
	  }

	  .centerBox {
		flex: 2;
		display: flex;
		justify-content: center;
		text-align: center;
		
		.title {
		  font-size: 16px;
		  color: #303133;
		}
	  }

	  .rightBox {
		flex: 1;
		display: flex;
		justify-content: flex-end;
	  }
	}

</style>

2.阿里iocn

注意使用阿里icon需要下载阿里的字体图标,然后把css的文件引入到app.vue,就可以使用iconfont icon-xxx,是你图标名称

html 复制代码
<template>
	<view>
		<text :class='`iconfont icon-${param.name}`' :style="{ fontSize: param.size + 'rpx' , color: param.color , fontWeight : param.blod ? '400' : 'bloder' }" ></text>
	</view>
</template>

<script lang="ts" setup>
	import { onBeforeMount, ref } from "vue";
	
	interface Prop {
		name: string;
		size?: number;
		color? : string;
		blod?: false;
	}
	
	const param = withDefaults(defineProps<Prop>(),{
		size: 38
	});

	
</script>

<style lang="scss" scoped>
</style>

3.缓存工具

这里扩展了一个记录历史查看

javascript 复制代码
export function setCache(key : string, value : any ) {
	uni.setStorageSync(key,value);
}

export function getCache(key : string) : any | null {
	return uni.getStorageSync(key);
}

export function removeCache(key : string)  {
	return uni.removeStorageSync(key);
}



interface Record {
	time: number;
	key: any;
}

export function saveHistory(key : string,val : any) {
	let localHistory : Array<Record> = getCache(key);
	if(!localHistory) { localHistory = [] }
	if(localHistory.some(item => item.key == val)) { return }
	localHistory.unshift({
		time: new Date().getTime(),
		key: val
	});
	setCache(key,localHistory);
}


export function removeHistory(key : string,val : any) : number {
	let row : number = 0;
	let localHistory : Array<Record> = getCache(key);
	if(!localHistory) { localHistory = [] }
	row = localHistory.length;
	localHistory = localHistory.filter(item => {
		if (item.key === val) {
			row++;
			return false;
		}
		return true;
	});
	setCache(key,localHistory);
	return row - localHistory.length;
}

4.公共工具类

获取位置、计算元素剩余搞定 , 页面跳转

javascript 复制代码
import { getCurrentInstance } from "vue";

/**
 * 根据类型跳转页面并传递数据
 * 
 * @param type - 跳转类型:
 *               - 0: 使用 `uni.navigateTo` 跳转,保留当前页面,跳转到新页面
 *               - 1: 使用 `uni.switchTab` 跳转,切换到指定 tabBar 页面
 * @param url - 目标页面的路径
 * @param key ? - 事件通道中传递数据的键名
 * @param data ? - 通过事件通道传递的数据
 */
export function skipPage(type : number,url : string,key ? : string , data ? : any) {
	switch (type){
		case 0:
			uni.navigateTo({
				url,
				success(res) {
					res.eventChannel.emit(key,data);
				}	
			})
			break;
		case 1:
			uni.switchTab({
				url,
				success(res) {
					res.eventChannel.emit(key,data);
				}	
			})
			break;
		default:
			console.log('接入中!');
			break;
	}
}



export async function getPageResidueDIST(nodeKey: string) : Promise<number> {
	const query = uni.createSelectorQuery().in(getCurrentInstance());
	let systemInfo = await uni.getSystemInfo();
	let nodeToTop : number = await new Promise((ok, _) => {
		query
			.select(nodeKey)
			.boundingClientRect((data: any) => {
				ok(data.top);
			})
			.exec();
	});
	return systemInfo.windowHeight - nodeToTop;
}

export async function getSystemInfo() {
	 return await uni.getSystemInfo();
}

export async function getMenuButton() {
	// #ifndef APP || H5
		return uni.getMenuButtonBoundingClientRect();
	// #endif
	return { width: 0  }
}

export async function getElementHight(nodeKey: string) : Promise<number> {
	const query = uni.createSelectorQuery().in(getCurrentInstance());
	let nodeToTop : number = await new Promise((ok, _) => {
		query
			.select(nodeKey)
			.boundingClientRect((data: any) => {
				ok(data.height);
			})
			.exec();
	});
	return nodeToTop;
}

interface Point {
	latitude: number;
	longitude: number;
}

export async function initLocation() : Promise<any> {
		return await uni.getLocation({
			type: 'wgs84',
			geocode:true});
}


export async function getAddress() : Promise<any> {
	return new Promise(( ok ) =>{
		uni.chooseLocation({
			success: function (res) {
				ok({
					code: 200,
					address: res.address,
					latitude: res.latitude,
					longitude: res.longitude,
					name: res.name
				})
			},
			fail() {
				ok({
					code: 201
				})
			}	
		});
	})
}

5.网络请求类

javascript 复制代码
import { env } from "@/env"
 
export default function() {
	
	interface AskModel {
		url: string,
		data?: any
		method?: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT'
	}
	 
	 
	interface ApiRes<T> {
		 code: number;
		 msg: string;
		 data: T;
	}
	 
	 
	async function orderMealAsk<T>( option : AskModel ) : Promise<ApiRes<T>> {
		return new Promise(( resolve, reject ) => {
			uni.request({
			    url:  env.orderMealReq + option.url, 
			    data: option.data || {},
				method: option.method || 'GET',
			    header: {
			    	'content-type':'application/json' 
			    },
			    success: (res) => {
			        resolve(res.data as ApiRes<T>);
			    },
				fail(res) {
					reject(res);
				}
			});
		})
	}
	
	return {  orderMealAsk }
}
相关推荐
05091512 分钟前
测试基础笔记第四天(html)
前端·笔记·html
聪明的墨菲特i43 分钟前
React与Vue:哪个框架更适合入门?
开发语言·前端·javascript·vue.js·react.js
时光少年44 分钟前
Android 副屏录制方案
android·前端
拉不动的猪1 小时前
v2升级v3需要兼顾的几个方面
前端·javascript·面试
时光少年1 小时前
Android 局域网NIO案例实践
android·前端
半兽先生1 小时前
VueDOMPurifyHTML 防止 XSS(跨站脚本攻击) 风险
前端·xss
冴羽1 小时前
SvelteKit 最新中文文档教程(20)—— 最佳实践之性能
前端·javascript·svelte
Nuyoah.1 小时前
《Vue3学习手记2》
javascript·vue.js·学习
Jackson__1 小时前
面试官:谈一下在 ts 中你对 any 和 unknow 的理解
前端·typescript
zpjing~.~1 小时前
css 二维码始终显示在按钮的正下方,并且根据不同的屏幕分辨率自动调整位置
前端·javascript·html