关于一些在uni-app中使用vue3,setup语法中使用的组件和方法
路由传参
在使用uni.navigateTo
跳转时,通过url
指定跳转路径,events
接收被打开页面emit
传递的方法,success
中通过eventChannel
向被打卡页面传数据,具体例子:
<script setup>
// 父页面
uni.navigateTo({
// 被打开的url对应pages中的path,注意需要加 '/' 前缀,不然跳转的是相对路径
url: `/pages/to/index`,
// 接收被打开页面emit的方法
events: {
fnFromEmit: function (data) {
console.log(data);
},
},
// 通过eventChannel向被打开页面传送数据
success: function (res) {
res.eventChannel.emit("dataFromFather", {
data: 'dataFromFather'
});
},
})
</script>
子页面一般在 onMounted
中接收传统过来的数据进行操作,需要通过 getCurrentInstance()
获取当前实例:
<script setup>
// 保存一个全局的eventChannel,以便后面向父页面emit数据
const eventChannel = ref(null)
onMounted(() => {
const instance = getCurrentInstance().proxy;
const event = instance.getOpenerEventChannel();
// 接收父页面传递过来的数据
event.on("dataFromFather", function (data) {
console.log(data) // dataFromFather
});
eventChannel.value = event
});
// 向父页面emit数据
function emitData(){
// 不要忘记 .value,emit的方法名需要和父页面中 events 中定义的方法匹配上
eventChannel.value.emit("fnFromEmit", { data: 'dataFromChild' });
}
</script>
全局拦截
uni-app中实现类似 router.beforeEach
的全局路由守卫,在 App.vue
的 onShow
方法中,使用 uni.onBeforePageLoad
监听,如全局拦截未登录情况下,跳转去登录页面
<script setup>
onShow: function () {
function isTologin(options) {
// 白名单
const whitePages = [
"pages/login/index",
"pages/mine/index",
"pages/index/index",
];
// 查看是否登录
const isLogin = function(){};
if (!isLogin && !whitePages.includes(options.path)) {
uni.redirectTo({
url: "/pages/login/index",
});
return false;
}
}
uni.onBeforePageLoad((options) => {
isTologin(options);
});
},
</script>
索引列表
使用 uni-indexed-list
, 直接去官网下载最新版本解压后,把文件复制到 src/components
下,在需要使用的地方引入
import uniIndexedList from "../../components/uni-indexed-list/uni-indexed-list.vue";
官网的代码直接使用是有问题的,它的 setList
方法中初始化的数据有问题,需要修改其中一些代码
首先确定根元素 view
有没有设置 ref="listRef"
,然后去 setList
方法中修改 winOffsetY
和winHeight
的初始化
setList(){
...
this.createSelectorQuery()
.select("#listRef")
.boundingClientRect()
.exec((ret) => {
this.winOffsetY = ret[0].top;
this.winHeight = ret[0].height;
this.itemHeight = this.winHeight / this.lists.length;
});
...
}
最后可以配合使用 uni-transition
实现从屏幕右侧滑出,也是去官网下载以后解压到 src/components
下,导入
<template>
<view>
<button @click="showIndexed=true"></button>
<uni-transition
mode-class="slide-right"
class="set-transition"
:styles="{ width: '100vw', height: '100vh' }"
v-if="showIndexed"
:show="showIndexed"
>
<uni-indexed-list
:options="list"
@click="handleSel"
></uni-indexed-list>
</uni-transition>
</view>
</template>
<script setup>
import uniTransition from "../../components/uni-transition/uni-transition.vue";
import uniIndexedList from "../../components/uni-indexed-list/uni-indexed-list.vue";
const showIndexed = ref(false);
// 索引列表的数据格式
const list = ref([
{
letter: "A",
data: [
"阿",
],
},
{
letter: "B",
data: [
"吧",
],
},
]);
function handleSel(data){
console.log(data)
}
</script>
地图使用
小程序默认使用的腾讯地图,只需要在页面中使用 <map>
标签就行,如果要获取位置信息,需要到小程序开发者页面申请权限,并在 manifest.json
中配置。
"mp-weixin": {
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示" // 公路行驶持续后台定位
}
},
"requiredPrivateInfos": ["getLocation", "choosePoi", "chooseLocation"]
},
下面例子介绍一些基本的数据和使用
- latitude,longitude: 通过设置 latitude、longitude 地图中心点
- polyline: 轨迹线
- markers: 地图上的点图,必要数据格式
{
longitude: ,
latitude: ,
id: 0,
name: ''
}
- includePoints: 需要被包含的点位,动态修改以后,地图会自动缩放到包含所给的点位
[
{
latitude: mapData.markers[0].latitude,
longitude: mapData.markers[0].longitude,
},
{
latitude: mapData.markers[1].latitude,
longitude: mapData.markers[1].longitude,
},
];
- scale: 地图缩放大小
当想手动监听地图移动时的事件时,可通过在 regionchange
方法获取当前地图的中心点位,详细使用可看官网,如果想在地图中心放一个固定的点位,可通过取巧的方式,在 <map>
外设置一个绝对定位的元素,这个元素的样式还可以自定义,设置显示的文字等
<template>
<view>
<map
id="map"
:longitude="mapData.longitude"
:latitude="mapData.latitude"
:scale="mapData.scale"
:include-points="mapData.includePoints"
:polyline="mapData.polyline"
@regionchange="updateMapCenter"
>
<!-->自定义marker样式<-->
<cover-view slot="callout">
<cover-view
v-for="item in mapData.markers"
:marker-id="item.id"
:key="item.id"
>
<cover-view class="custom-callout">
{{ item.name }}
</cover-view>
</cover-view>
</cover-view>
</map>
<view class="center-marker">
<text class="text">{{ mapData.centerName }}</text>
</view>
</view>
</template>
<script setup>
const mapData = reactive({
latitude: "", // 通过设置 latitude、longitude 地图中心点
longitude: "",
polyline: "", // 轨迹线
markers: [], // 地图上的点图
includePoints: [], // 需要被包含的点位
scale: 14, // 地图缩放大小
centerName: '' // 自定义的中心点位
});
// 监听地图中心点位发生变化
function updateMapCenter(e) {
// 当是 begin 阶段 并且是 手势触发 时,清空
if (e.type === "begin" && e.causedBy === "gesture") {
mapData.centerName = "";
} else if (e.type === "end" && e.causedBy === "gesture") {
// 当是 end 阶段 并且是 手势触发 时,触发获取当前中心点位的地址信息
mapData.centerName = "正在定位";
const mapCtx = uni.createMapContext("map");
// 获取当前中心点位经纬度
mapCtx.getCenterLocation({
success: function (res) {
console.log("updateMapCenter:", res);
// 获取以后可自己实现获取地址信息
},
});
}
}
</script>
<style>
.map_container {
position: relative;
overflow: hidden;
}
#map {
width: 100%;
height: 30vh;
}
.center-marker {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.custom-callout {
border-radius: 6px;
background-color: #ffffff;
color: #000000;
padding: 6px;
font-size: 12px;
max-width: 120px;
white-space: pre-wrap;
word-break: break-all;
}
</style>
其他一些api的使用
打电话
uni.makePhoneCall({
phoneNumber: "11111111111",
// 成功回调
success: (res) => {
console.log("调用成功!");
},
// 失败回调
fail: (res) => {
console.log("调用失败!");
},
});
提示框
// 消息提示框
uni.showToast({
title: "登录成功",
icon: "success",
});
//对话框
uni.showModal({
title: "标题",
content: "内容可加\r\n 设置换号,开发者工具中看不到效果 \r\n 真机可以",
showCancel: false, // 是否展示取消按钮
confirmText: "确定按钮文字",
success(res) {
if (res.confirm) {
console.log("用户点击确定");
} else if (res.cancel) {
console.log("用户点击取消");
}
},
});
// loading提示框
uni.showLoading({
title: "登录中...",
});
// 需手动关闭
uni.hideLoading();
缓存数据
// 同步方式设置
uni.setStorageSync("login", {
time: new Date().getTime(),
});
// 同步方式获取
uni.getStorageSync("login")