uniapp(微信小程序、h5)+PC+微服务

概述

最近码代码的时候遇到一些问题,这里自己记录总结一下,供大家参考,说得不对的地方希望大家指出

大概介绍一下我用到的内容

  1. 用HbuilderX新建一个uni-app项目 ,vue版本选的2,爬坑轻松一点
  2. 移动端ui框架选了uView(全量引入),打包的时候没用到的不会打包(可以查看 sourcemap),vant Weapp在微信小程序上面表现不佳,不推荐
  3. css预处理语言scss,比较接近css写法,小程序样式隔离比较严格,css代码使用样式穿透::v-deep .u-button(框架组件的类名)
  4. 图标都采用ali-icon加载,代码包可以做一下分包,主包最大2M,最大20M

以下是遇到的问题

1、开发环境代理配置无效

代理配置:

在这里插入图片描述

H5中代理有效:

在这里插入图片描述

微信小程序中异常:

在这里插入图片描述

解决办法:后端配置允许跨域,把服务地址直接指定到自己封装的request.js文件中,api.js中的接口配置要把/api前缀去掉,不然404。这里要对uni.request进行封装,使用axios封装在小程序中会报一个不支持使用XMLHttpRequest的错误。

配置方式:
在这里插入图片描述
请求结果:
在这里插入图片描述

2、scroll-view封装左侧导航,也可以自定义监听oncsrcll事件拿到scrollTop,微信不支持ref

首次渲染时需要计算右侧列表元素的高度(包括类别的高度),uniapp提供了操作dom的方法

页面结构:
在这里插入图片描述

//这样的方式存在一些问题,加载的列表不能为空,而且首次加载的数据可能会庞大。后面改造成单次只加载一个门类,做分页上拉加载
//uniapp提供了操作dom的api(微信小程序/H5均支持)
this.$nextTick(()=>{
				this.query = uni.createSelectorQuery().in(this);
				this.query.select('.scroll-con .cata-name').boundingClientRect();
				this.query.select('.scroll-con .item').boundingClientRect().exec((data)=>{
					this.headHeihgt=data[0].height;
					this.contentHeight=data[1].height;
					this.listcata.forEach((item,index)=>{
						if(index==0){
							this.areaList.push({
								startY:0,
								endY:this.headHeihgt+this.contentHeight*item.list.length
							})
						}else{
						//这里计算每个滚动区间,与左侧联动
							this.areaList.push({
								startY:this.areaList[index-1].endY,
								endY:this.areaList[index-1].endY+this.headHeihgt+this.contentHeight*item.list.length
							})
						}
						this.areaList.push();
						this.orderList.push(item.list.length);
					})
				});
				
				})

实现效果,左侧点击和右侧滚动联动(双向)

在这里插入图片描述

3、自定义组件的使用,不要在子组件修改父组件的值(子组件改数据,在H5中能渲染,但是有逻辑问题,不推荐),通过子组件emit事件在父组件中修改数据,对于通过v-for遍历要传递给子组件的值如果使用v-model语法糖写法,数据需要写成arr[index]的形式,选中的商品存入Vuex,不会丢失响应式,其它页面数据变更,分类列表中的数据也会收到通知

在这里插入图片描述
在这里插入图片描述

4、错位瀑布流布局,基于grid布局的gridRow属性实现,没有强迫症完全没必要做这样的布局,就像底部的TabBar一样

在这里插入图片描述

//这段代码用于计算每个元素的位置,错位布局的重点感觉在于数据的筛选,否则没有足够的内容填充容器
gridLayout(){
				this.gridInfo=[];
				let  flag=true;
				//可以调整左右的高度,当前数据会表现成一个回字结构
				let arr=[3,4];
				for(let i=0;i<this.prefGoods.length;i++){
					if(flag){
						this.gridInfo.push({
							startRow:this.gridInfo[i-2]?this.gridInfo[i-2].endRow:1,
							endRow:this.gridInfo[i-2]?this.gridInfo[i-2].endRow+arr[0]:4,
							offset:arr[0],
							className:arr[0]>arr[1]?'largeSty':'normalSty'
						})
					}else{
						this.gridInfo.push({
							startRow:this.gridInfo[i-2]?this.gridInfo[i-2].endRow:1,
							endRow:this.gridInfo[i-2]?this.gridInfo[i-2].endRow+arr[1]:5,
							offSet:arr[1],
							className:arr[1]>arr[0]?'largeSty':'normalSty'
						})
					
					}
					if((i+1)%2==0){
						//反转数组,切换左右的高度变化
						arr.reverse();
					}
						
						flag=!flag;
				}

效果:

在这里插入图片描述

PC端准备用Vue3写,后面有问题也接在这里.
书接上回接着写,vue3代码都是在setup语法糖中写的,还是老配方js,后续用ts改一下,先上个效果图

在这里插入图片描述

5、多层级别的菜单(理论上可以无限层级),原理主要是组件的递归,直接贴代码了,参考了一下别人vue2的玩法,一开始用vuex做状态管理,感觉太重了,后面用了pinia,直接配置实现持久化,真香~

<template>
    <template v-for="(v, index) in props.siderbarMenu">
        <el-sub-menu :index="v.name" v-if="v.children && v.children.length > 0" :key="v.name">
            <template #title>
                <el-icon :size="20">
                    <span class="iconfont" :class="v.meta.icon"></span>
                </el-icon>
                <span>{{ v.meta.name }}</span>
            </template>
            <my-nav :siderbarMenu="v.children">
            </my-nav>
        </el-sub-menu>
        <el-menu-item v-else :key="index" :index="v.name" @click="gotoRoute(v)">
            <el-icon :size="20">
                <span class="iconfont" :class="v.meta.icon"></span>
            </el-icon>
            <template #title>{{ v.meta.name }}</template>

        </el-menu-item>
    </template>
</template>

<script>
export default {
    name: 'myNav' //给组件命名
}
</script>
<script setup >
import { onMounted } from 'vue';
import { useRouter } from "vue-router"
import usePermission from '~/store/permission.js'
const permissionStore = usePermission();
const router = useRouter();
const props = defineProps({
    siderbarMenu: {
        type: Array,
        default () {
            return new Array();
        }
    }
})
onMounted(() => {

})
const gotoRoute = function (route) {
    permissionStore.currentMenu = route.name;
    if (permissionStore.selectMenu.every(item => item.name != route.name)) {
        permissionStore.selectMenu.push({
            name: route.name,
            title: route.meta.name
        })
    }

    router.push({ name: route.name })
}
</script>

里面需要注意一些问题,
1.不要在setup以外的地方使用useStore、useRouter以及useRoute,原因就是无法保证对应的实例已经创建
2.动态路由加载中一定要配置404路由,当用户刷新页面时路由时匹配不到的,会报一个警告,设置临时路由的方式不推荐,太绕了,直接通配解决,路由守卫没有放行用户是看不到404页面的(3g慢速会看到一个白屏)
3.路由拦截中使用pinia需要注意时机

问题1:(引用对应的实例就可以了)
在这里插入图片描述
在这里插入图片描述
问题2:(配置正则通配,位置可以随意放,不像vue2中“”必须放最后)*
在这里插入图片描述

在这里插入图片描述
问题3:(个人理解是进入守卫之前,pinia还没挂载好)
在这里插入图片描述
在这里插入图片描述

目前差不多就这样,用户菜单数据目前是写死的,接下来撸java,等接口撸完回来搞一搞echarts美化一下。
书接上回,后端的权限设计做完了,基于RBAC模型,一开始想基于用户做权限绑定,但是权限表的数据会十分庞大,因为要做成菜单树返回,因为涉及到递归效率也十分低下,下面是所有的微服务

在这里插入图片描述

权限相关的表设计,需要注意的会在图中指出,提一下就是用户和角色是多对多的关系(看到关联表应该明白)

在这里插入图片描述

在这里插入图片描述

下面是后端鉴权的流程,认证鉴权服务就是上述中的auth-service,主要是生成token,将用户具备的api接口集合存到redis中,用于gateway网关服务放行的参照,这样就控制到了按钮级别。组装前端的菜单树需要一个方法进行迭代,一开始我把按钮权限绑定到了每个路由下(注意不是api),但是vue3中useRoute没办法用,在每个页面写v-if又有点low,最后还是把按钮权限全部收集成一个集合返给前端,前端存pinia(配置了持久化),通过v-directive做按钮权限控制。

在这里插入图片描述

下面这段代码用于生成菜单树,我只测试到了四级菜单,理论上可以无限层级,但是没必要哈

//迭代菜单树,从level=1开始
private  List<Menu> assemble(List<Menu> routes,List<Menu> menus,Integer level){
        //当前遍历的菜单层级
        Integer finalLevel = level;
        List<Menu> currentLevel=new ArrayList<>();
        List<Menu> childrens=new ArrayList<>();
        currentLevel=routes.stream()
                .filter(m->m.getLevel()== finalLevel).collect(Collectors.toList());
        if(currentLevel.stream().count()==0)
            return null;
        //每个层级下面的子菜单
        for (Menu menu : currentLevel) {
            level=finalLevel;
            //遍历子菜单
            childrens=routes.stream().filter(m->m.getParentid()==menu.getId())
                    .collect(Collectors.toList());
            menu.setChildren(childrens);
            assemble(routes,menus,++level);
        }

        return currentLevel;
    }

在这里插入图片描述

前端代码以及实现效果,当前用户没有sys:order:edit权限

在这里插入图片描述

在这里插入图片描述

后续完善一下功能,结合业务接入一些高大上一点的功能,目前就这样了,撒花撒花~

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值