- 目前为止最全的微信小程序项目实例
wx-gesture-lock 微信小程序的手势密码 WXCustomSwitch 微信小程序自定义 Switch 组件模板 WeixinAppBdNovel 微信小程序demo:百度小说搜索 shitoujiandaobu 小程序:石头剪刀布(附代码说明) audiodemo 微信小程序开发之视频播放器 Video 弹幕 弹幕颜色自定义 star 微信小程序开发之五星评分 switchCity 微信小程序开发之城市选择器 城市切换 huadong_del 微信小程序滑动删除效果 jianhang_menu 微信小程序开发之圆形菜单 仿建行圆形菜单 xiaoxiaoxiao_lazyload 实现微信小程序图片懒加载特效 kangaiduowei 微信小程序:康爱多微商城:学习界面设计 tianmao_dazhuanpan 小程序实现大转盘 仿天猫抽奖 跑马灯效果(有图有源码) weapp-meirong 微信小程序学习用demo推荐:美容商城;列表,预约 baisi 微信小程序仿百思不得姐 weapp-one 仿 「ONE · 一个」 的微信小程序 netmusic-app 仿网易云音乐APP的微信小程序 a_takeaway 微信小程序的外卖demo sideslip 微信小程序『侧边栏滑动』特效 wx_plo 微信小程序之仿微信漂流瓶 kwonWhere 微信小程序-知亦行 audiodemo 微信小程序开发之视频播放 弹幕 弹幕颜色自定义 wxChart 微信小程序图标插件 guoku 微信小程序-果库 snake 微信小程序-贪吃蛇小程序 douban_movie 微信小程序-仿豆瓣电影 RecordDemo 麦克风动画 shishanggou 实现了包括常用组件,ajax获取数据,模板使用,路由等的使用,下拉刷新数据;
2019-02-12 - 解密用户信息报错pad block corrupted
解密用户信息报错,如下: 前端: [代码] [代码][代码]wx.login({[代码] [代码] [代码][代码]success: [代码][代码]function[代码] [代码](loginResp) {[代码][代码] [代码][代码]if[代码] [代码](loginResp.code) {[代码][代码] [代码][代码]//获取用户信息[代码][代码] [代码][代码]wx.getUserInfo({[代码][代码] [代码][代码]withCredentials: [代码][代码]true[代码][代码],[代码][代码] [代码][代码]success: [代码][代码]function[代码] [代码](res) {[代码][代码] [代码][代码]//封装登陆需要的参数[代码][代码] [代码][代码]var[代码] [代码]params = {};[代码][代码] [代码][代码]params.code = loginResp.code;[代码][代码] [代码][代码]params.encryptedData = res.encryptedData;[代码][代码] [代码][代码]params.iv = res.iv;[代码][代码] [代码][代码]//调用登陆接口[代码][代码] [代码][代码]that.sendRequest({[代码][代码] [代码][代码]url: [代码][代码]'/login'[代码][代码],[代码][代码] [代码][代码]data: params,[代码][代码] [代码][代码]success: [代码][代码]function[代码] [代码](res) {[代码][代码] //cache userInfo...[代码][代码] [代码][代码]}[代码][代码] [代码][代码]})[代码][代码] [代码][代码]},[代码][代码] [代码][代码]fail: [代码][代码]function[代码] [代码](e) {[代码][代码] [代码][代码]console.log(e);[代码][代码] [代码][代码]}[代码][代码] [代码][代码]});[代码][代码] [代码][代码]} [代码][代码]else[代码] [代码]{[代码][代码] [代码][代码]console.log([代码][代码]'获取用户登录态失败!'[代码] [代码]+ res.errMsg)[代码][代码] [代码][代码]}[代码][代码] [代码][代码]}[代码][代码] [代码][代码]});[代码] 后台步骤: 1) 跟据code换取用户session_key 拼接url参数:https://api.weixin.qq.com/sns/jscode2session?appid=xxx&secret=xxxx&js_code=xxxx&grant_type=authorization_code 请求方式:http get 返回结果: {"session_key":"xxxxxxxx","openid":"xxxxxxxxxx"} 2) 使用解密工具类解密出明文,使用:AES/CBC/PKCS7Padding AES方式解密 参数:encryptedData、sessionKey、iv 结果: javax.crypto.BadPaddingException: pad block corrupted 但是紧接着第二次再走以上流程是可以正常解出明文用户信息的 过会再走以上流程第一次请求又是报这个错误
2018-03-20 - 手机号解密失败?扫盲帖+解决方案
一、之前的解密流程,会偶现“解密失败”,步骤如下: 1、点击 ‘getPhoneNumber’ 的按钮,弹出授权界面 2、调用 wx.checkSession 进行检查,success 的话就发送授权手机号解密接口;fail 的话就进行 wx.login 获取 code 后请求后端获取 openid/sessionKey,并将两个值缓存到本地,然后再进行手机号解密。 二、粗暴方式解密流程,会偶现“解密失败”,步骤如下: 1、点击 ‘getPhoneNumber’ 的按钮,弹出授权界面 2、调用 wx.login 获取 code 后请求后端获取 openid/sessionKey,然后进行手机号解密 探讨微信解密机制(个人理解,如有不对,请指出哟),如下: 1、点击 ‘getPhoneNumber’ 的按钮,弹出授权界面时,在微信后台会将数据进行加密,此时用于加密的 sessionKey-0 是微信后台已存的 sessionKey,这个 sessionKey 有可能是之前其他业务生成的,比如 wx.login(会刷新微信后台的 sessionKey)。 [图片] 2、按照如上错误的步骤,进行 wx.login 获取 code 再获取 sessionKey-1,由于 wx.login 会刷新微信后台的登录状态,此时新生成的 sessionKey-1 和上一步中用于加密的 sessionKey-0 不是同一个,于是解密失败了。 3、重点:必须保持操作前后的 sessionKey 都是同一个,如果 wx.login 刷新了后台的 sessionKey,而之前的操作还是原来的 sessionKey,则会失败。 必现方式一(解密失败),如下: 1、正常授权解密后,关闭小程序一段时间,测试的时候大概 30-40 分钟左右,后台 sessionKey 过期了 2、重新打开小程序走之前的步骤,出现“解密失败”,然后第二次进行授权解密时,又成功了 必现方式二(解密失败),如下: 1、清理缓存后,点击授权登录(此时后台的sessionKey为空,所以无论怎么做登录和检查,都会解密失败),弹出界面后调用 wx.login 进行登录获取 sessionKey 2、授权解密,失败 3、再次点击授权登录(此时会获取第一步中登录生成的 sessionKey,与未过期的sessionKey一致),则进行解密,成功。 解决方案,如下: 基于对上面机制的理解,wx.login 方式获取的 sessionKey 必须在唤起授权弹窗前进行,必须保证授权弹窗时获取的 sessionKey 和 本地未过期的sessionKey是同一个。 1、在 app.js 的 onLaunch 中,先进行 wx.checkSession。success,则进行后续代码执行;如果 fail,则进行 wx.login 重新获取 sessionKey,后端同学将 sessionKey 存储至数据库,openid 是唯一的,可以作为主键。此时,会先于任何操作之前生成一个 sessionKey。 2、唤起授权界面,点击“允许”后,将 openid+iv+encryptedData 传给后端进行解密。 代码如下(IDE复制后没发改样式,const 等变量可能看不清,可以复制到自己的编辑器中查看哈): 然后在 onLaunch 中调用 onLogin.checkSession 进行前置 session 检查和获取 export const onLogin = { // 检查 session 是否有效 checkSession(cb = () => {}) { const _this = this; // 检查登录态是否可用 wx.checkSession({ success () { console.log('session success'); // session_key 未过期,并且在本生命周期一直有效 const { openid, session_key } = wx.getStorageSync('session'); cb(openid, session_key); }, // 登录态失效了 fail () { console.log('session fail'); _this._wxLogin((openid, session_key) => { cb(openid, session_key); }); } }); }, // 微信获取 code 进行解密 _wxLogin(cb = () => {}) { // 将 js_code 发送给后端获取 openId 和 sessionKey,并进行缓存 wx.showLoading({ mask: true }); wx.login({ success: ({ code }) => { // 将 js_code 发送给后端获取 openId 和 sessionKey,并进行缓存 request({ url: `/wx/open/getSessionKey.json?code=${code}&clientIdentity=${CONFIG.clientIdentity}`, onSuccess: ({ openid, session_key }) => { wx.setStorageSync('session', { openid, session_key }); cb(openid, session_key); }, complete: () => { wx.hideLoading(); } }) } }); }, }
2020-11-05 - 小程序中使用npm引入扩展组件库(举例:使用微信开发工具来加载扩展组件recycle-view)
微信小程序平台提供了一些扩展组件库,可以有效地解决一些特定问题。但是,对于没怎么接触过npm和微信开发者工具的同学来说,可能想通过npm来引用一个扩展组件库的过程并不是看上去那么容易,这里我把主要操作要点梳理一下。 注:1、以下操作仅在微信开发工具以及电脑命令窗口中进行; 2、本文主要解决用npm引入recycle-view的问题,至于如何使用recycle-view,还需参照官方文档。 1、在微信开发者工具中,点击详情-本地设置,勾选使用npm模块: [图片] 2、使用电脑的命令窗口打开miniprogram目录(小程序根目录,不包含云函数目录哈): 1)初始化npm:输入命令 npm init (如果该项目之前没用过npm,此步骤不可省略),然后在命令窗口中一路回车即可。 2)安装recycle-view:输入命令 npm install --save miniprogram-recycle-view 3、在微信开发者工具中,点击 工具-构建npm 4、在要引入页面的 .json文件中引用recycle-view和recycle-item: "usingComponents": { "recycle-view": "miniprogram-recycle-view/recycle-view", "recycle-item": "miniprogram-recycle-view/recycle-item" } 5、在要引入页面的 .wxml文件中就可以正常使用recycle-view了: 具体使用方式参考官方文档:https://github.com/wechat-miniprogram/recycle-view
2021-09-17 - 是否应在保险类目里增加一个合作开展互联网保险业务?
2019年11月2日、11月5日、11月10日, 分别萌保小程序版本在发布审核后,系统后台一直提示“你好,你的小程序涉及在线办理保险业务,请补充选择:金融业-保险类目” 现就该小程序申诉如下: 萌保为南京思十亦公司旗下微信小程序(AppID wxeefaab4233e03aa9)。南京思十亦公司与中盛国际保险经纪有限责任公司在银保监会进行了互联网保险销售资质备案,并在中保协进行了信息披露,披露结果及合作协议,合作模式如附件,目前银保监会已允许中盛国际在该平台进行保险销售,中盛是专业的保险中介公司,业务许可证如附件,中盛与南京思十亦公司进行合作,利用萌保开展互联网保险销售。 如需提供其他证明资料,还请指明。盼复。 另外,根据《中国保监会关于印发<互联网保险业务监管暂行办法>的通知》(原保监会官网http://xizang.circ.gov.cn/web/site0/tab5225/info3968308.htm),允许符合规定的保险机构通过第三方网络平台开展互联网保险业务;《通知》第二十三条:”中国保险行业协会依据法律法规及中国保监会的有关规定,对互联网保险业务进行自律管理。中国保险行业协会应在官方网站建立互联网保险信息披露专栏,对开展互联网保险业务的保险机构及其合作的第三方网络平台等信息进行披露,便于社会公众查询和监督。中国保监会官方网站同时对相关信息进行披露。“;"思十亦小程序是为具有合法的有保险产品销售资质的机构中盛经纪和保险公司提供技术支持,保险产品交易相关收款账号为保险机构,而非思十亦,其他要求也都符合监管要求。而且该”产品-销售平台“已经由保险机构报备保险监管部门,同时披露在互联网上,完全合法合规。" 综上,请微信考虑应在保险类目下,增加一个“与第三方平台开展互联网保险业务的类目”,添加银保监要求的最新审核规则,否则将严重影响很多涉及此业务的小程序主体的利益。 [图片] [图片][图片]
2019-11-11 - 一个RequestTask.abort()引发的悲剧
背景介绍 我司有一款健康记录的微信小程序产品,为了程序的健壮性,前辈开发者们在产品开发初期就引入了[代码]wx.request[代码]响应超时,自动重发的逻辑。本月产品迎来重大迭代,用户量开始增加。sentry中突然有一个错误日志断断续续出现,日志显示前端收到了接口的response,但是response中没有数据。而后端确认接口是有数据的,多么诡异的问题,唯一有迹可循的是,接口报错时,是接口超时没响应后重发的第二次请求 [图片] 开始排查 作为公司唯一的实习生,我荣获了周末加班排查这个bug的殊荣,打开我的大宝剑,错了,打开我的macbook,打开IDE,我发现了前辈们在接口重发逻辑中写的一个我不认识的东西 [代码]this.requestTask.abort() [代码] [图片] 马上打开官方文档查看 [图片] 文档让我心里慌的一比,没办法,只能自己去尝试 [图片] 举个栗子🌰 为了胜利我把重发的核心逻辑剥离出来放在一个单页面的小程序中,大概就是这样👇 [代码] data: { requestTask: null, retryRequest: null, retryCount: 0, timeout: 50 // 为了测试我把接口超时的时间改成了50ms }, test: function() { if(this.retryCount>3) { clearTimeout(this.retryRequest) return false } this.retryRequest = setTimeout(() => { this.retryCount++ this.requestTask.abort() // 中止上一个请求 this.test() // 调用自己发起下一次请求 }, 50) this.requestTask = wx.request({ url: 'api', success: (res) => { console.log('in success:', res) clearTimeout(this.retryRequest) }, fail: (res) => { console.log('in fail:', res) } }) } [代码] RequestTask.abort()分析 来,请大家猜猜下面红色的error是代码错误了还是中断成功了? [图片] 恭喜,这是请求中止成功啦。鼓掌!!! abort()函数执行成功(请求被中止),会进入fail回调和complete回调,如果errMsg == “request:fail abort”,就表示之前的请求被中止了。至于为什么会有红色的报错(没有任何意义),这是爱的鼓励,不要问为什么。 [图片] 重现问题 我一遍又一遍的点击着小程序开发者工具的编译按钮,发现在我点击十次之内,一定会出现重发多个请求后,有一个请求得到响应,其他请求被取消,而在success中打印res,发现里面的data不见了,就是下面这样👇 [图片] 推测一下 [图片] abort()函数是已经封装好的函数,是一个异步的函数 原先的逻辑中,abort被执行,但是并不知道请求是否已经彻底终止,就发起了下一个请求 [代码]this.requestTask.abort() this.test() [代码] 就在终止请求的时,下一个请求响应,底层开始处理请求的响应,上一次的终止逻辑被停了。最后,上一个来不及终止的请求也得到了响应,各种巧合导致其中一个得到响应的请求,success回调中打印不出来data 改动一下 在定时器setTimeout中执行requestTask.abort(),在fail的回调中,只有判断出res.errMsg === 'request:fail abort’的情况下,表示上一个请求已经彻底终止。重发下一次请求 [代码] test: function() { this.retryRequest = setTimeout(() => { this.requestTask.abort() }, 50) this.requestTask = wx.request({ url: 'api', success: (res) => { console.log(res) clearTimeout(this.retryRequest) }, fail: (res) => { if (res.errMsg === 'request:fail abort') this.test() }, complete: function (res) {}, }) } [代码] 鸣谢 [图片]
2019-10-28 - 升级开发者工具到最新,种种原因需要恢复旧版,旧版安装包找不到应急处理方法
刚需 新的开发者工具出来发现跟现有项目有兼容性问题。 而项目一天不能停,要急着修改上架,所以要恢复最新的开发者工具到旧版本 旧版本安装包没备份找不到了怎么办,2个方案: 解决方案 1、使用自带的回退功能 开发者工具菜单,回退功能,如果这里回退的版本不行或者不能正常回退,那么使用方案2 2、稳定版更新日志页面选择回退 如果是稳定版,可以在稳定版的更新日志页面找到对应旧版本的历史下载链接: 稳定版 Stable Build 更新日志 | 微信开放文档 https://developers.weixin.qq.com/miniprogram/dev/devtools/stable.html 3、根据规律找出历史版本下载链接 分析规律 找出指定旧版本的下载链接,直接打开链接下载旧版本。 应急处理的下载链接格式: [代码]https://servicewechat.com/wxa-dev-logic/download_redirect?type=x64&from=mpwiki&download_version=1021910120&version_type=1 [代码] 这个链接:后面版本号(1910120)改成你想要的版本就为所欲为的下载旧版本了。 版本号1910120的分拆:前6位代表发布的年月日(YYMMDD)格式后面的一位代表当天的第几个版本,从0开始 另外说说url里面的type是代表平台(x64/ia32/darwin) version_type代表版本类型:正式版/预览版/开发版(推测) 下载链接demo 经过上面分析后,可以得出1910120的X64版本下载链接为: https://servicewechat.com/wxa-dev-logic/download_redirect?type=x64&from=mpwiki&download_version=1021910120&version_type=1 MacOs版本下载链接为: https://servicewechat.com/wxa-dev-logic/download_redirect?type=darwin&from=mpwiki&download_version=1021910120&version_type=1
2020-09-24 - 如何实现一个6位数的密码输入框
背景: 因为公司业务调整需要做用户支付这一块 开发者需要在小程序上实现一个简单的6位数密码输入框 [图片] 首先想下如何实现该效果: 1.使用input覆盖在框上面,设置letter-spacing达到数字之间间距的效果,实现时发现在input组件上使用letter-spacing无效果 2.循环六个view模拟的框,光标使用动画模拟,一个隐藏的input,点击view框时触发input的Focus属性弹起键盘,同时模拟的光标展示出来,输入值后,input的value长度发生变化,设置光标位置以及模拟的密码小黑圆点 好了,废话不多数,咱们直接上手。 wxml [代码]<view class='container'> <!-- 模拟输入框 --> <view class='pay-box {{focusType ? "focus-border" : ""}}' bindtap="handleFocus" style='width: 604rpx;height: 98rpx'> <block wx:for="{{boxList}}" wx:key="{{index}}"> <view class='password-box {{index === 0 ? "b-l-n":""}}'> <view wx:if="{{(dataLength === item - 1)&& focusType}}" class="cursor"></view> <view wx:if="{{dataLength >= item}}" class="input-black-dot"></view> </view> </block> </view> <!-- 隐藏input框 --> <input value="{{input_value}}" focus="{{isFocus}}" maxlength="6" type="number" class='hidden-input' bindinput="handleSetData" bindfocus="handleUseFocus" bindblur="handleUseFocus" /> </view> [代码] wxss [代码]/* 第一个格子输入框 */ .container .b-l-n { border-left: none; } .pay-box { margin: 0 auto; display: flex; flex-direction: row; border-left: 1px solid #cfd4d3; } /* 支付密码框聚焦的时候 */ .focus-border { border-color: #0c8; } /* 单个格式样式(聚焦的时候) */ .password-box { flex: 1; border: 1px solid #0c8; margin-right: 10rpx; display: flex; align-items: center; justify-content: center; } /* 模拟光标 */ .cursor { width: 2rpx; height: 36rpx; background-color: #0c8; animation: focus 1.2s infinite; } /* 光标动画 */ @keyframes focus { from { opacity: 1; } to { opacity: 0; } } /* 模拟输入的password的黑点 */ .input-black-dot { width: 20rpx; height: 20rpx; background-color: #000; border-radius: 50%; } /* 输入框 */ .hidden-input { margin-top: 200rpx; position: relative; } [代码] JS [代码]Component({ data: { //输入框聚焦状态 isFocus: false, //输入框聚焦样式 是否自动获取焦点 focusType: true, valueData: '', //输入的值 dataLength: '', boxList: [1, 2, 3, 4, 5, 6] }, // 组件属性 properties: { }, // 组件方法 methods: { // 获得焦点时 handleUseFocus() { this.setData({ focusType: true }) }, // 失去焦点时 handleUseBlur() { this.setData({ focusType: false }) }, // 点击6个框聚焦 handleFocus() { this.setData({ isFocus: true }) }, // 获取输入框的值 handleSetData(e) { // 更新数据 this.setData({ dataLength: e.detail.value.length, valueData: e.detail.value }) // 当输入框的值等于6时(发起支付等...) if (e.detail.value.length === 6) { // 通知用户输入数字达到6位数可以发送接口校验密码是否正确 this.triggerEvent('initData', e.detail.value) } } } }) [代码] 实现方式很简单,有点小问题,还有一些后续准备做的优化点,等完善后上线后再来修改一波。 最后附上代码片段: https://developers.weixin.qq.com/s/8CtRqJmT7W8k
2020-07-06 - 小程序多个输入框自动聚焦时,键盘在切换的时候出现闪烁的情况
如下在身份证后6位的输入框中,没输入1位代码会自动的去切换输入框的焦点,这个时候出现虚拟键盘不停的下去又弹起来,体验的效果很不好,这个有解决的办法吗,还是小程序的设计bug,希望有人能帮忙看下,谢谢了! [图片]
2018-07-27 - wx.requestSubscribeMessage 小程序模版消息升级为订阅消息,
还要从那不久前的炎炎夏日说起, 一位苦逼的前端小妹, 为了加模版消息,熬了好几个加班夜, 动了几十个页面, 修改了几百个按钮, 终于把模版消息都全面埋雷, 不留任何死角. 也就过了才 1 2 3 4 5个月吧, 订阅消息一出. 我们的前端小妹, 那脸色、那眼神、我至今找不到一个合适的词语来形容(主要是笔者词穷) 下面还是主要来说说订阅消息吧, 不然对不起读者. 升级第一步: 注意订阅消息是有最低版本库要求的 (这个主要是需要产品和客户同步, 不是所有人都能订阅哦) 注意:iOS客户端7.0.6版本、Android客户端7.0.7版本之后的一次性订阅/长期订阅才支持多个模板消息,iOS客户端7.0.5版本、Android客户端7.0.6版本之前的一次订阅只支持一个模板消息 升级第二步: 干就完了 官方 api 地址: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/subscribe-message/wx.requestSubscribeMessage.html wx.requestSubscribeMessage(Object object) [图片] 撸起袖子就是干 小手一抖, 代码全有 [图片] 屏幕一点, 效果立显 [图片] 友情提示: 这里 tmplIds 用的是订阅消息 id 哦, 不要搞错咯 这里必须是在手机上才能看到效果哦 每次弹框, 只能配置最多 3 个订阅消息哦 如果勾选了: “总是保持以上选择, 不再询问” , 真的就是“此生不复相见哦”, 删除了小程序也不管用哦 由于弹出的 3 个订阅消息, 是可以单独勾选, 就会出现如果某 1 个配置的已经“总是保持以上选择, 不再询问”. 那么弹框只会显示其他两个哦, 属于正常情况. 不要以为是哪里错了哈. 并且返回的结果还是 3 个(不要晕哈, 说的啰嗦, 其实不难理解) 小框框弹出来了, 返回也很顺利拿到了, 抿一口手边的枸杞菊花茶, 是不是很舒服? 上面说到了, “总是保持以上选择, 不再询问” , 就是“此生不复相见哦”, 那么如果之前手贱, 点了拒绝. 那如何才能重新订阅呢? 小生也是研究了的: 操作步骤: 右上角点点点, 》 设置 》订阅消息 效果一目了然 [图片] 前方高能: 设置里的订阅消息, 它此生的标签是 “总是保持以上选择, 不再询问”, 不管是你允许还是拒绝, 都不会在弹框里再看到 写在最后 提一个更苦逼的事情, 记得把之前为获取 formid 而写的代码, 统统删掉 写在最最后 给不给点赞? 不点我下一篇还问 未完待续… 以下是补充哦, 持续关注订阅消息 一: 一个模版, 在首页勾选了“总是保持以上选择, 不再询问”按钮. 在别的页面也将不会有弹框. 你懂的, 在产品角度这个是很重要、很关键的交互需求 二: 同意次数是可以累计的. 也就是说, 一个模版, 客户A点击了 10 次允许发送消息. 那我们就可以给他发 10 次模版消息提醒 三: 一次拒绝, 是不会清除之前同意所累计的次数的 这个是针对有网友说: “点一次同意, 再点击一次拒绝,是收不到消息的”. 实践证明: 点一次同意, 就能发一次消息, 后面点击拒绝, 不影响之前点击同意的 四: 有网友问: ”一个弹框有三个模版, 全都勾选并同意. 可以发几条消息? “ 很明显是三个模版每个可以发一次. 这个也是验证了的 干活!! 是不是满满的都是干活!
2019-12-09 - 针对新手很容易出现理解误区的微信小程序订阅消息模块
1. 写在前面 微信小程序下架了模板消息功能,取而代之的是订阅消息功能。这个订阅消息目前又分为「一次性订阅」和「永久订阅」。使用订阅消息也有一段时间了,感觉对新手订阅消息很容易让新开发者进入一个理解的误区,这里觉得有必要说出来 2. 理解误区 很多新手认为,只要用户勾选了小程序端订阅消息弹出时底部的「总是保持以上选择…」后,就可以「为所欲为」的不限次数的推送订阅消息给用户了。如下图: [图片] 3. 正确理解 如果你使用的「一次性订阅」模板(目前发现绝大多数开发者都是只能用一次性的,因为永久性的订阅消息申请门槛太高),那么勾选底部的「总是…」这个并不代表以后可以直接推送了。官方原话wx.requestSubscribeMessage的介绍里是这样写的: 3.1 官方说明 wx.requestSubscribeMessage(Object object) 基础库 2.8.2 开始支持,低版本需做兼容处理。 调起客户端小程序订阅消息界面,返回用户订阅消息的操作结果。当用户勾选了订阅面板中的“总是保持以上选择,不再询问”时,模板消息会被添加到用户的小程序设置页,通过 wx.getSetting 接口可获取用户对相关模板消息的订阅状态。 注意事项 一次性模板 id 和永久模板 id 不可同时使用。 低版本基础库2.4.4~2.8.3 已支持订阅消息接口调用,仅支持传入一个一次性 tmplId / 永久 tmplId。 2.8.2 版本开始,用户发生点击行为或者发起支付回调后,才可以调起订阅消息界面。 2.10.0 版本开始,开发版和体验版小程序将禁止使用模板消息 fomrId。 3.2 重点关注 这里重点关注第7条:「用户发生点击行为或者发起支付回调后,才可以调起订阅消息界面。」这就意味着你需要在用户主动点击某个组件是触发调用wx.requestSubscribeMessage方法再次订阅,订阅后,你才可以「为所欲为」推送一次模板消息,注意只能一次。下次再想推送时,需要用户再次点击触发wx.requestSubscribeMessage。 4. 破局方案 目前订阅消息功能,就是这么个情况,所以针对这个情况的替代方案有以下 4.1 永久性订阅消息 如果能达到申请「永久性订阅」消息的模板的门槛,那自然是极好的,直接用永久性模板「为所欲为」。 4.2 使用服务号的模板消息替代 比较常用的是使用公众号服务号的模板消息代替小程序的订阅消息功能,公众号的模板消息功能限制就比订阅号好多了,基本上可以「为所欲为」的推送。但是这个方案有个致命的运营成本:必须要用户关注公众号,还有小程序要跟公众号同一主体并绑定在开放平台下。同时开发成本有所增加,要采用unionId机制来打通小程序跟公众号的openId。这个具体的实现方案,大家有兴趣的话可以讨论下。笔者目前就是用这种方案的。 5. 几个注意点 5.1 官方提示 订阅消息如果选择选择‘总是保持以上选择,"不再询问"后的设置问题: 目前是选择‘总是保持以上选择,"不再询问"后,可以在设置中开启或拒绝接收,但不会再次拉起授权弹窗 6. 长期性订阅消息 请参考官方最新文档: 小程序模板消息能力调整通知 | 微信开放社区 https://developers.weixin.qq.com/community/develop/doc/00008a8a7d8310b6bf4975b635a401 长期性订阅消息 一次性订阅消息可满足小程序的大部分服务场景需求,但线下公共服务领域存在一次性订阅无法满足的场景,如航班延误,需根据航班实时动态来多次发送消息提醒。为便于服务,我们提供了长期性订阅消息,用户订阅一次后,开发者可长期下发多条消息。 目前长期性订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放,后期将逐步支持到其他线下公共服务业务。 7.题外话 鉴于被戴上各种「刷赞,冲级,让社区点赞“通货膨胀”」等等一些恶毒字眼(最近多了个职业回复的「雅称」),各种帽子戴得,做一个开发爱好者积极分享和解决各种问题太难了,姑且不论咱写一篇文章需要截图多少,单单排版就得废掉俺多少时间哈,很受伤,所以本人决定在微信开放者社区封笔。你看到是俺最后一篇发表在微信开放社区的文章。如果你想继续查看俺的一些文章可以私聊我。我会在其他平台保持继续创作。bye-bye~ 8. 最最重要的来了 看完后觉得有用记得点赞~~ ↓点赞处↓
2020-09-04 - 有什么方法让onLaunch里面的ajax运行运行完 再运行各个页面里面的ajax?
有什么方法让onLaunch里面的ajax运行运行完 再运行各个页面里面的ajax? 如果实在没办法 只能把 onloaunch里面的放的ajax放到这个页面里面了
2019-10-29 - 小程序不同页面的异步回调,callback和promise的使用讲解
发个扫盲贴,大神请绕道。最近好多同学问我如何再请求数据成功后直接使用数据。我们通常的做法就是在请求成功后,再调用我们定义的方法,进而使用数据。如下代码 [代码] onLoad() { let that=this wx.cloud.database().collection("users").get({ success(res) { that.setData(res.data) }, fail(res) { } }) }, showData(dataList) { //.........做数据处理 }, [代码] 我们这样写其实也没什么不对,但是如果数据请求和使用是在两个不同的页面呢。 比如我们在app.js里请求位置,获取用户信息。然后在首页index.js里要使用这些数据,那么我们这么写就有问题了。下面就来教大家两种方式来很好的解决这个问题。 一,通过callback回调。 先看下代码,然后我再具体给大家讲解下原理。 app.js里定义如下方法 [图片] 然后再index.js 里这么使用 [图片] 这时候,其实就可以看到了,我们在首页index.js里调用了app.js里的请求数据的方法,并且可以在index.js里直接使用数据。 原理讲解 原理其实很简单,就是我们在app.js里的获取数据的方法里定义一个参数。而这个参数和普通参数唯一不同的地方,就是这个参数是个function方法 [图片] 我们上图的callback参数,其实就是下图 function(result){} [图片] 把function方法作为一个参数传递进去的目的,就是为了下面的回调。 [图片] 我们这个callBack参数,可以在请求数据成功或者失败的时候作为一个方法调用。这样就可以把请求到的数据,回传回去了。 讲的有点绕,不知道大家有没有被绕晕。这在java开发中,其实就相当于监听者模式。说白了就是在一个页面里监听另外一个页面的动作,如获取数据成功,当监听到数据获取成功这个动作以后,就可以直接把数据回传回来了。 如果觉得这种方法有点绕,不好使用,我们就用下面的这个第二种方式。 二,promise promise的好处就是可以不用那个层层传递,不用那么绕。 还是先看代码,后面结合代码给大家讲下原理 app.js里定义如下方法 [图片] index.js里这么调用 [图片] 用句通俗的话说,就是通过promise让我们的数据请求和使用看上去是在同一个页面完成。怎么实现的呢 1,在app.js里把数据请求封装到promise里,然后把promise返回到我们的首页index.js里 2,在首页里使用这个promise 实现数据的获取和使用。 在具体些就是下面这几步 promise基础用法 [图片] 1、new 一个Promise对象 2、请求数据的异步代码写在promise的函数中 3、promise接受两个参数,一个resolve(已成功success),一个reject(已失败fail) 4、promise有三种状态pendding(进行中,当new了promise就是pendding的状态)、fulfilled(已成功)、rejected(已失败),当成功的时候调用resolve将状态改为已成功,当失败的时候调用reject将状态改为已失败,一旦状态发生改变之后,状态就凝固了,后面就无法改变状态了,成功会将成功的数据返回,失败会将失败的信息返回。 5、在需要获取数据的地方通过promise.then()的方式获取,这里面接受两个参数,都是匿名函数,第一个是接受成功的函数,第二个是失败时候的函数 [图片] 好了,到这里我们两种不同页面的异步回调就给大家将完了。代码就完整的给大家贴出来吧,方便大家日后使用 app.js [代码]//app.js App({ //第二种,通过promise promiseGetData() { let promise = new Promise(function(success, fail) { wx.cloud.database().collection("users").get({ success(res) { success(res) }, fail(res) { fail(res) } }) }) return promise; }, //第一种,通过callback的方式来实现回调 callBackGetData(callBack) { wx.cloud.database().collection("users").get({ success(res) { callBack(res) }, fail(res) { callBack(res) } }) }, }) [代码] index.js [代码]// 异步调用,callback const app = getApp() Page({ clickBtn() { //按钮点击 //callback方式 // app.callBackGetData(function(result) { // console.log("dataList", result) // }) //promise方法 let promise = app.promiseGetData() promise.then((res) => { //获取成功的结果,res中存着获取成功时的数据 console.log("成功", res) }, (error) => { // 获取数据失败时 console.log("失败", error) }) }, }) [代码]
2019-11-14 - 【周刊-1】三年大厂面试官-面试题精选及答案
前言 在阿里和腾讯工作了6年,当了3年的前端面试官,把期间我和我的同事常问的面试题和答案汇总在我 Github 的 Weekly-FE-Interview 中。希望对大家有所帮助。 如果你在bat面试的时候遇到了什么不懂的问题,欢迎给我提issue,我会把题目汇总并将面试要点和答案写好放在周刊里,大家一起共同进步和成长,助力大家进入自己理想的企业。 项目地址是:https://github.com/airuikun/Weekly-FE-Interview 常见面试题精选 以下是十道大厂一面的时候常见的面试题,如果全部理解并且弄透,在一面或者电话面的时候基本上能中1~2题。小伙伴可以先不急着看答案,先自己尝试着思考一下和自己实现一下,然后再看答案。 第 1 题:http的状态码中,499是什么?如何出现499,如何排查跟解决 解析:第 1 题:http的状态码中,499是什么?如何出现499,如何排查跟解决 第 2 题:讲解一下HTTPS的工作原理 解析:第 2 题:讲解一下HTTPS的工作原理 第 3 题:讲解一下https对称加密和非对称加密。 解析:第 3 题:讲解一下https对称加密和非对称加密 第 4 题:如何遍历一个dom树 解析:第 4 题:如何遍历一个dom树 第 5 题:new操作符都做了什么 解析:第 5 题:new操作符都做了什么 第 6 题:手写代码,简单实现call 解析:第 6 题:手写代码,简单实现call 第 7 题:手写代码,简单实现apply 解析:第 7 题:手写代码,简单实现apply 第 8 题:手写代码,简单实现bind 解析:第 8 题:手写代码,简单实现bind 第 9 题: 简单实现项目代码按需加载,例如import { Button } from ‘antd’,打包的时候只打包button 解析:第 9 题: 简单实现项目代码按需加载,例如import { Button } from ‘antd’,打包的时候只打包button 第 10 题:简单手写实现promise 解析:第 10 题:简单手写实现promise 结语 本人还写了一些前端进阶知识的文章,如果觉得不错可以点个star。 blog项目地址是:https://github.com/airuikun/blog 我是小蝌蚪,腾讯高级前端工程师,跟着我一起每周攻克几个前端技术难点。希望在小伙伴前端进阶的路上有所帮助,助力大家进入自己理想的企业。
2019-04-08 - 榛子应用市场-你需要的毕业微信小程序都在这
智能垃圾回收小程序 智能垃圾回收小程序,支持拍照识别、语音录入识别,包含垃圾分类题库测试。 下载地址: http://market.zhenzikj.com/detail/103.html [图片][图片][图片][图片][图片][图片][图片] 通用答题小程序 通用答题小程序,支持多种题库,可以设置答题场景。 支持答题模式和背题模式 支持模拟答题场景,可自定义答题时间和答题数量 左右滑动就可以进入下一题,操作灵活 可以作为商业使用,也可以作为学生的毕业设计使用,提供源码。 新增了背题模式。 下载: http://market.zhenzikj.com/detail/105.html [图片][图片][图片][图片][图片][图片][图片][图片][图片] 外卖点餐小程序 小程序+java后台 点餐外卖小程序。 适用于线下餐厅支持外卖。 也可用于毕业设计 下载: http://market.zhenzikj.com/detail/111.html [图片][图片][图片][图片][图片]
2020-03-13 - 解决问题,解决问题,不要互相伤害 @官方的进
关于2.4基础库小程序无法跳转的问题,看看有多少开发者遇到这个问题了,就不能正面的出来解决一下问题么?别敷衍行么。麻烦看看下面的问题,赶紧解决一下,OK?本帖子将收集有关跳转的所有问题,我想看看官方到底什么时候能出面解决。 https://developers.weixin.qq.com/community/develop/doc/0006e8622e0c208a41a725a9d55c00 https://developers.weixin.qq.com/community/develop/doc/00080a5450c3307232a7ae68756800 https://developers.weixin.qq.com/community/develop/doc/000aec78a44c10ae6ba76cc8d51c00?highLine=%25E5%25B0%258F%25E7%25A8%258B%25E5%25BA%258F%25E8%25B7%25B3%25E8%25BD%25AC https://developers.weixin.qq.com/community/develop/doc/000ca8ce818fc8ce69a7ddc6e56800?highLine=%25E5%25B0%258F%25E7%25A8%258B%25E5%25BA%258F%25E8%25B7%25B3%25E8%25BD%25AC https://developers.weixin.qq.com/community/develop/doc/0000c09062c258cc46a7d9d8856000?highLine=%25E5%25B0%258F%25E7%25A8%258B%25E5%25BA%258F%25E8%25B7%25B3%25E8%25BD%25AC https://developers.weixin.qq.com/community/develop/doc/0006e8622e0c208a41a725a9d55c00?highLine=%25E5%25B0%258F%25E7%25A8%258B%25E5%25BA%258F%25E8%25B7%25B3%25E8%25BD%25AC https://developers.weixin.qq.com/community/develop/doc/000826d9984e38283ca73417a5b000?highLine=%25E5%25B0%258F%25E7%25A8%258B%25E5%25BA%258F%25E8%25B7%25B3%25E8%25BD%25AC https://developers.weixin.qq.com/community/develop/doc/00020487ba8450e73ba7f5a635d000?highLine=%25E5%25B0%258F%25E7%25A8%258B%25E5%25BA%258F%25E8%25B7%25B3%25E8%25BD%25AC https://developers.weixin.qq.com/community/develop/doc/00080a5450c3307232a7ae68756800?highLine=%25E5%25B0%258F%25E7%25A8%258B%25E5%25BA%258F%25E8%25B7%25B3%25E8%25BD%25AC https://developers.weixin.qq.com/community/develop/doc/000a0c5c6786f0b82aa7d7f5159400?highLine=%25E5%25B0%258F%25E7%25A8%258B%25E5%25BA%258F%25E8%25B7%25B3%25E8%25BD%25AC https://developers.weixin.qq.com/community/develop/doc/00064606b78288b421a77faff57800?highLine=%25E5%25B0%258F%25E7%25A8%258B%25E5%25BA%258F%25E8%25B7%25B3%25E8%25BD%25AC https://developers.weixin.qq.com/community/develop/doc/00048cd0a786703120a76a29e5b400?highLine=%25E5%25B0%258F%25E7%25A8%258B%25E5%25BA%258F%25E8%25B7%25B3%25E8%25BD%25AC
2018-11-12