关于服务器域名的配置
小程序中wx.request请求的接口,必须要在后台开发设置中配置对应的域名,如果api有端口,则配置域名时必须带上端口。值得注意的是,微信一个月内只允许申请修改5次,由于后台提供的接口端口号比较多,刚开始没有意识到这个问题,导致后面无法配置剩余的域名端口进而无法访问,最终在和后端同事的讨论下,借用已配置的域名做了一个中转,也就是我去访问已配置的域名,传要请求的api和参数及请求方式给他,他那边去帮我做请求然后将结果返回我,目前只能这样处理了,等后面再改回来吧,希望看到的朋友注意一下。
关于业务域名的配置
小程序不存在iframe和localtion.hred的概念,所以要想跳转外链,需借助web-view标签,web-view所跳转的链接必须在后台进行业务域名的配置,配置时注意以下几点:
1.域名需经过备案
2.域名可校验,也就是说必须是自己的网站或者说是自己可以操作控制的网站
3.域名中不能含有端口号
4.注意修改次数,一年只可修改50次,最多可配置20个
在这个过程当中,同样遇到过一个问题,首先我的h5页面是公用的,既想在app里也可在小程序里,为了和ios那边交互,我的h5页面引用了一个必须的js文件,而这个js文件里又加载了另外一个域名,web-view打开时默认也会去加载这个域名,而这个域名呢并不是我的,我也无法控制,所以就没法进行校验从而不能再后台业务域名里进行配置,从而被微信识别为非法域名不能正常进行访问。最开始采用的解决方案是单独再写一个不引用交互js的页面,但考虑到后期公用的页面比较多,也不可能一个一个去重写,也不是我想要的结果,于是就从交互js上入手,在js里域名那块做了判断,判断是否在微信里打开,如果是则不访问该域名,因为小程序里不存在和ios的交互,所以也就不存在影响的问题。
点击事件和参数传递
小程序的点击事件不同于vue的@click和原生js的onclick而是用的bindtap='alert',alert为方法名
如果需要传递参数,则需要在点击元素上进行参数的定义,如data-obj='123',obj为自定义 123为值
方法里面接受参数:
alert(e){
let obj = e.currentTarget.dataset.obj; // view接参格式
let obj = e.target.dataset.obj; // text接参格式
}
路由跳转及传参
最常用的莫过于wx.navigateTo,参数传递采用url拼接参数的形式,如果需要传递对象,可将对象转化为json字符串形式
wx.navigateTo({
url: '../home/home?id=123'
})
被跳转页面接参,可在监听页面加载生命周期中进行
onLoad: function (options) {
this.setData({
id: options.id,
})
},
需要注意的是,从普通页面跳转到tabBar页面,需要用wx.switchTab
但目前switchTab不支持url传参,如果想要传递参数,可考虑使用定义全局变量的方式
background-image不显示
小程序用background-image设置背景图片,在开发工具里面看可以显示,但在真机上无法显示,查阅后才知道,背景图片目前不支持加载本地资源,需加载网络资源,可以考虑将图片放到远程服务器上面去。
onLoad和onShow的区别
onLoad 监听页面加载,页面第一次加载是会触发,可以把一些不需要实时更新的数据放入。
onShow 监听页面显示,页面加载就触发,建议少放置操作减少请求。
之所以会关注这个问题 是在做登录那块的功能是 需要在storage里面存储一个参数 完了在首页里获取 但发现在首页里默认习惯性在onLoad里面去拿并不能及时获取到 需要刷新重新加载之后才可以 排除了异步加载的可能性之后 最终在onShow里去获取发现确实可以及时拿到 因为onShow监听的是页面显示 只要加载就会触发
如何实现列表上拉加载和下拉刷新
最开始用的是小程序的视图容器scroll-view去做,给定容器高度(如果是满屏的话可以用wx.getSystemInfo获取屏幕高度),然后用bindscrolltoupper和bindscrolltolower监听滚动到顶部和底部,从而实现下拉刷新和上拉加载的目的。但配置和逻辑相对比较麻烦,有多个需要注意的点。
后来发现了一个更好的方法,就是page页面本身提供的onPullDownRefresh和onReachBottom函数,直接监听用户是否有下拉刷新和上拉加载的动作,配置方便,逻辑判断简单。但缺点是,只能监听整个页面的动作,不能监听页面内的某一个容器的滚动事件,这一项不如scroll-view那样灵活。
// 页面下拉 归为首页 下拉刷新
onPullDownRefresh: function () {
// 显示导航栏loading
wx.showNavigationBarLoading();
// 调用接口加载数据
this.setData({
pageIndex: 1,
list: [],
isEnd: false,
})
this.getList();
// 隐藏导航栏loading
wx.hideNavigationBarLoading();
// 当处理完数据刷新后,wx.stopPullDownRefresh可以停止当前页面的下拉刷新
wx.stopPullDownRefresh();
},
// 页面上拉 向上滑 类似于向下翻页
onReachBottom: function () {
if (!this.data.isEnd) {
this.setData({
pageIndex: this.data.pageIndex + 1
})
this.getList()
}
},
需要注意的是,使用时需要先在页面json里配置enablePullDownRefresh和导航栏的样式,否则下拉加载三个点效果看不是很清楚。
{
"usingComponents": {},
"navigationBarTitleText": "我的订单",
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark"
}
具体怎么用,因需求而定;以上方式,仅供参考。
rich-text解析html时如何让图片自适应
html.replace(/\<img/gi, '<img style="max-width:100%;height:auto"')
全局变量的定义和使用
1.在app.js中定义全局参数userInfo
2.在对应页面js中 使用getApp().userInfo获取
单个页面配置导航栏为自定义
刚开始上网搜索 都说只能在app.json里window对象下配置全局的 可是我的需求是只是单独的页面需要配置 如果全局配置的话 其他页面的样式都要跟着修改 太麻烦了。然后查看了微信官方给出的文档 说是支持单页面配置 但对于导航栏样式仅限7.0.0版本以后。20201204更新:页面导航栏自定义后有个缺陷,分享出去不能使用官方的小房子图标回到首页,因为导航栏你已经自定义了,除非手动去写返回首页的图标。
小程序集成微信支付(前端)
1.用wx.login方法获取code后换取openid(后台获取 微信安全限制不让前端携带appid和secret去请求)
2.传入openid和商品价格数量等参数生成商户订单
3.用订单号获取支付参数
4.拿到支付参数 用wx.requestPayment唤起支付完成支付操作
获取openid接口:https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
参考链接:微信小程序支付前端源码 - oneall - 博客园
自定义导航栏时iPhoneX适配问题
1.app.js globalData对象中定义全局属性navHeight:0,然后在onLaunch中赋值
// 获取手机系统信息
wx.getSystemInfo({
success: res => {
//导航高度
this.globalData.navHeight = res.statusBarHeight + 46;
}, fail(err) {
console.log(err);
}
})
2.在对应的页面中获取导航栏高度属性值
this.setData({
navH: getApp().globalData.navHeight
})
3.为导航栏添加样式
<view class="tab" style='height:{{navH}}px;padding-top:calc({{navH-35}}px)'></view>
<view class="container" style='padding-top:calc({{navH}}px)'></view>
小程序中如何定义倒计时
1.util.js中定义方法并抛出
function getKillTime(killTime) {
// 计算目标与现在时间差(毫秒)
let time1 = new Date(killTime).getTime();
let time2 = new Date().getTime();
if (time1 > time2){
let mss = time1 - time2;
// 将时间差(毫秒)格式为:天时分秒
let days = parseInt(mss / (1000 * 60 * 60 * 24));
let hours = parseInt((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = parseInt((mss % (1000 * 60 * 60)) / (1000 * 60));
let seconds = parseInt((mss % (1000 * 60)) / 1000);
// 返回需要的格式
return (hours < 10 ? '0' + hours : hours) + ":" + (minutes < 10 ? '0' + minutes : minutes) + ":" + (seconds < 10 ? '0' + seconds : seconds)
// return days + "天" + hours + "时" + minutes + "分" + seconds + "秒"
}else{
return false
}
}
module.exports = {
getKillTime: getKillTime
}
2.在对应的页面中引入util.js
const util = require('../../utils/util.js')
data: {
killTime: "2019/07/25 19:59:00 GMT+0800", // 秒杀开始时间
killTimeShow: "" // 剩下的时间(天时分秒)
},
// 获取秒杀时间 由于我这边需要对时间做一些样式处理 所以单独拿出来时分秒
let timer = setInterval(() => { //注意箭头函数!!
if (util.getKillTime(this.data.killTime)){
let hour = util.getKillTime(this.data.killTime).substr(0, 2)
let minute = util.getKillTime(this.data.killTime).substr(3, 2)
let second = util.getKillTime(this.data.killTime).substr(6, 2)
this.setData({
// killTimeShow: util.getKillTime(this.data.killTime)
killTimeShow: '<span class="span">' + hour + '</span>' + ':' + '<span class="span">' + minute + '</span>' + ':' + '<span class="span">' + second + '</span>',
});
}else{
clearInterval(timer);
}
}, 1000);
小程序中如何清除计时器?如何清除多个计时器?
1.data中定义timer为数组格式
2.每创建一个计时器 用this.data.timer.push(timer)
3.onHide和onUnload生命中周期中循环遍历timer去清除
for (let i = 0; i < this.data.timer.length; i++) {
clearInterval(this.data.timer[i])
}
点击按钮分享指定页面(小程序暂不支持分享指定h5链接出去,网上有说用web-view做的还是分享出去的是一个小程序,只不过里面是h5的内容)
<button plain="true" class="item" data-id="shareBtn" open-type="share">
<image src="https://tb-images.oss-cn-shenzhen.aliyuncs.com/wxapp/wechat.png"></image>微信
</button>
/**
* 用户点击右上角分享
*/
onShareAppMessage: function (options) {
let id = options.target.dataset.id;
return {
title: '好友帮砍',
path: '/pages/bargain/help?id=' + id,
imageUrl: '', //用户分享出去的自定义图片大小为5:4,
success: function (res) {
// 转发成功
wx.showToast({
title: "分享成功",
icon: 'success',
duration: 2000
})
},
fail: function (res) {
// 分享失败
},
}
}
小程序中给对象属性赋值;给对象新增属性赋值
let value = 'aaa.name'; // 给对象已有属性赋值
let value2 = `aaa.${'age'}` // 给对象新增属性并赋值 注意引号
this.setData({
[value]:'我是名字',
[value2]:'我是年龄'
})
事故性问题:小程序发版本,提交了好几次都被驳回了,而我这边又再进行新模块的开发,每次都要回退到之前那个版本去,来回切换了有七八次,也比较着急,可能是开发工具里有缓存,导致最终提交的代码部分页面样式错乱,我这边看到审核通过了也就直接发布正式了,市场那边接到命令后也就直接推广宣传了,但线上是有问题的这就比较尴尬,这里需要注意一下,每次提交代码之后,尽量在体验版里整体走一遍测一遍,确保没有问题,再提交审核,即便已经测试过了。
小程序与h5的交互(页面跳转及传参)
1.小程序跳h5 直接采用web-view命令 设置src属性即可 参数传递可采用url拼接的方式
2.h5跳小程序
第一步 引入微信开放js文件 这里请注意版本 我最开始引入的是1.2.0 跳转不成功
<script src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
第二步 判断h5打开的环境 执行对应的操作
goDetail(id){
var smallPro=false;
wx.miniProgram.getEnv(function(res) {
console.log(res.miniprogram) // 是否在微信打开
if(res.miniprogram){
smallPro=true;
}else{
smallPro=false;
}
});
if(smallPro){
wx.miniProgram.navigateTo({
url:'../service/detail?id=' + id + '&areaId=' + 859, // 跳转到小程序的服务详情页
});
}else{
this.getDevice().method.saveData('service',{ // 跳转到app的服务详情页
serviceId:id,
areaId:859,
});
}
},
小程序中在线生成分享的h5链接二维码
1.刚开始想到的是引用第三方js用代码生成 完了再github上找了几个发现引用到的项目里 生成出来的二维码怎么扫都识别不了
2.想到了在线api去生成,网上搜索有很多,我选择了两个带https的
https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=http://www.baidu.com(未备案)
https://sapi.k780.com/?app=qr.get&data=http://www.xsyrz.cn&level=L&size=15(已备案)
过程中遇到以下几个问题:
1.canvas绘制网络图片 在真机上不生效 需先下载至本地
2.下载二维码图片至本地时 在后台配置域名时 提示未备案域名不可以
3.用已备案的地址生成二维码 用canvas绘制出来时太过模糊 扫不出来 将size加大
4.url路由中含有#号 生成时不识别具体路径 尝试UrlEncode编码的方式
小程序中绘制canvas并将其生成图片保存在本地
// 绘制分享图片
drawShareImage(headUrl,codeUrl){
let ctx = wx.createCanvasContext('shareImg');
let headImg = headUrl; // 分享首图
let codeImg = codeUrl; // 二维码
ctx.fillStyle = "white";
ctx.fillRect(0, 0, 350, 400); // 绘制白色背景
ctx.drawImage(headImg, 0, 0, 350, 260); // 绘制首图
ctx.fillStyle = 'black';
ctx.fillText(this.data.NickName + ' 喊你帮TA砍价', 20, 300); // 绘制黑色文字
ctx.drawImage('../../img/logo2.png', 20, 320, 45, 15); // 绘制logo
ctx.drawImage(codeImg, 180, 270, 75, 75);
// 将canvas生成图片 必须在draw回调中执行
ctx.draw(false, function () {
let self = this;
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 350,
height: 450,
destWidth: 700,
destHeight: 900,
canvasId: 'shareImg',
success(res) {
console.log(res.tempFilePath)
self.setData({
shareImgSrc: res.tempFilePath
})
}
})
});
},
小程序保存网络图片和本地图片到相册
saveImage() {
// 如果是网络图片 需先下载至本地
wx.downloadFile({
url: this.data.shareImgSrc,
success(res) {
console.log(res.tempFilePath)
// 如果已生成本地图片路径 可直接到这一步保存
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success(res) {
wx.showToast({
title: '保存成功'
});
}
})
},
})
},
日期格式带 - 的话在ios不生效 需用.replace(/-/g, '/')将其转成 /
小程序中如何阻止事件冒泡?和h5有什么区别?
举例:外层容器有点击事件进入详情 容器内包含按钮 点击后只想调提醒接口而不进详情
现象:传统的bindtap点击了内部按钮 外部事件也会随之触发
解决:内部按钮的提醒事件用catchtap
和h5阻止事件冒泡的区别:
$("button").click(function(event){
event.stopPropagation();
alert("The button element was clicked.");
});
$("div").click(function(){
alert("The div element was clicked.");
});
小程序web-view页面 分享出去 打开空白
原因分析:分享时微信对url进行了编码 导致打不开
解决办法:onLoad中对url进行解码处理 url: decodeURIComponent(options.url)
用户拒接保存相册权限后怎样重新打开
问题出现:项目中有一个向用户本地相册保存图片的权限 默认进来会打开弹框提示 是否授权 用户点击同意 成功保存 但点击拒绝之后 再次保存就没办法了 官网查询解释如下:
所以 原有的wx.authorize重新获取授权的方法并不能成功(网上很多人说的这种)
解决办法:wx.openSetting调起小程序设置界面 引导用户再次打开权限(但是现在好像官方好像不允许通过代码去执行了,需要用户通过点击事件去执行)
<button open-type="openSetting" bindopensetting='handler'>点击授权保存相册权限</button>
小程序中如何上传图片到阿里云oss
参考文档:
小程序上传图片到阿里云oss_征途人生&梦-CSDN博客
微信小程序直传实践 - 对象存储 OSS - 阿里云
需求描述:
用户通过小程序上传图片到阿里云服务器(oss对象存储),拿到对应的链接地址后,通过接口传给后台。
解决方案:
1.登录阿里云管理控制台,配置 Bucket 跨域,设置允许跨域访问
2.登录小程序管理后台,配置uploadFile合法域名,加入你的域名
3.下载上传demo,upload.js中配置accessid、accesskey、host,并打印new_multipart_params参数
4.通过html测试上传图片 控制台里拿到key、policy、OSSAccessKeyId、signature等参数
(以上四步参考文档里都有,讲的很详细,可以对照看一下)
5.小程序中拿取照片并上传,代码如下
// 上传照片
upload(e) {
let self = this;
wx.chooseImage({
success: function (res) {
let imgSrc = res.tempFilePaths[0];
let fileType = imgSrc.split('.')[imgSrc.split('.').length-1];
let folderName = 'app-contract/test/';
let key = folderName + new Date().getTime() + '.' + fileType;
let imgUrl = 'https://tb-images.oss-cn-shenzhen.aliyuncs.com/' + key
wx.uploadFile({
url: 'https://tb-images.oss-cn-shenzhen.aliyuncs.com',
filePath: imgSrc,
name: 'file',
formData: {
'name': imgSrc,
'key': key,
'policy': 'xxxxx',
'OSSAccessKeyId': 'xxxxx',
'signature': 'xxxxx',
'success_action_status': '200',
},
success: function (res) {
console.log(res)
self.uploadImage(imgUrl);
},
fail: function (res) {
console.log(res)
},
})
}
})
},
微信单击双击事件并存
<image mode='aspectFill' data-url='{{item}}' src="{{item}}" bindload="swiperHeight" style='width:100%;height:100%;' bindtap='multipleTap' bindtouchstart="touchStart" bindtouchend="touchEnd"></image>
// 按钮触摸开始触发的事件
touchStart(e) {
this.touchStartTime = e.timeStamp
},
// 按钮触摸结束触发的事件
touchEnd(e) {
this.touchEndTime = e.timeStamp
},
// 单击预览图片 双击心动
multipleTap(e) {
var self = this
// 控制点击事件在350ms内触发,加这层判断是为了防止长按时会触发点击事件
if (self.touchEndTime - self.touchStartTime < 350) {
// 当前点击的时间
var currentTime = e.timeStamp
var lastTapTime = self.lastTapTime
// 更新最后一次点击时间
self.lastTapTime = currentTime
// 如果两次点击时间在300毫秒内,则认为是双击事件
if (currentTime - lastTapTime < 300) {
console.log("双击事件被触发")
// 成功触发双击事件时,取消单击事件的执行
clearTimeout(self.lastTapTimeoutFunc);
wx.showModal({
title: '示爱成功',
content: '对方将会收到您的心动提示',
showCancel: false
})
self.setData({
isLove:true
})
} else {
// 单击事件延时300毫秒执行,这和最初的浏览器的点击300ms延时有点像。
self.lastTapTimeoutFunc = setTimeout(function () {
console.log("单击事件被触发")
wx.previewImage({
current: e.currentTarget.dataset.url, // 当前显示图片的http链接
urls: self.data.bannerList // 需要预览的图片http链接列表
})
}, 300);
}
}
},