评论

uniapp小程序实现分享进入权限拦截方案

小程序分享进入权限拦截处理

背景说明

在小程序中做一些权限管理的时候,比如由哪些页面指定用户可看,可以通过 uni.addInterceptor 做接口和页面跳转拦截,非常方便,但是如果牵扯到这个页面如果可以分享,那么就不太适用了,由于分享进入直接进入小程序周期,走的onLoad, onShow,此刻页面已经进入了,没有被拦截器拦截,此刻该如何处理呢

方案一

写一个工具拦截方法,在全局或指定页面onLoad中进行执行,保证拿到用户权限后执行该方法,如果没有权限,raunchTo跳转业务落地页(登录页,首页),有权限可正常查看

<template>
    <view>
      <header></header>
      <main></main>
      <footer></footer>
    </view>
</template>
<script setup>

import { onLoad } from "@dcloudio/uni-app";
import { ref } from 'vue';
import  { isAuth } from '@/util/auth.js'
// 页面参数
const msgOptions = ref({})
onLoad(async (option) => {
 // 判断权限,跳转登录或首页
 if(option.isShare)  isAuth(option)
});
</script>
<style scoped>
</style>

但是该方法有个不太好的点,就是通过分享还是会进入到这个页面,再跳转,由于此刻onLoad,onShow已经默置执行了,会闪屏一下突然跳转到其他落地页,感觉体验上不是特别好,如果不想让用户看业务页Dom元素,看到暂无权限底图或直接跳转呢?

方案二

vue3新特性中 有个 Suspense,是等到loading结束,再渲染页面
查看Vue Suspense

方法说明:在正确渲染组件之前进行一些异步请求是很常见的事。suspense允许将等待过程提升到组件树中处理,而不是在单个组件中。

但是uniapp目前还不支持这个新特性,不过这种体验优化倒是提供了一个思路,是不是可以通过自定义实现一个拦截逻辑全局组件,类似slot插槽形式包裹去做处理呢?

1. 封装权限拦截器组件 GlobalPermission

<template>
  <!-- 加载状态 -->
  <view v-if="loading" class="loading">
    <text>加载中...</text>
  </view>
  <!-- 权限校验通过,渲染目标组件 -->
  <slot v-else-if="hasPermission"></slot>
  <!-- 权限校验未通过,显示无权限提示 -->
  <view v-else class="no-permission">
    <text>无权限访问</text>
  </view>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const props = defineProps({
  // 自定义权限校验函数
  validatePermission: {
    type: Function,
    required: true,
  },
  // 无权限时跳转的路径
  redirectPath: {
    type: String,
    default: '/pages/index/index',
  },
  options: {
    type: Object,
    default: () => ({})
  }
});
const hasPermission = ref(false); // 是否有权限
// 异步权限校验
onMounted(async () => {
  try {
    // 调用权限校验函数,或全局拦截方法
    const isValid = await props.validatePermission();
    hasPermission.value = isValid;
    if (!isValid) {
      // 无权限跳转
      uni.reLaunch({
        url: props.redirectPath,
      });
    }
  } catch (error) {
    console.error('权限校验失败:', error);
  } finally {
    loading.value = false; // 结束加载状态
  }
});
</script>
<style scoped>
</style>

2 main.js 引入注册

import GlobalPermission from './components/global-permission/index.vue'
app.component("GlobalPermission", GlobalPermission);

3 页面使用

例如:某个权限页面,当然也可以直接跳转,不需要额外loading,或者通过代码添加uni.showLoading,hideLoading去实现,只保留一个slot,这个不管是通过分享还是正常进入

<template>
  <GlobalPermission :option="msgOptions">
    <view>
      <header></header>
      <main></main>
      <footer></footer>
    </view>
  </GlobalPermission>
</template>
<script setup>

import { onLoad } from "@dcloudio/uni-app";
import { ref } from 'vue';
// 页面参数
const msgOptions = ref({})
onLoad(async (option) => {
  msgOptions.value = Object.assign({}, option)
});
</script>
<style scoped>
</style>

目前业务上通过第二种进行实现的,如果类似场景,有其他好的方案欢迎讨论哈

最后一次编辑于  01-24  
点赞 0
收藏
评论
登录 后发表内容