场景
在微信小程序开发中,应用小程序web-view组件能够在小程序中嵌入一个H5利用。如果在公众号曾经开发实现了一个网页,之后又想在小程序中也开发一个雷同的利用,就能够间接应用webview组件
间接套用一个已公布的公众号页面节俭很多开发成本。当有差异化性能时就能够通过微信sdk
的接口进行以后是否小程序/公众号的判断,而后进行webview新页面的开发。
我的公众号网页是Vue+iView
写的,小程序比较简单因为外围逻辑只是与webview进行通信,所以是原生编写。本篇次要解说应用webview遇到的一些问题解决办法以及调起领取、下载性能。简略建设一个原生小程序我的项目构造:
退出webview
首先建设一个homepage.wxml
,内容次要是一个webview组件嵌入公众号页面https://test.xxxx.com/wxgzh,传入openid和appid用于外部传递给生成订单的后端接口,ver参数
能够保障页面不缓存(最新的页面):
<!--index.wxml-->
<view class="container">
<web-view src="https://test.xxxx.com/wxgzh/?someid=38127&openid={{openid}}&appid={{appid}}&ver={{ver}}#/index"></web-view>
</view>
在首页加载时调用官网wx.login
接口申请用户登录小程序,登录后调取后端的登录接口去获取openid
最终传递到webview中。
homepage.js
//homepage.js
const app = getApp()
Page({
data: {
ver:'timesp',
openid:'',
appid:''
},
onLoad: function() {
const accountInfo = wx.getAccountInfoSync();
console.log(accountInfo.miniProgram.appId, '小程序 appId')
this.setData({
ver:new Date().getTime(),
appid:accountInfo.miniProgram.appId,
})
this.doLogin();
},
getLoginData(code){
let that = this;
wx.request({
method:'post',
url: app.globalData.baseUrl+'wx/wx/user/login',
data: {
data:{
appId:this.data.appid,
code: code
},
token:''
},
success (res) {
console.log('获取openid胜利',res)
that.setData({openid:res.data.data.openid});
},
fail(res){
console.log('获取openid失败')
}
})
},
doLogin:function(){
let that = this;
wx.login({
success (res) {
if (res.code) {
//发动网络申请
that.getLoginData(res.code)
} else {
wx.showToast({
title: '登录失败!',
})
console.log('登录失败!' + res.errMsg)
}
}
})
}
})
给小程序加返回按钮
到这里其实是曾经实现能够在小程序中关上公众号页面了,然而有个问题,当webview页面在外部进行多层跳转时,想返回上一层发现微信是没有明确的返回按钮的,影响体验。解决办法是在公众号网页外部本人实现一个公共有返回按钮的TopBar组件,然而咱们公众号页面是不须要这个TopBar的。
有一个解决办法是创立一个两头者空页面作为小程序的初始页面index.js
,当页面加载时立刻跳转到实在的首页homepage,这样做就能够强制让小程序显示出返回按钮了:
index.js
onShow: function () {
wx.navigateTo({
url: '/pages/homepage/homepage' //页面一显示就跳转至主webview页 用于返回按钮的显示
})
},
小程序缓存隔离
如果你的公众号有应用本地缓存,用户在应用完公众号网页后又切换回小程序,也就是当用户先后关上了这两个平台,因为微信内置浏览器的问题,同域的两个网站共享了同一个状态,这样会导致外部的网站本地存储的登录状态数据凌乱,显然是不行的。
那就要在拜访小程序之前就要对以后状态及时进行革除,我这里简略对以后状态判断进行重置状态。
function clearCache(){
if (
navigator.userAgent.indexOf("miniProgram") >-1
) {
if (this.getBrowserData("isWxmini") === 'false') {
//小程序查看到公众网页缓存,革除之前的缓存,包含首次进入小程序状况
// 给token一个默认值
localStorage.setItem("token", "xxx");
document.cookie = "token=xxx";
sessionStorage.setItem("token", "xxx");
this.setBrowserData("isWxmini", true);
console.log("已革除微信来的缓存");
}
} else if (this.getBrowserData("isWxmini") === 'true') {
//公众网页查看到小程序缓存,革除之前的缓存
localStorage.setItem("token", "xxx");
document.cookie = "token=xxx";
sessionStorage.setItem("token", "xxx");
this.setBrowserData("isWxmini", false);
console.log("已革除小程序来的缓存");
}
}
fetch(myConfig) {
clearCache.call(this);
数据申请...
}
因为webview
和实在公众号
中的页面应用的是同一个前端资源,所以就能够在页面的全局网络申请函数fetch调用之前执行clearCache.call(this)
。通过userAgent
是否呈现miniProgram
标识来判断以后是否在小程序当中,应用isWxmini
标识来辨别环境进行不同环境数据的革除。
小程序领取
在小程序中建设一个wxPay
页面,当这个页面加载时就间接调用官网领取的API wx.requestPayment
,而后传入从webview中传递进去的领取参数,这么做是因为要从webview中点击领取后跳转过来,前面会介绍:
wxPay.wxml
const app = getApp()
Page({
data: {
},
onLoad: function(options) {
this.getPayinfo(JSON.parse(unescape(options.payData)));
},
getPayinfo:function(data){
console.log(data);
// 调起领取
wx.requestPayment({
'timeStamp': String(data.timeStamp),//为字符串,否则报错
'nonceStr': data.nonceStr,
'package': data._package,
'signType':data.signType,
'paySign': data.paySign,
'success': function (res) {
console.log('=======领取胜利==========');
wx.showToast({
title: '领取胜利!',
})
wx.navigateBack({
})
},
'fail': function (res) {
console.log('=======领取失败==========')
wx.showToast({
icon:'error',
title: '领取失败!',
})
wx.navigateBack({
})
}
})
},
})
接下来是公众号网页的局部:
首先须要在公众号网页中退出以下公共办法,用于在公众号网页中判断以后是否在小程序webview环境中,而后就能够通过isWxMiniEnv
标识来编写相应的逻辑
import wx from "weixin-js-sdk";// 引入微信js-sdk
//以后是否在小程序webview环境
common.isWxMiniEnv = () => {
let env = false;
wx.miniProgram.getEnv((res)=> {
env = res.miniprogram;
});
return env
}
//进行小程序领取性能调用
common.wxMiniPay = (data,cb) => {
if(!common.isWxMiniEnv()) return;
let payData = escape(JSON.stringify(data)) ;
const url=`../wxPay/index?payData=${payData}`;
//跳转到小程序领取界面wxPay
wx.miniProgram.navigateTo({
url
});
cb&&cb();
}
wxMiniPay
就是一个简略的跳转函数应用sdk
中的navigateTo
能够间接跳转到小程序中的相应页面并能够在url上传递一些参数进行通信。
而后筹备工作做好之后就能够间接应用wxMiniPay
调起领取了,领取时会调用后端领取接口,返回一些订单的参数,给wxMiniPay
传入参数用于小程序页面那边接管。
_this.common.wxMiniPay({order:_this.order,timeStamp, nonceStr, _package, signType, paySign},()=>{
_this.getOrder(_this.order) //通过接口查问订单是否已领取实现
});
当跳转实现时这边会执行getOrder
办法,这个办法逻辑就是始终轮询以后订单的领取状态,如果返回订单领取实现了就会弹出领取胜利的提醒,这里我就不贴轮询代码了。
文件下载
因为是在小程序中进行下载,所以也须要在小程序创立一个下载页,当页面加载实现就间接通过传递过去的options
下载参数进行下载。
这边调用了微信官网的api wx.downloadFile
,传入下载接口和存储的地位,因为参数避免url因为一些字符导致参数谬误或者被谬误截断,就当时曾经编码一遍,所以这里须要进行一遍解码decodeURIComponent
。下载实现后调用wx.openDocument
间接把文件关上:
download.js
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.download(options)
},
download(options){
console.log(options.url)
wx.downloadFile({
url:decodeURIComponent(options.url), //解码url'
filePath: wx.env.USER_DATA_PATH + '/'+ decodeURIComponent(options.filename),
success: function (res) {
var filePath = res.filePath;
console.log(res.filePath);
wx.openDocument({
showMenu:true,
filePath: filePath,
success: function (res) {
console.log('打开文档胜利')
wx.navigateBack({ //为了不显示空页面 ,及时回退一下
delta: 1,
})
},
error: function (msg) {
console.log(msg)
}
})
},
fail:function(e){
console.log(e)
}
}
)
},
设置showMenu:true
,就能够让文件右上角呈现三个点的菜单,在下载实现后能够对文件进行转发/存储。最初因为download页面是个只有下载逻辑的空页面,在下载实现后就须要调用wx.navigateBack来关掉这个空页面。
在公众号下载界面中退出逻辑,次要是以后为小程序时就拼接一个下载url和下载接口的入参,最初通过wxsdk跳转到小程序中的对应download页面,url留神应用encodeURIComponent
能够反对更多url符号的编码:
downLoad() {//下载
let item = {
url: '',
}
item.url = "?someid=test&someNo='
+ this.$route.query.someNo;
if(this.common.isWxMiniEnv()){
let durl = window.location.protocol + "//" + window.location.host + '/wx/pdfDownload' + item.url
const url=`../download/download?url=${encodeURIComponent(durl)}&filename=文件名.pdf`;
//跳转到小程序下载界面
this.wx.miniProgram.navigateTo({
url
});
}else{
//...
}
},
->>赞赞赞~
发表回复