十四、分包加载
(一)普通分包与主包
随着项目越来越大,为了用户更好的体验,小程序引用了分包技术,分包技术将tabBar页面及一些全局使用的静态资源,放到主包中,开发者可以根据需要添加分包,这些分包中也可以包含一些页面,但是在用户跳转到分包页面前,小程序是不会下载分包的相关内容。这样也减小了用户使用小程序的压力,加快了小程序的加载速度,避免了很多没有必要的内容的加载。
主包是默认没有放到分包中的所有核心源码中的内容,不需要指定主包!
1、在app.json中指定分包
"subPackages": [
{
"root": "modules/goods",
"name":"goodsModules",
"pages":[
"pages/goods/goods",
"pages/index/index"
]
}
]
2、在主包页面中添加navigator跳转到分包页面:
<!-- 注意,这里路径直接使用/定位到modules即可,/默认为项目根路径 -->
<navigator url="/modules/goods/pages/goods/goods" open-type="navigate">点击跳转到分包页面</navigator>
该配置项是一个数组,数组中有三个属性,分别
- root,分包的根目录
- name,指定项目中使用该分包时的名称
- pages,指定该分包中包含的页面。
因为分包是在数组中声明的,故可以同时有多个分包,但是分包时也有很多其他要注意的地方:
1、所有分包(包括主包)的大小之和不能超过20MB,每个分包的大小不能超过2MB。
2、分包的根目录之间不能进行嵌套,一个分包的根目录不能是另一个分包的子目录。
3、主包不可以引用分包资源,分包资源也不可以引用其他分包资源(原因可想而知,因为当用户打开小程序页面时,分包资源在用户跳转之前不会被下载,故不能引用,分包和分包之间亦是如此)。分包可以引用主包中的静态资源。
(二)独立分包
为什么会有独立分包?其适用于如下场景:
当分包页面不依赖主包资源,是一个相对独立的功能时,可以将分包设置为独立分包,如此,只有当从独立分包跳转到主包、其他分包或者直接加载主包时,主包资源才会被下载。
使用:只需要在subPackges属性中的分包对象中增加“independent”属性为true即可。
{
"root": "modules/goods",
"name":"goodsModules",
"pages":[
"pages/goods/goods",
"pages/index/index"
],
"independent": true
}
注意点:
1、独立分包不受app.wxss中样式影响
2、独立分包不能引用主包的资源(因为那时候主包可能未加载!)
3、独立分包中不能使用APP这个构建小程序的方法,否则可能会引起一些未知的错误。
(三)分包预加载
人就挺怪,有时候希望只加载用户需要的页面,这样可以更快,但又担心用户突然跳转下载又来不及,两害相权全保留,只是不同场合需要使用不同的方案,这里我们讲一下如何设置预加载。
涉及几个元素:当前所在页面,要预加载页面、开启预加载的环境!(在app.json中配置)
1、在主包主页面开启预加载:
"preloadRule": {
"pages/index/index":{
"network": "all",
"packages": ["goodsModules"]
}
}
"network"指定预加载环境:"wifi"、"all";
"packages"指定要加载的分包,可以使用上面指定分包时的"name"属性,也可以使用"root"属性(分包根目录地址)
2、在独立分包中指定预加载主包:
"modules/goods/pages/goods/goods":{
"network": "all",
"packages": ["__APP__"]
}
这里留个疑问,虽然预加载显示了,但是有警告说__APP__没有找到!
十五、微信开放能力
(一)获取微信头像并使用
A、前置准备
我们准备一个被按钮包裹的图片,实现点击图片后跳转出换头像菜单,结构如下:
<button class="btn" >
<image src="{{avatarUrl}}" class="avatarImage" ></image>
</button>
</view>
.btn{
/* 将背景色设置为透明 */
background-color: transparent;
}
/* 将按钮的边框去掉 */
.btn::after{
border: none;
}
/* 设置图片大小 */
.avatarImage{
width: 333rpx;
height: 250rpx;
border-radius: 50%;
}
B、开启菜单跳转
open-type="chooseAvatar"指定跳转出菜单,
随后指定处理的方法bindchooseavatar="bindchooseHandler",方法名没有规定。
<button class="btn" open-type="chooseAvatar" bindchooseavatar="bindchooseHandler">
<image src="{{avatarUrl}}" class="avatarImage" ></image>
</button>
bindchooseHandler(event){
// 微信头像临时地址会储存在传入参数的detail中
//这个头像的地址也是临时的,需要我们在自己的服务器做持久化处理!
console.log(event.detail)
let avatarUrl= event.detail.avatarUrl;
this.setData({
avatarUrl
})
}
(二)获取微信昵称并使用
1、我们要让input框和button被form表单包裹,这样才能实现我们的效果。
结构:
</view>
<form bindsubmit="sendName">
<!-- nickName,当点击输入框时,会弹出使用微信昵称的快捷选项 -->
<!-- name属性,提交时form表单会收集name作为key,value值作为value发送到目标服务器 -->
<input type="nickname" class="inputMe" name="nickname"placeholder="请输入昵称"/>
<!-- form-type为submit,当点击该按钮时,就会触发form标点的 -->
<button form-type="submit" class="buttonSubmit">提交昵称</button>
</form>
方法:
// 表单发送昵称的方法
sendName(event){
//昵称会被保存在传入事件参数的detail.value中
console.log(event.detail.value.nickname);
}
(三)分享
需要在页面js文件或者按钮中声明按钮类型
A、分享给朋友
1、在页面js文件的Page方法中声明。
onShareAppMessage(obj){
console.log(obj);
//return的对象,可以控制分享弹窗的内容,包括名字,路径,最后是本页面的路径。
return{
title:'我的分享',
path:'/pages/index/index',
imageUrl: "/static/suolong.jpg"
}
}
如此,该页面即可分享。
2、通过按钮形式,分享到朋友(注意此种方式需要小程序得到认证)
<button open-type="share">点我分享给朋友</button>
B、分享到朋友圈
1、在js文件中声明分享的方法:
onShareTimeline(obj){
console.log(obj);
//返回对象,控制转发朋友圈的名字,图片和当前页面的参数
return{
title:"我的分享",
query:"name=chen&age=23",
imageUrl:"/static/suolong.jpg"
}
}
注意:开启分享到朋友圈功能前提是开启分享给朋友功能!
(四)验证手机号码
A、前置
因为验证手机号服务是付费服务,且不对个人开发着开启使用,所以我们要想继续尝试使用,可以在开发时将AppID切换到接口测试号,即可正常使用。方法如下:
1、点击“详情”,然后点击AppId后的修改
2、点击下拉框,选择接口测试号即可
B、快速手机号验证、手机号实时验证
二者的区别是,前者不需要用户接受验证码,后者需要用户等待接受验证码。
结构:
<!-- 手机号快速验证 -->
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">
手机号快速验证
</button>
<!-- 手机号实时验证 -->
<button open-type="getRealtimePhoneNumber" bindgetrealtimephonenumber="getRealtimePhoneNumber">手机号实时验证</button>
js:
getPhoneNumber(event){
console.log(event);
},
getRealtimePhoneNumber(event){
console.log(event)
}
/*/实际需要一个过程就是,将传入参数中的code值传入到后端,然后后端根据code调用相应的API。
/*/返回给我们真正的用户手机号,从而让我们进行业务,这里省略。
大概结构:
{type: "getrealtimephonenumber", timeStamp: 26538, target: , currentTarget: , mark: , …}
currentTarget: Object
detail: Object
code: "156e5838b4022107394d917d427d463b123952b848a420708c2d9c546"
errMsg: "getPhoneNumber:ok"
__proto__: Object
mark: Object
mut: false
target: Object
timeStamp: 26538
type: "getrealtimephonenumber"
__evName: "getrealtimephonenumber"
_userTap: false
__proto__: Object
(五)客服支持
微信提供了客服支持,只需要设置一下按钮的属性之后,就可以接入微信提供的客服网页(或者小程序),非常的方便!
A、用户端代码:
<button open-type="contact">联系客服</button>
这样,当用户点击该按钮就会跳到客服对话界面,等待客服回复。
B、客服人员添加与回复
1、在微信公众平台上点击“服务侧边栏”,然后点击“添加客服”按钮,搜索微信号,点击添加:
最后点击蓝色字,即可作为客服回复用户疑问。
2、客服界面展示:
(六)getApp()
该方法可以用来获取小程序全局对象,我们可以在app.js中声明一些对象,方法等,在其他页面和组件中,可以通过该方法生成小程序实例,然后通过实例拿到全局数据,这样我就可以实现全局数据和方法传递。
1、在app.js中声明数据和方法:
// app.js
App({
globalData:{
myData:"天下无双,唯我独尊!"
},
//设置myData的方法
setMyData(myData){
this.globalData.myData = myData;
}
})
2、在index页面中产生app实例对象并使用app中的方法:
// 生成app实例对象
const appInstance = getApp();
Page({
//获取全局实例然后,应用到页面上。
data:{
indexData:""
},
onLoad(){
this.setData({
indexData: appInstance.globalData.myData,
})
},
changeText(){
//注意这里只是为了证明可以调用全局app中的方法,其数据并不是响应式的。
appInstance.setMyData("我才是无敌的!");
}
})
<text>{{indexData}}</text>
<button bind:tap="changeText">点我修改data</button>
十六、数据通信(补充)
(一)跳转新页面后利用数据通道
本质上跟vue的自定义事件实现页面之间数据传递很像,要接受数据的页面,利用on方法绑定自定义事件,接受方执行自定义事件接受到数据。不过微信将这种思想更加综合了,中间好似有个看不见的中间人,让数据接受方也可以发送数据,从而实现数据互通。(本质上,还是绑定自定义事件,实现数据传递
1、在接收方使用this.navigateTo,在success回调函数中调用eventChannel发送数据:
wx.navigateTo({
url: '/pages/second/second',
success(res){
//在执行传递自定义事件的同时,向跳转页面传递数据
res.eventChannel.emit("getData",{
name:"chen延年",
age: 22
})
},
//专门的配置项,用来接受跳转页面发来的数据,绑定自定义事件,并传递数据
events:{
giveData(arg1){
console.log(arg1);
}
}
})
2、发送方:
const eventChannel = this.getOpenerEventChannel();
eventChannel.on("getData",function(res){
console.log(res);//展示我们接收到的参数
});
//同时将数据发送
eventChannel.emit("giveData",{
lover:"清漪"
});
(二)数据总线
像上面分析的那样,如果需要交换数据的组件并不相临为父子组件,关系比较复杂时,一层一层传递数据中间不需要这些数据的组件就相当于白白当了一回工具,这样是极其浪费源的。所以就有下面这种思想:
一个组件专门负责数据通信,负责数据的转发,发送方只需要将要发送的数据发送,想要接收到该条数据的组件,只需要根据事件名,就可以从数据中介中获取想要的数据。(所谓发布订阅模式)
两个通信的组件,同时被同一个页面引用。
1、首先我们要引入包pubsub-js(注:笔者是mac系统,sudo是为了把文件夹权限给到位):
sudo npm install pubsub-js
2、构建(前有所提)
3、在组件中引入,并绑定事件和数据(发送方)
import PubSub from "pubsub-js"
//要引入
methods:{
giveData(){
//定阅消息
PubSub.publish("myEvent",{
name:'陈大炮',
age: 23
})
}
}
<button type="primary" bind:tap="giveData">发送数据到组件scanyou</button>
4、数据接收方(默认引入pubsub包)
lifetimes: {
//接受消息
attached(){
//接受发布者的消息
PubSub.subscribe("myEvent",(msg,data)=>{
console.log(msg,data);
this.setData({
name:data.name,
})
})
}
}
<text>孩子的名字是:{{name}}</text>