常州个性化网站建设,学院管理网站建设,网站建设知识库,织梦教程网本章目标 授权登录【难点、重点】 条件编译【理解】 小程序分包【理解】
一、授权登录
我的模块其实是两个组件#xff0c;一个是登录组件#xff0c;一个是用户信息组件#xff0c;根据用户的登录状态判断是否要显示那个组件
1、登录的基本布局
template一个是登录组件一个是用户信息组件根据用户的登录状态判断是否要显示那个组件
1、登录的基本布局
templateview classlogin-container!-- 提示登录的图标 --uni-icons typecontact-filled size100 color#AFAFAF/uni-icons!-- 登录按钮 --button typeprimary classbtn-login一键登录/button/view
/template
style langscss.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 typeprimary classbtn-login clickgetUserProfile一键登录/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.userinfouserinfouni.setStorageSync(userinfo,JSON.stringify(userinfo))}
} 修改methods节点中的getUserProfile方法添加调用调用Mutations中的updateUserInfo实现保存数据到vuex中
import {createNamespacedHelpers} from vuexconst {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.tokentokenuni.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、抽离出自定义组件
templateviewlogin v-if!token/loginuserinfo v-else/userinfo/view
/template
scriptimport {createNamespacedHelpers} from vuexconst {mapState}createNamespacedHelpers(user)import login from /components/login/login.vueimport userinfo from /components/userinfo/userinfo.vueexport 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.code0){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中生成条件编译的代码的快捷键是CTRLALT/
1、跨端兼容
uniapp已将常用的组件、JS API 封装到框架中开发者按照 uni-app 规范开发即可保证多平台兼容大部分业务均可直接满足。
但每个平台有自己的一些特性因此会存在一些无法跨平台的情况。 大量写 if else会造成代码执行性能低下和管理混乱。 编译到不同的工程后二次修改会让后续升级变的很麻烦。
在 C 语言中通过 #ifdef、#ifndef 的方式为 windows、mac 等不同 os 编译不同的代码。 uni-app 参考这个思路为 uni-app 提供了条件编译手段在一个工程里优雅的完成了平台个性化实现。
2、条件编译
条件编译是用特殊的注释作为标记在编译时根据这些特殊的注释将注释里面的代码编译到不同平台。
写法以 #ifdef 或 #ifndef 加 %PLATFORM% 开头以 #endif 结尾。 #ifdefif defined 仅在某平台存在 #ifndefif not defined 除了某平台均存在 %PLATFORM%平台名称
条件编译写法说明#ifdef APP-PLUS 需条件编译的代码 #endif仅出现在 App 平台下的代码#ifndef H5 需条件编译的代码 #endif除了 H5 平台其它平台均存在的代码#ifdef H5 || MP-WEIXIN 需条件编译的代码 #endif在 H5 平台或微信小程序平台存在的代码这里只有||不可能出现因为没有交集
%PLATFORM% 可取值如下
值平台APP-PLUSAppAPP-PLUS-NVUEApp nvueH5H5MP-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 nullvar 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-idtest/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}},