uni-app在vue3 setup中的一些使用

240 阅读4分钟

关于一些在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.vueonShow 方法中,使用 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 方法中修改 winOffsetYwinHeight 的初始化

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")