1.基本布局页面
适用于自定义Navbar头部
<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,是你图标名称
<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.缓存工具
这里扩展了一个记录历史查看我
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.公共工具类
获取位置、计算元素剩余搞定 , 页面跳转
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.网络请求类
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 }
}