Uniapp笔记(五)uniapp语法4

本章目标

  • 授权登录【难点、重点】

  • 条件编译【理解】

  • 小程序分包【理解】

一、授权登录

我的模块其实是两个组件,一个是登录组件,一个是用户信息组件,根据用户的登录状态判断是否要显示那个组件

1、登录的基本布局

<template>
      <view class="login-container">
        <!-- 提示登录的图标 -->
        <uni-icons type="contact-filled" size="100" color="#AFAFAF"></uni-icons>
        <!-- 登录按钮 -->
        <button type="primary" class="btn-login">一键登录</button>
      </view>
</template>
<style lang="scss">
    .login-container {
      // 登录盒子的样式
      height: 750rpx;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      position: relative;
      overflow: hidden;
      // 登录按钮的样式
      .btn-login {
        width: 90%;
        border-radius: 100px;
        margin: 15px 0;
        background-color: #EA9518;
      }
    }
</style>

2、获取微信用户的基本信息

  • 为登录绑定单击事件,调用getUserProfile方法,获取用户基本信息

<button type="primary" class="btn-login" @click="getUserProfile">一键登录</button>
  • methods 节点中声明getUserProfile事件处理函数如下

methods: {
    getUserProfile(){
        uni.getUserProfile({
            desc:'用户完善会员信息',
            success(res) {
                console.log('res',res.userInfo);
            }
        })
    }
}

3、将用户的基本信息存储到vuex

  • store/user.js 模块的 state 节点中,声明 userinfo 的信息对象如下:

state:{
    userinfo:JSON.parse(uni.getStorageSync('userinfo')||'{}')
}
  • store/user.js 模块的 mutations 节点中声明updateUserInfo()

mutations:{
    updateUserInfo(state,userinfo){
        state.userinfo=userinfo
        uni.setStorageSync('userinfo',JSON.stringify(userinfo))
    }
}
  • 修改methods节点中的getUserProfile方法,添加调用调用Mutations中的updateUserInfo实现保存数据到vuex中

import {createNamespacedHelpers} from 'vuex'
    const {mapMutations}=createNamespacedHelpers('user')
    export default {
        methods: {
            ...mapMutations(['updateUserInfo']),
            getUserProfile(){
                uni.getUserProfile({
                    desc:'用户完善会员信息',
                    success:(res) =>{
                        //将用户基本信息存储到vuex中
                        this.updateUserInfo(res.userInfo)
                          //调用getCode()方法完成code生成
                          this.getToken(res)
                    }
                })
            }
        }
    }

执行如上代码,用户基本信息已经存储到了本地,如下图所示

4、登录获取token

  • 当用户同意授权后,我们可以调用 uni.login() 方法来获取 code

async getToken(info){
    let [err,res]=await uni.login()
    const query = {
        code: res.code,
        userInfo:this.userinfo,
        appId: 'wx2b9aa7f72b4f34e2',
        appSecret: '29c37378cf09ecf6fc44466bf5612ecd'
    }
    uni.request({
        method:"POST",
        url:'http://47.98.128.191:3001/users/wxLogin',
        data:query,
        success: (res) => {
            console.log(res.data.token);
        }
    })          
}

参数说明:

  • code:必传参数,后端需要通过 code 去获取用户的 openid;

  • userInfo:非必选参数,需要根据实际项目需求,看后端是否需要用户信息;

  • appId 和 appSecret:学习阶段需要传递,实际项目中不需要传递,这两个值会在后端直接设置好;

    appId 和 appSecret 在“微信公众平台”中获取

5、将token存储到vuex中

  • user.js模块中state和mutations中分别定义token以及updateToken方法

export default{
    namespaced:true,
    state:{
        token:uni.getStorageSync('token')||''
    },
    mutations:{
        updateToken(state,token){
            state.token=token
            uni.setStorageSync('token',token)
        }
    }
}
  • 在页面组件中通过mapMutations将updateToken方法进行映射

import {createNamespacedHelpers} from 'vuex'
const {mapMutations,mapState}=createNamespacedHelpers('user')
export default{
    methods: {
		...mapMutations(['updateUserInfo','updateToken']),
        async getToken(info){
			let [err,res]=await uni.login()
			const query = {
				code: res.code,
				userInfo:this.userinfo,
				appId: 'wx2b9aa7f72b4f34e2',
				appSecret: '29c37378cf09ecf6fc44466bf5612ecd'
			}
			uni.request({
				method:"POST",
				url:'http://47.98.128.191:3001/users/wxLogin',
				data:query,
				success: (res) => {
					console.log(res.data.token);
					//保存token到vuex中
					this.updateToken(res.data.token)
				}
			})	
		}
    }
}

6、抽离出自定义组件

<template>
	<view>
		<login v-if="!token"></login>
		<userinfo v-else></userinfo>
	</view>
</template>
<script>
	import {createNamespacedHelpers} from 'vuex'
	const {mapState}=createNamespacedHelpers('user')
	import login from '@/components/login/login.vue'
	import userinfo from '@/components/userinfo/userinfo.vue'
	export default{
		components:{login,userinfo},
		computed:{
			...mapState(['token'])
		}
	}
</script>

二、退出登录

在components/userinfo/userinfo组件中完成用户的退出登录功能

import {createNamespacedHelpers} from 'vuex'
const {mapMutations}=createNamespacedHelpers('user')
export default {
	name:"userinfo",
	methods:{
		...mapMutations(['updateToken','updateUserInfo']),
		async logout(){
			const [err, succ] = await uni.showModal({
				title: '提示',
				content: '确认退出登录吗?'
			}).catch(err => err)
			if (succ && succ.confirm) {
				this.updateToken('')
				this.updateUserInfo({})
			}
		}
	}
]}

三、判断用户是否有效

之前的操作只是判断token有或者无,但是并没有完成token是否有效的判断,下面我们可以完成token是否有效的判断,具体步骤如下

  • 首先在user模块的状态机文件中编写actions的方法getUserInfoAsync来判断用户的token是否有效,如果无效直接跳到登录页面

export default{
	namespaced:true,
	state:{},
	mutations:{},
	//完成的是异步操作
	actions:{
		/*
			vuex中的actions选项中的方法是异步方法
			该方法的参数有两个
			第1个参数是vuex状态机的上下文
			第2个参数是payload是参数
		*/
		getUserInfoAsync(context,payload){
			//向后端接口发送请求
			console.log('token信息',context.state.token);
			uni.request({
				url:'http://47.98.128.191:3001/users/getUserInfo',
				header:{
					'Authorization':context.state.token
				},
				success: (res) => {
					console.log('-----------成功----------');
					console.log('res',res.data.code);
					if(res.data.code==0){
						console.log('999999999999999999');
						uni.showToast({
							title:'token已经过期请重新登录',
							success() {
								//调用mutations中的updateUserInfo和updateToken方法
								context.commit('updateUserInfo',{})
								context.commit('updateToken','')
								//跳转到我的页面中来
								uni.switchTab({
									url:'/pages/mine/index'
								})
							}
						})
						
					}
				},
				fail: (err) => {
					console.log('-----------失败----------');
				}
			})
		}
	}
}
  • 在需要认证的页面组件的onShow方法中调用状态机中的这个方法

比如mine模块中和购物车模块中有需要,则在onShow方法中添加

import {createNamespacedHelpers} from 'vuex'
const {mapActions:mapUserActions}=createNamespacedHelpers('user')
export default {
		methods: {
			...mapUserActions(['getUserInfoAsync']),
		},
		//当页面组件显示在前台的时候调用
		onShow() {
			console.log('-------购物车模块的onShow---------');
			this.getUserInfoAsync()
		}
}

四、条件预编译

注意:在HBuilder中生成条件编译的代码的快捷键是CTRL+ALT+/

1、跨端兼容

uniapp已将常用的组件、JS API 封装到框架中,开发者按照 uni-app 规范开发即可保证多平台兼容,大部分业务均可直接满足。

但每个平台有自己的一些特性,因此会存在一些无法跨平台的情况。

  • 大量写 if else,会造成代码执行性能低下和管理混乱。

  • 编译到不同的工程后二次修改,会让后续升级变的很麻烦。

在 C 语言中,通过 #ifdef、#ifndef 的方式,为 windows、mac 等不同 os 编译不同的代码。 uni-app 参考这个思路,为 uni-app 提供了条件编译手段,在一个工程里优雅的完成了平台个性化实现。

2、条件编译

条件编译是用特殊的注释作为标记,在编译时根据这些特殊的注释,将注释里面的代码编译到不同平台。

写法:以 #ifdef 或 #ifndef 加 %PLATFORM% 开头,以 #endif 结尾。

  • #ifdef:if defined 仅在某平台存在

  • #ifndef:if not defined 除了某平台均存在

  • %PLATFORM%:平台名称

条件编译写法说明
#ifdef APP-PLUS 需条件编译的代码 #endif仅出现在 App 平台下的代码
#ifndef H5 需条件编译的代码 #endif除了 H5 平台,其它平台均存在的代码
#ifdef H5 || MP-WEIXIN 需条件编译的代码 #endif在 H5 平台或微信小程序平台存在的代码(这里只有||,不可能出现&&,因为没有交集)

%PLATFORM% 可取值如下:

平台
APP-PLUSApp
APP-PLUS-NVUEApp nvue
H5H5
MP-WEIXIN微信小程序
MP-ALIPAY支付宝小程序
MP-BAIDU百度小程序
MP-TOUTIAO字节跳动小程序
MP-QQQQ小程序
MP微信小程序/支付宝小程序/百度小程序/字节跳动小程序/QQ小程序

支持的文件

  • .vue

  • .js

  • .css

  • pages.json

  • 各预编译语言文件,如:.scss、.less、.stylus、.ts、.pug

3、API条件编译

// #ifdef %PLATFORM%
平台特有的API实现
// #endif

示例,如下代码仅在 App 下出现:

//#ifdef APP_PLUS
plus.push.addEventListener('click',function(msg){
    var payload = null
    var action = '';
    if(msg.payload){
        if(typeof msg.payload === 'string'){
            payload = JSON.parse(msg.payload)
        }
        action = payload.action;
        if(action === 'open'){
            plus.webview.open(payload.url)
        }
    }
})
//#endif

示例,如下代码不会在 H5 平台上出现:

//#ifndef H5
uni.scanCode({
    success:(res)=>{
        console.log(res.result);
    }
});
//#endif

除了支持单个平台的条件编译外,还支持多平台同时编译,使用 || 来分隔平台名称。

示例,如下代码会在 App 和 H5 平台上出现:

//#ifdef APP-PLUS || H5
uni.chooseVideo({
    success:(res)=>{
        console.log(res.result);
    }
});
//#endif

4、组件的条件编译

<!--  #ifdef  %PLATFORM% -->
平台特有的组件
<!--  #endif -->

示例,如下广告组件仅会在微信小程序中出现:

<!-- #ifdef MP-WEIXIN -->
<ad unit-id="test"></ad>
<!-- #endif -->

5、样式的条件编译

/*#ifdef  %PLATFORM% */
平台特有样式
/* #endif */

注意: 样式的条件编译,无论是 css 还是 sass/scss/less/stylus 等预编译语言中,必须使用 /注释/ 的写法。

正确写法

/* #ifdef MP-WEIXIN */
.wx-color{
    color:#fff000;
}
/* #endif */

错误写法

// #ifdef MP-WEIXIN
.wx-color{
    color:#fff000
}
// #endif

6、pages.json 的条件编译

下面的页面,只有运行至 App 时才会编译进去。

// #ifdef APP-PLUS
{
    "path":"pages/api/speech/speech",
    "style":{
        "navigationBarTitleText":"语音识别"
    }
}
//#endif

不同平台下的特有功能,以及小程序平台的分包,都可以通过 pages.json 的条件编译来更好地实现。这样,就不会在其它平台产生多余的资源,进而减小包体积。

json的条件编译,如不同平台的key名称相同,cli项目下开发者自己安装的校验器会报错,需自行关闭这些校验器对json相同key的校验规则。如果使用HBuilderX的校验器,无需在意此问题,HBuilderX的语法校验器为此优化过

7、static 目录的条件编译

在不同平台,引用的静态资源可能也存在差异,通过 static 的的条件编译可以解决此问题,static 目录下新建不同平台的专有目录(目录名称同 %PLATFORM% 值域,但字母均为小写),专有目录下的静态资源只有在特定平台才会编译进去。

如以下目录结构,a.png 只有在微信小程序平台才会编译进去,b.png 在所有平台都会被编译。

┌─static                
│  ├─mp-weixin
│  │  └─a.png     
│  └─b.png
├─main.js        
├─App.vue      
├─manifest.json 
└─pages.json  

五、小程序分包

1、分包概述

1.1、什么是分包

分包是指将一个完整的小程序项目,按照需求划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。

1.2、分包的好处
  • 可以优化小程序首次启动的下载时间

    • 分包前,小程序项目中所有的页面和资源都被打包到了一起,导致真个项目体积过大,影响小程序首次启动的下载时间

    • 分包后,小程序项目由1个主包+多个分包组成

      • 主包:一般只包含项目的启动页面或Tabbar页面,以及所有分包都需要用到的一些公共资源

      • 分包:只包含和当前分包有关的页面和私有资源

  • 在多团队共同开发时可以更好的解耦协作

1.3、分包的加载规则
  • 在小程序启动时,默认会下载主包并启动主包内页面

    • tabBar页面需要放在主包中

  • 当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示

    • 非tabBar页面可以按照功能的不同,划分为不同的分包之后,进行按需下载

1.4、分包的体积限制

目前,小程序分包的大小有以下两个限制

  • 整个小程序所有分包大小不超过16M(主包+所有分包)

  • 单个分包/主包大小不能超过2M

2、分包的基本用法

2.1、配置步骤

在pages.json中配置subPackages实现分包,下面对象的常见属性

  • root:分包的根目录

  • name:分包的别名

  • pages:分包目录下,页面的相对存放路径

  "subPackages": [
        {
            "root": "productPkg",
            "name": "product",
            "pages": [
                "pages/product/product-list",
                "pages/product/product-detail"
            ]
        },
        {
            "root": "payPkg",
            "name": "pay",
            "pages": [
                "pages/pay/apy-address",
                "pages/pay/apy-detail"
            ]
        }
    ],
2.2、应用原则
  • 主包无法引用分包内的私有资源

  • 分包之间不能相互引用私有资源

  • 分包可以引用主包内的公共资源

3、独立分包

3.1、什么是独立分包

独立分包本质上也是分包,只不过它比较特殊,可以独立于主包和其他分包而单独运行。

3.2、普通分包和独立分包的区别

最主要的区别:是否依赖于主包才能运行

  • 普通分包必须依赖于主包才能运行

  • 独立分包可以在不下载主包的情况下,独立运行

3.3、独立分包的应用场景
  • 当小程序从普通的分包页面启动时,需要首先下载主包

  • 而独立分包不依赖主包即可运行,可以很大程度上提升分包页面的启动速度

3.4、配置方法
  "subPackages": [
        {
            "root": "productPkg",
            "name": "product",
            "pages": [
                "pages/product/product-list",
                "pages/product/product-detail"
            ]
        },
        {
            "root": "payPkg",
            "name": "pay",
            "pages": [
                "pages/pay/apy-address",
                "pages/pay/apy-detail"
            ],
            "independent":true
        }
    ],
3.5、引用原则

独立分包和普通分包以及主包之间,是相互隔绝的,不能相互引用彼此的资源!例如:

  • 主包无法引用独立分包内的私有资源

  • 独立分包之间,不能相互引用私有资源

  • 独立分包和普通分包之间,不能相互引用私有资源

  • 特别注意:独立分包中不能引用主包内的公共资源

4、分包预下载

4.1、什么是分包预下载

分包预下载指的是:在进入小程序的某个页面时,由框架自动预下载可能需要的分包,从而提升进入后续分包页面时的启动速度。

4.2、配置分包预下载

预下载分包的行为,会在进入指定的页面时触发。在 app.json 中,使用 preloadRule 节点定义分包的预下载 规则,示例代码如下:

 "preloadRule": {
    "pages/contact/contact": {
      "packages": [
        "p1"
      ],
      "network": "wifi"
    }
  },

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/99926.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT创建可移动点类

效果如图所示&#xff1a; 创建新类MovablePoint&#xff0c;继承自QWidget. MovablePoint头文件: #ifndef MOVABLEPOINT_H #define MOVABLEPOINT_H#include <QWidget> #include <QPainter> #include <QPaintEvent> #include <QStyleOption> #includ…

2023年7月京东打印机行业品牌销售排行榜(京东运营数据分析)

鲸参谋监测的京东平台7月份打印机行业销售数据已出炉&#xff01; 7月份&#xff0c;打印机市场呈现下滑趋势。根据鲸参谋平台的数据可知&#xff0c;当月京东平台打印机的销量为48万&#xff0c;环比下降约28%&#xff0c;同比下降约18%&#xff1b;销售额为4亿&#xff0c;环…

OCR多语言识别模型构建资料收集

OCR多语言识别模型构建 构建多语言识别模型方案 合合&#xff0c;百度&#xff0c;腾讯&#xff0c;阿里这四家的不错 调研多家&#xff0c;发现有两种方案&#xff0c;但是大多数厂商都是将多语言放在一个字典里&#xff0c;构建1w~2W的字典&#xff0c;训练一个可识别多种语…

Java 8 新特性——Lambda 表达式(2)

一、Java Stream API Java Stream函数式编程接口最初在Java 8中引入&#xff0c;并且与 lambda 一起成为Java开发里程碑式的功能特性&#xff0c;它极大的方便了开放人员处理集合类数据的效率。 Java Stream就是一个数据流经的管道&#xff0c;并且在管道中对数据进行操作&…

IP初学习

1.IP报文 首部长度指的是报头长度&#xff0c;用于分离报头和有效载荷 2.网段划分 IP地址 目标网络 目标主机 3.例子 4.特殊的IP地址 5.真正的网络环境 6.调制解调器 “猫”&#xff0c;学名叫宽带无线猫 7.NAT 源IP在内网环境不断被替换 8.私有IP不能出现在公网上 因…

时序预测 | MATLAB实现CNN-BiGRU卷积双向门控循环单元时间序列预测

时序预测 | MATLAB实现CNN-BiGRU卷积双向门控循环单元时间序列预测 目录 时序预测 | MATLAB实现CNN-BiGRU卷积双向门控循环单元时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.MATLAB实现CNN-BiGRU卷积双向门控循环单元时间序列预测&#xff1b; 2.运行环境…

性能提升3-4倍!贝壳基于Flink + OceanBase的实时维表服务

作者介绍&#xff1a;肖赞&#xff0c;贝壳找房&#xff08;北京&#xff09;科技有限公司 OLAP 平台负责人&#xff0c;基础研发线大数据平台部架构师。 贝壳找房是中国最大的居住服务平台。作为居住产业数字化服务平台&#xff0c;贝壳致力于推进居住服务的产业数字化、智能…

嵌入式学习笔记(1)ARM的编程模式和7种工作模式

ARM提供的指令集 ARM态-ARM指令集&#xff08;32-bit&#xff09; Thumb态-Thumb指令集&#xff08;16-bit&#xff09; Thumb2态-Thumb2指令集&#xff08;16 & 32 bit&#xff09; Thumb指令集是对ARM指令集的一个子集重新编码得到的&#xff0c;指令长度为16位。通常在…

微服务-sentinel详解

文章目录 一、前言二、知识点主要构成1、sentinel基本概念1.1、资源1.2、规则 2、sentinel的基本功能2.1、流量控制2.2、熔断降级 3、控制台安装3.1、官网下载jar包3.2、启动控制台 4、项目集成 sentinel4.1、依赖配置4.2、配置文件中配置sentinel控制台地址信息4.3、配置流控4…

每日一题——下一个排列

下一个排列 题目链接 读懂题目 要理解题目的意思&#xff0c;主要是要读懂这一句&#xff1a;整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。 我们来逐词分析&#xff1a; 其整数&#xff0c;即我们要将这个数组的数字构成一个十进制整数&#xff0c;例如数组…

并发编程的关键——LOCK

并发编程的关键——LOCK 锁的分类synchronized万物即可为锁synchronized的实现锁升级 LockAQSLockSupportCLHCAS Lock实现ReentrantLock阻塞方法acquireReadWriteLockReentrantReadWriteLockStampedLock 锁的分类 公平锁/非公平锁&#xff1a; – 公平的意思是多个线程按照申请…

解决vue项目首行报红( ESLint 配置)和新建的vue文件首行报红问题

目录 前情提要&#xff1a; 修改ESLint 配置 新建的vue文件首行还是报红 报红原因&#xff1a; 解决方法&#xff1a; 前情提要&#xff1a; 在网上查到的方法可能是在package.json文件或者.eslintrc.js文件中添加 requireConfigFile: false 如果此方法对你的错误不起作用…

2020ICPC南京站

K K Co-prime Permutation 题意&#xff1a;给定n和k&#xff0c;让你构造n的排列&#xff0c;满足gcd(pi, i)1的个数为k。 思路&#xff1a;因为x和x-1互质&#xff0c;1和任何数互质&#xff0c;任何数和它本身不互质 当k为奇数时&#xff0c;p11&#xff0c;后面k-1个数…

云原生Kubernetes:二进制部署K8S多Master架构(三)

目录 一、理论 1.K8S多Master架构 2.配置master02 3.master02 节点部署 4.负载均衡部署 二、实验 1.环境 2.配置master02 3.master02 节点部署 4.负载均衡部署 三、总结 一、理论 1.K8S多Master架构 (1) 架构 2.配置master02 &#xff08;1&#xff09;环境 关闭防…

yolov5自定义模型训练三

经过11个小时cpu训练完如下 在runs/train/expx里存放训练的结果&#xff0c; 测试是否可以检测ok 网上找的这张识别效果不是很好&#xff0c;通过加大训练次数和数据集的话精度可以提升。 训练后的权重也可以用视频源来识别&#xff0c; python detect.py --source 0 # webca…

盘点狼人杀中的强神与弱神 并评价操作体验

最初 强神是大家对猎人的称呼&#xff0c;但随着板子的增加 强神渐渐变成了强神神牌的统称。 狼人杀发展至今板子已经非常多了&#xff0c;而每个板子都会有不同的角色。 相同的是 大部分都会希望拿到一张强力神牌&#xff0c;这样能大大提高我们玩家的游戏体验&#xff0c;但其…

Vue2项目练手——通用后台管理项目第五节

Vue2项目练手——通用后台管理项目 首页组件布局面包屑&tag面包屑使用组件使用vuex存储面包屑数据src/store/tab.jssrc/components/CommonAside.vuesrc/components/CommonHeader.vue tag使用组件文件目录CommonTag.vueMain.vuetabs.js 用户管理页新增功能使用的组件页面布局…

Docker切换文件系统为VFS

一、介绍 Docker支持AUFS、Btrfs、Device Mapper、OverlayFS、VFS、ZFS六种不同的存储驱动。 1. AUFS AUFS是一种常见的存储驱动程序&#xff0c;它也使用了Linux内核的AUFS文件系统。它的优点是支持所有的Linux发行版&#xff0c;可以在不同的容器之间共享文件系统&#xf…

多因素认证与身份验证:分析不同类型的多因素认证方法,介绍如何在访问控制中使用身份验证以增强安全性

随着数字化时代的到来&#xff0c;信息安全问题变得愈发重要。在网络世界中&#xff0c;用户的身份往往是保护敏感数据和系统免受未经授权访问的第一道防线。单一的密码已经不再足够&#xff0c;多因素认证&#xff08;MFA&#xff09;应运而生&#xff0c;成为提升身份验证安全…

【RabbitMQ】RabbitMQ 服务无法启动。系统出错。发生系统错误 1067。进程意外终止。

问题描述 RabbitMQ 服务无法启动。 rabbitmq-service.bat startRabbitMQ 服务正在启动 . RabbitMQ 服务无法启动。系统出错。发生系统错误 1067。进程意外终止。原因分析 RabbitMQ和Erlang版本不匹配。 解决方案 查询并安装RabbitMQ版本对应Erlang版本 https://www.rabbitm…