- ad广告放在自义组件里面,第一次ad是100%,第二次300px
ad广告组件在page相互切换没有问题。但是在多个自定义组件切换(自定义组件切换的方式为diplay:none或者block)时会第一次会100%,第二次为300px; 基础库版本 2.7.0至2.8.3.问题应该是出现在ad放在自定义组件里面时出现。 第一次正常[图片] 第二次不正常 [图片]
2019-10-08 - 小打卡|如何组件化拆分一个200+页面的小程序
大家好,我是小打卡的前端唐驰。刚才金轩正同学分享了基于原生小程序底层架构,在此基础上我为大家分享下如何拆分一个200+页面的小程序,主要通过以下几点来聊一聊小打卡在组件化路上的一些实践 1.背景 2.组件与方案 3.组件间通讯 4.基于组件我们做了哪些事 [图片] [图片] 1. 其实一开始小打卡是没有引入组件化的,因为微信最开始是不支持组件化的。当时js代码已经4k+行了,各种功能代码,有用的没有用的,不知道干什么的代码就躺在那里,一动不动。举个例子,一个头像点击跳转的逻辑搜索了下,遍布在各个页面。修改起来可想而知的胆战心惊。另一个原因就是当时由于业务功能直线上升,很快我们就遇到了代码包超包了。在微信还没有实现分包之前,我们就只能一个一个页面的去review剔除代码,效率极低。这也是促成我们决定寻求出路的原因之一。可是删代码删功能是不能解决问题,期间我们也考虑过h5的方式,跑了demo之后却发现h5方式的多次渲染, 与加载首页白屏,尽管有各种服务端渲染方案,但是我们一致觉得为了用户体验,放弃了。 [图片] 2. 对于小打卡来说,我们不能再任由项目裸奔了,需要一种开发方式来进行约束,主要是有几个诉求: 在之前的项目上,为了方便。功能与功能之间的耦合程度极其的高,各种为了使用方便而随意修改某一个方法。 1.降低页面上各个功能点的耦合程度 我们不希望同一个功能点同样的代码在页面肆意copy,这样带来了极高的维护成本。以至后面无法维护。并且功能的复用不希望是copy,前端与后端不同的是不仅是单单的逻辑复用、更有布局、样式等。 2.提供代码的可复用性、可维护性 对于一个程序员来说,如果你打开一个代码文件。映入眼帘的是密密麻麻的代码,行数达到好几千K行,我相信大家的第一反应是抗拒的,更别说去修改代码,天知道会改出什么问题。 3.降低单一文件的复杂度 4.如果是公共功能的化我们还希望它能够有自己的作用域,保持自己的独立性。 [图片] 3. 根据以上几点,我们用一个页面举例,如何去拆分一个页面,首先我们需要有以下几点认识: 决定一个页面如何组件化的前提是该页面的功能是否是有全局都需要的功能模块 功能模块是否需要与页面其他模块强耦合 单个功能模块逻辑是否过于复杂(占用代码空间过大)——>单纯是为了页面代码的可读性。 不是全拆成组件就是最好的,不能为了组件而组件化 [图片] 4. 说了这么多,其实我们应该首先应该了解下,组件的特性? 专一性(一个组件只干一件事情,或者某一类事情。)功能的高度内聚 比如说右侧的feed集上的头像、它是一个组件、就负责显示头像跟跳转,其他的事它都不参与 可配置(能够适应通过设置属性值的方式来输出不同的东西)输入影响部分输出 然后我们同时可以设置头像组件上的size属性来设置头像在不同页面下的大小样式 生命周期(组件可以在自身或者说所在页面的生命周期内可以做不同的事情)比如可以在组件生成的时候进行数的初始化、属性值的类型校验、组件销毁时并同时销毁定时器等其他任务 事件传递 (既然要让组件与页面保持独立性,那么组件与页面的通讯交互就得需要一个标准) 右侧的feed组件其实是一个组件集合、我们通过组合不同的组件然后就形成了feed组件。就跟搭积木一样、只需要引入组件就行了。特别方便。 [图片] 5. 说到组件,那么小程序早期的不支持自定义组件开发这就很让人头疼、同样的feed组件我们经历了几乎三个版本的大改动、从最开始的直接写在页面里,后台使用template方式、再到后来的自定义组件方式。所以我们的演进步骤就成了page->template->component, 这儿列了一个表格对比了下几种组件化方式的对比。 可以看到,include的方式其实是最鸡肋的,include的方式其实实际意义上我理解成更多的是代码的切割,并且还不能将(template、wxs)分出去、所以这种方式我们直接pass掉了, 而template的方式其实是我们曾经主力使用的方式、到现在我们也还在使用、相对于include来说,template有了独立的作用域、虽然css、跟js还是与页面共享的。但是已经可以做一些比较简单的事情了。 对于component来说,完完全全的组件,满足了组件的所有要求。 [图片] 6. 先说说template的方式吧,举个列子,这个是我们的使用template构建的头像组件。跟写页面的方式很像、同样是js、wxss、wxml组成。用名称来命名。但是由于微信当时没有很方的方式去引用这些文件,或者说没有一种方法可以打包供我们很方便的使用。但是比起之前直接copy代码的方式、这样通过引用的方式使用其实感觉已经好了很多了。 [图片] [图片] 7. 具体的使用方式我画了张图,对应组件内文件与页面文件的对应方式、这里对于js的引用其实我们是做了一些小动作, 我们在调用Page方法前做了一次page方法与组件方法的check,因为在page代码里我们不能保证所有的方法名不会跟组件内的方法名不会冲突,所以我们做了这个一个检查、 然后mix函数还做了另一个事情就是将page方法与组件方法合并。然后对于mix函数其实我们还可以做很多事情、、比如规范生命周期回调函数放在一个对象内,然后我们自己定义的方法放在另一个对象里,就跟vue一样。 But,在经历了一段template组件化的时间后,我们又觉得这个方式还是有点烂,为什么呢?在使用时仍然不能避免引入众多的文件、虽然我们对js文件做了处理,但是wxss的样式仍然会被污染、js与page仍然共享作用域。并不能成为一个真正的标准组件。好在后来,微信上了自定义组件的功能,接下来聊聊这个标准的微信自定义组件吧。 8. 微信提供了自定义组件的功能后我们也第一时间跟进了,相对于template这种方式来说,现在是真正的独立于页面存在。使用也比之前更为方便与简洁,右图是我们对component的一个项目目录划分。我们将component划分为了公共组件与页面组件、为什么会有页面组件, 1.是为了降低页面代码的复杂度 2.为了好看。 公共组件就不说了,一定是最基础、最通用的组件。 [图片] 9. 转向component方式后有一个问题逐渐便凸显出来了,由于组件的独立作用域,组件间的通讯就成了一个问题,接下来聊一聊组件的事件传递。微信最开始的时候提供了一种triggerEvent的方式,可是这样的方式似乎并不能满足我们某些场景下的需求。后来又提供了page下selectComponent方法来直接操作组件内部的属性与方法。然后还有就是基于我们自己的事件广播机制。这几种方式构成了小打卡现目前最主要的组件与page、组件与组件间的数据交互方式 [图片] 10. 先来说说triggerEvent模式,微信在自定义组件上可以自定义监听函数。我们在组件内将需要向外抛出的事件统一通过this.triggerEvent(‘invoke’,{handler:’fun’,data:{}})这个方法来执行。其中invoke对应了我们绑定在组件标签上的监听函数。而将需要外部执行的方法与数据通过数据的方式传给监听函数。而在page上面我通过统一的监听回调函数去自动执行需要执行的方法、这里的trigger与event都不要我们去手写在组件与page创建的时候底层就已经帮我们预置了,我们只需要关注业务开发就行。这是对于一部分需要page与组件交互的模式。而对于我们想直接操作组件方法而不需要反馈的模式就得使用selectComponent的模式 [图片] 11. 一个简单的列子:全局的toast组件。在需要弹出toast的时候我们想直接调用就行、不用在通过传值给组件、然后由组件来执行显示或隐藏。这类组件我们在组件目录里新增了一个lib的文件。在page里只需要引入这个lib文件然后就可以直接调用toast组件。lib主要是对this.selectCompent与执行逻辑的一个封装。 [图片] 12. 事件发布订阅模式:基于底层的eventBus。简化后我们用在了组件与组件之间的通讯上、特点是简单。 [图片] 13. 解决了组件间的通讯问题,可是对于公共组件的引用仍然让我们觉得麻烦与不畅快、所以我们构建了全局通用模版、它是干什么的呢。它提供给了一些基础的全局组件、比如自定义导航头、toast、loading等等。小打卡所有的页面都通过slot的方式插入到这个模版组件x-page下面。这样就解决了我们需要在每个页面引入公共组件的问题。另一个问题使用自定义导航栏的时定位起点会有状态栏下移动到屏幕左上方。会造成布局的错误。通过x-page可以很好解决这个问题而不用重新布局。并且通信问题也不用担心,都是由x-page组件作为中台来对内对外进行分发与执行。 [图片] [图片] [图片] 14. 通过以上小打卡的开发模式就基本形成。要做的事情还有很多,更多组件的玩儿法,对于现在或者将来我们正在做的。 是构建小打卡的组件与基础sdk的仓库。 拆分组件开发与业务开发。 通过npm包管理的方式来应对越来越多的小程序平台的开发。 或者通过形成小程序插件的方式供其他小伙伴使用。 [图片] [图片] 以上就是我今天分享的内容。谢谢。
2019-04-26 - 关于微信安卓端网页字体适配的通知
为了提供给用户更好的阅读体验,微信安卓版 7.0.10 版本起,网页的字体会跟随微信设置里的字体大小更改而变化。 若调整字体变大或变小后,部分未适配网页的排版会出现显示错乱,建议未进行适配的开发者尽快完成对“ 字体大小” 的适配。 查看网页在字体不同大小下展示效果的方法: 方法1:"设置">"通用">“字体大小">进行字体大小修改后查看对应网页显示效果。 方法2:在微信内访问对应网页右上角”…">底部菜单栏选择调整字体">进行字体大小修改后查看对应网页显示效果。 另外,对于现有的显示问题,我们提供以下方案让开发者临时将字体还原标准大小。同时,开发者可以在页面中提示用户在右上角”…”更多菜单中修改字体到合适的大小。 下列方案可以将字体还原标准大小,但我们仍然建议后续做字体适配来提高用户的阅读体验。 『字体还原标准大小』方案: 我们提供了一个 JSAPI 用于设置字体大小,只需将字体大小等级设置为 2 (标准)即可,代码示例如下: document.addEventListener("WeixinJSBridgeReady", function () { WeixinJSBridge.invoke("setFontSizeCallback", { fontSize: '2' }); }, false); 此外,若页面是用 rem 单位进行排版的(目前该做法更容易导致页面不可用),可以反向重置 font-size 的数值达到还原字体标准大小的目的,此方法在效果上也比较理想。代码示例如下: // 以下代码思路来源网络。同时代码放在 body 标签开头位置效果最佳 var $dom = document.createElement('div'); $dom.style = 'font-size: 10px'; document.body.appendChild($dom); // 计算出放大后的字体 var scaledFontSize = parseInt(window.getComputedStyle($dom, null).getPropertyValue('font-size')); document.body.appendChild($dom); // 计算原字体和放大后字体的比例 var scaleFactor = 10 / scaledFontSize; // 取 html 元素的字体大小 var originRootFontSize = parseInt(window.getComputedStyle(document.documentElement, null).getPropertyValue('font-size')); // 由于设置 font-size 后实际会变大,故 font-size 需设置为更小一级 document.documentElement.style.fontSize = originRootFontSize * scaleFactor * scaleFactor + 'px';
2020-01-14 - 小程序订阅消息开发指南
2019年10月12日微信开放了小程序订阅消息的功能。按官方的说法,目前的模板消息在实现小程序服务闭环上存在缺陷: 1. 部分开发者在用户无预期或未进行服务的情况下发送与用户无关的消息,对用户产生了骚扰;2. 模板消息需在用户访问小程序后的 7 天内下发,不能满足部分业务的时间要求模板消息确实存在上述的硬伤,不利于小程序的用户留存和用户体验。为了解决这些问题,微信官方推出了用户订阅消息功能。我在微慕专业版上加了订阅消息的功能,并验证了这个功能。这个功能是否能都达到官方的预期,这个我感觉不那么乐观。这里我先说我的感受:目前的订阅消息还不完善,后续还有很大的优化空间。 目前,官方只开放了“一次性订阅消息”,尚未开放“长期性订阅消息”,因此我只尝试了“一次性订阅消息”。 一次性订阅消息:用于解决用户使用小程序后,后续服务环节的通知问题。用户自主订阅后,开发者可不限时间地下发一条对应的服务消息;每条消息可单独订阅或退订。 订阅消息推送位置:服务通知 订阅消息下发条件:用户自主订阅 订阅消息卡片跳转能力:点击查看详情可跳转至该小程序的页面 以下我简单说明订阅消息的开发过程和使用体验。 一.订阅消息的开发1.获取订阅消息的模板ID 在微信小程序的管理后台,在左侧“功能”菜单,选择“订阅消息”,然后点击“添加” [图片] 然后选择你需要的消息模板,并配置关键词。 [图片] 配置完成后,如下图所示。 [图片] 值得关注的是,在配置好的模板详情页面里的“详细内容”很重要,这个就是开发订阅消息时需要遵循的消息格式,这个格式和模板消息有细微的差别 根据微慕小程序的需要,我选用了“新的评论提醒”和“内容更新提醒”这两个消息模版。前者用于提醒发表话题或文章的作者,有新的话题或文章评论,增强作者与读者之间的交流互动;后者是提醒订阅用户,小程序有新的文章发布,引导用户回归小程序。 订阅消息申请模板的时候,需要选择所属类目,只能选择当前小程序相关的类目模板,对于模板消息不需要选择对应类目。如果删除小程序类目,就会把订阅消息模板一起删除。因此删除类目要小心谨慎。 [图片] 2.触发用户订阅,获取下发的权限 触发用户订阅,微信小程序提供的api是: [代码]wx.requestSubscribeMessage[代码],用户发生点击行为或者发起支付回调后,才可以调起订阅消息界面。 注意:微信小程序开发工具尚不支持此功能,在开发工具触发订阅的api,会提示: requestSubscribeMessage:fail 开发者工具暂时不支持此 API 调试,请使用真机进行开发 调用api的代码示例如下: [代码]wx.requestSubscribeMessage({[代码] [代码]tmplIds: ["模板A","模板B"],[代码] [代码]success: function (res) {[代码] [代码]//成功[代码] [代码]},[代码] [代码]fail(err) {[代码] [代码]//失败[代码] [代码]console.error(err);[代码] [代码]}[代码] [代码]})[代码] wx.requestSubscribeMessage(Object object) 的回调函数[代码]object.success [代码]参数有两个:errMsg和TEMPLATE_ID; 接口调用成功时errMsg值为’requestSubscribeMessage:ok’。TEMPLATE_ID是动态的键,即模板id,值包括’accept’、’reject’、’ban’。’accept’表示用户同意订阅该条id对应的模板消息,’reject’表示用户拒绝订阅该条id对应的模板消息,’ban’表示已被后台封禁。例如 { errMsg: “requestSubscribeMessage:ok”, zun-LzcQyW-edafCVvzPkK4de2Rllr1fFpw2A_x0oXE: “accept”} 表示用户同意订阅zun-LzcQyW-edafCVvzPkK4de2Rllr1fFpw2A_x0oXE这条消息。 个人觉得这个动态键不是特别合理,代码处理起来有些麻烦,如果改成静态键的json格式比较方便处理,例如: [代码]{[代码] [代码] errMsg:"requestSubscribeMessage:ok",[代码] [代码] result: [[代码] [代码] { templateId:"zun-LzcQyW-edafCVvzPkK4de2Rllr1fFpw2A_x0oXE",[代码] [代码]status:"accept"[代码] [代码]}[代码] [代码] ][代码] [代码]}[代码] 在手机上调用此api方法会调出订阅消息的界面,如下图所示: [图片] 关于这个订阅消息的授权有几点要注意: 1) 在确认提示框里,如果用户选择“取消”表示拒绝(取消)订阅消息,选择“允许”表示用户订阅一次消息。 2) 如果用户不勾选“总是保持以上选择,不再询问”,那么每次用户触发都会弹出提示框。 3) 如果用户勾选“总是保持以上选择,不再询问”,那么将再也不会唤起这个对话框。同时,如果选择“取消”,那么以后每次调用这个api的时候,都会自动拒绝;如果选择“允许”,那么以后每次调用此api,都会自动允许授权。 目前小程序没有提供获取用户是否授权订阅消息的方法。通过wx.openSetting 方法无法获取用户是否授权消息订阅的信息,scope 列表没有订阅消息的内容。 如果想从自动拒绝转换到自动自动运行,需要打开小程序的设置去配置。设置方法:点击小程序右上角的三个点,打开如下对话框 [图片] 然后选择“设置”,在设置项里选择“订阅消息” [图片] [图片] 4)对于同一种消息,用户可以订阅多次,订阅多少次,就会收到多少次订阅消息,这个订阅次数是否有上限,官方没有说明,初步判断是不限的。但是,微信不会提供订阅的次数,因此需要在小程序的后端服务里存储用户订阅的次数。因此,我在微慕小程序专业版里,提供了一个给用户多次订阅的设置,并记录用户订阅的次数。 [图片] 如果用户需要某个消息服务,可以订阅多次,当然也可以在点击“订阅”的对话框里选择“取消”,“取消”一次也就减少一次订阅。 5)对于支付的场景,也需要用户确认是否订阅,这个我觉得不合理,支付后给用户一个订单推送消息应该是刚性需求,不需要再询问一遍用户是否订阅。 2.调用接口下发订阅消息 订阅消息下发的接口是小程序后台服务端调用:subscribeMessage.send,此方法类似下发模板消息的方法,详细调用说明见参考官方的链接: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html 订阅消息的下发接口方法和模板消息稍有不同, 模板消息的json格式如下 [代码]"data": {[代码] [代码]"keyword1": {[代码] [代码]"value": "内容1",[代码] [代码]"color": "#000"[代码] [代码]},[代码] [代码]"keyword2": {[代码] [代码]"value": "内容2",[代码] [代码]"color": "#000"[代码] [代码]}[代码] [代码]}[代码] 而订阅消息的json格式如下: [代码]"data": {[代码] [代码]"thing1": {[代码] [代码]"value": "内容"[代码] [代码]},[代码] [代码]"number2": {[代码] [代码]"value": 20[代码] [代码]}[代码] 订阅消息的字段key是和数据类型有关,value的参数需要严格按照设置的类型提交,如果不按类型提交,会导致发送失败。同时如果是文本型的内容,字数也有限制,超过限制也会发送失败,但具体字数是多少,官方没有给出,同时中英文混合计算的长度也有差异,据我目前测试25个中文字符是可以的。希望官方能给出具体的字符长度限制的明确数字。 如果调用下发的次数大于用户的订阅次数,调用接口下发订阅消息会返回失败。报如下错误 [图片] 二.订阅消息使用心得1.订阅消息虽然把订阅的授权的交给了用户,但是也增加了用户使用难度,同时,一次性订阅只能收到一次,操作起来比较繁琐,如果不是刚需用户可能会首次就拒绝了这个服务,要想重新获取授权,需要用户自己打开小程序设置里去配置,颇为麻烦,小程序没有提供更简便的方法去唤起。 2.小程序的服务商为了获得更多给用户发送订阅消息的次数,肯定会想方设法去埋点引诱用户去点击订阅,这种诱导估计也是违规。 3.用户使用门槛和学习比较高,比如某个预约的服务,原来的场景是用户只要有提交表单,小程序就可以推送消息给用户,但是现在需要用户主动去订阅,无形中多了一步,如果用户不熟悉订阅消息或者直接点了“取消”,小程序就没法通知到用户了,用户可能因此错失服务,对商家和用户都是损失。 4.微信小程序将采用订阅消息,并逐步取消模板消息,虽然微信官方试图在方便用户和不打扰用户这两种选择里去寻求平衡,但订阅消息目前的模式恐怕无法达到这个期望,至少在我看来,无论对小程序的服务商,还是小程序的用户,都感到不方便。 update:2020年5月18日,日前订阅消息已经支持微信小程序开发工具。
2020-05-18 - 「笔记」订阅消息体验踩坑
前言 10月12日夜晚社区发了公告小程序模板消息能力调整通知,正式发布了 一次性订阅消息 这一能力,所以第一时间进行了体验。 本文主要是补充一下官方未提供的使用方法,和使用中与模板消息用法的不同。 文档地址 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/subscribe-message.html 使用方法 [代码]wx.requestSubscribeMessage({ tmplIds: ["模板id1","模板id2"], success: function (res) { //成功 }, fail(err) { //失败 console.error(err); } }) [代码] 第一个坑 如果不勾选红色方框内的内容,用户每次触发订阅消息功能都会弹出授权窗口,如果用户勾选了则不会出现弹窗。 [图片] 第二个坑 目前开发者工具(v1.02.191012)不支持调试,只能通过真机调试。 [图片] 第三个坑 微信不会为开发者保存订阅次数,需要自己在后台记录用户触发的次数。 超过次数调用接口下发订阅消息会返回失败。 [图片] 第四个坑 发送模板格式和原来的模板消息格式不一致,特别是data内的内容,订阅消息的字段key是和数据类型有关,value的参数需要严格按照设置的类型提交,具体使用参考后台的模板详情。 模板消息的格式: [代码]"data": { "keyword1": { "value": "内容", "color": "#000" }, "keyword2": { "value": "内容", "color": "#000" } } [代码] 订阅消息的格式: [代码]"data": { "thing1": { "value": "内容" }, "number2": { "value": 20 } [代码] 第五个坑 订阅消息申请模板的时候,需要选择所属类目,而且只能是自己小程序相关类目,模板消息是不需要选择对应类目的。 如果删除小程序类目,则会把订阅消息模板一起删除,需谨慎操作。 [图片] 第六个坑 长期订阅消息只针对特定行业开放,所以普通开发者并无法使用。 结束 暂时就先总结这些,有其它坑再补充。
2019-10-13 - 请问官方,小程序插件中跳转小程序页面的方案
由于公司有几个小程序,其中有一些公共模块,并且该模块功能较多,不想写两份, 现有方案是另外做一个小程序,但是每次跳转之前会提示是否跳转,很影响用户体验, 故打算做一个插件在多方引用,但是在官方文档中只看到了从小程序跳转到插件页面的方法,没有看到插件中可以跳转回小程序页面的方法,想请官方解答一下是否可以实现。
2019-07-08 - 插件用到用户信息、支付行为时为什么要用功能页?
插件开发对用户信息、支付、收获地址这些能力做限制的原因是啥,直接使用不可以么?为什么必须要通过功能页。
2019-09-19 - 小程序组件化开发
一、组件实现方式:template模板和component构造器 除了component,小程序中还有另一种组件化你的方式template模板 区别: 1、template主要是展示,方法则需要在调用的页面中定义。简单来说,如果只是展示,使用template就足够了 2、而component组件则有自己的业务逻辑,可以看做一个独立的page页面。如果涉及到的业务逻辑交互比较多,那就最好使用component组件了。 二、template模板 1、模板定义 建议单独创建template目录,在template目录中创建管理模板文件。 由于模板只有wxml、wxss文件,一个template的模板文件和样式文件只需要命名相同即可,方法则需要在调用的页面中定义 模板文件(wxml):用name区分多个模板 [代码]<template name="packModule"> <view class="packModule">packModule</view> </template> [代码] 模板文件(wxss):自定义模板的样式文件(略),实例中模块相关样式都统一集中在module.wxss中 2、页面引用:(如首页引用) index.wxml: [代码]<!--导入模板--> <import src="./modules/pack.wxml"/> <!--嵌入模板--> <view class="moduleWrap" wx:for="{{moduleInfoList}}" wx:for-item="moduleInfo" wx:key="index"> <!--自由容器模块 里面还有子模块--> <template is="packModule" data="{{moduleInfo}}" wx-if="{{moduleInfo.style == 5}}"></template> <view> [代码] index.wxss: [代码]@import "../../libs/templates/module.wxss"; [代码] 备注: 一个模板文件中可引用多个template,每个template均以name进行区分,页面调用的时候也是以name指向对应的template; template模板没有配置文件(.json)和业务逻辑文件(.js),所以template模板中的变量引用和业务逻辑事件都需要在引用页面的js文件中进行定义; 三、Component组件: [图片] 1. 组件创建: 新建component目录——创建子目录——新建Component(如示例组件:dialog组件) 示例dialog组件也由4个文件构成,与page文件类型相同,但是js文件和json文件与页面有所不同。 dialog.wxml: [代码]<view class="dialog" wx:if="{{ isShow }}"> <!-- 遮罩层 --> <view class="dialog_mask" catchtouchmove="_catchTouch"></view> <!-- 内容 --> <view class="container" catchtouchmove="_catchTouch"> <view class="title" wx:if="{{title}}">{{title}}</view> <view class="content" wx:if="{{content}}"> {{content}} </view> <view class="footer"> <view class="btn cancel_btn" wx:if="{{showCancelButton}}" bindtap="hide" style='background-color:{{globalColor}};'>{{cancelButton}}</view> <view class="btn comfirm_btn" bindtap="comfirm" style='background-color:{{globalColor}};'>{{confirmButton}}</view> </view> </view> </view> [代码] dialog.json: [代码]{ "component": true, "usingComponents": {} } [代码] dialog.wxss:(组件对应 wxss 文件的样式,只对组件wxml内的节点生效) [代码]/* components/dialog/dialog.wxss */ .dialog { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; position: fixed; top:0; z-index: 9999; } ... [代码] dialog.js: [代码]/* * dialog 模态对话框 * Props * 通过事件调用组件 * globalColor:全局色 * Event * show 模态对话框 @param {Object} 配置参数 * hide 模态对话框 * Example * 1、页面中引用dialog:(示例index页面) * 1-1:index.json中声明组件引用 * { * "usingComponents": { * "dialog": "../../components/dialog/dialog" * } * 1-2:index.wxml引用模板 * <dialog id='dialog' global-color="{{globalColor}}"></toast> * 1-3:index页面所引用js文件中,获取组件实例 * onReady: function () { * //获得组件 * this.dialog = this.selectComponent("#dialog"); * } * 2、根据业务条件进行调用: * 2-1、页面中调用: * this.dialog.show({ * title: "提交成功", * content: "描述信息", * cancelButton: "取 消", * showCancelButton:false,//是否显示取消按钮,可缺省,默认不显示 * confirmButton: '确 定', * callback: function () {}//确定按钮回调函数,可缺省,默认只关闭对话框 * }); * 2-1、页面组件中调用: * getCurrentPages()[getCurrentPages().length - 1].dialog.show(...);//传参同上 * 备注:不直接在组件ready中获取dialog组件,会产生多个组件实例,故直接调用页面已有组件实例方法 */ Component({ /** * 组件的属性列表 */ properties: { 'globalColor': String }, /** * 组件的初始数据 */ data: { isShow: false, title: '标题',// 弹窗标题 content: "", // 弹窗内容 cancelButton: '取 消', showCancelButton:false,//是否显示"取消"按钮 confirmButton: '确 定', callback: null //回调函数 }, /** * 组件的方法列表 */ methods: { //隐藏信息提示 hide() { this.setData({ isShow: !this.data.isShow }) }, // 阻止页面滚动 _catchTouch: function () { return; }, //展示信息提示 show(options) { this.setData({ isShow: !this.data.isShow, callback:null }); let _this = this; // 通过options参数配置 if (options) { this.setData(options); } }, // 确定回调 comfirm(){ this.hide(); this.data.callback && this.data.callback();//执行各dialog的回调逻辑 } } }) [代码] 2、页面引用: index.json:(需在json配置文件中进行配置开启使用组件) [代码]{ "usingComponents": { "dialog": "/components/dialog/dialog" } } [代码] index.wxml:(模板文件中引用) [代码]<!-- 自定义dialog组件 --> <dialog id='dialog' global-color="{{globalColor}}"></dialog> [代码] 四、注意点: 1、component组件中扩展自定义节点: 在组件模板中可以提供一个 <slot> 节点,用于承载组件引用时提供的子节点。 默认情况下,一个组件的wxml中只能有一个slot。需要使用多slot时,可以在组件js中声明启用,以不同的 name 来区分。 [代码]Component({ options: { multipleSlots: true // 在组件定义时的选项中启用多slot支持 } }) [代码] 2、component组件样式注意点: 组件对应 wxss 文件的样式,只对组件wxml内的节点生效。 2-1、组件和引用组件的页面不能使用id选择器(#a)、属性选择器([a])和标签名选择器,请改用class选择器。 2-2、组件和引用组件的页面中使用后代选择器(.a .b)在一些极端情况下会有非预期的表现,如遇,请避免使用。 2-3、子元素选择器(.a>.b)只能用于 view 组件与其子节点之间,用于其他组件可能导致非预期的情况。 2-4、继承样式,如 font 、 color ,会从组件外继承到组件内。 2-5、除继承样式外, app.wxss 中的样式、组件所在页面的的样式对自定义组件无效(除非更改组件样式隔离选项)。 [代码] #a { } /* 在组件中不能使用 */ [a] { } /* 在组件中不能使用 */ button { } /* 在组件中不能使用 */ .a > .b { } /* 除非 .a 是 view 组件节点,否则不一定会生效 */ [代码] 五、组件间通信与事件: 1、父组件(调用页面)向子组件传值通讯: 通过properties向自定义组件传递数据 2、子组件向父组件(调用页面)传值通讯: 1、监听事件 自定义组件可以触发任意的事件,引用组件的页面可以监听这些事件 [代码]<!-- 当自定义组件触发“myevent”事件时,调用“onMyEvent”方法 --> <component-tag-name bindmyevent="onMyEvent" name="{{name}}" /> Page({ data:{ name:"test" }, onMyEvent: function(e){ e.detail // 自定义组件触发事件时提供的detail对象 } }) [代码] 2、触发事件 自定义组件触发事件时,需要使用 triggerEvent 方法,指定事件名、detail对象和事件选项: [代码]<!-- 在自定义组件中 --> <view>{{name}}</view> <button bindtap="onTap">点击这个按钮将触发“myevent”事件</button> Component({ properties: { name: { type: String, value: '' } }, methods: { onTap: function(){ var myEventDetail = {} // detail对象,提供给事件监听函数 var myEventOption = {} // 触发事件的选项 this.triggerEvent('myevent', myEventDetail, myEventOption) } } }) [代码] 总结 自定义组件,可以理解为一个自定义的标签,页面的一个片段,可以分为template方式和component组件方式实现;如果是简单的内容展示,逻辑单一,使用template方式即可,但如果每一个组件都有自己的业务逻辑,各自独立,建议使用component组件方式实现,灵活性更高。 参考文献 官方文档
2019-06-20 - 从源码看微信小程序启动过程
一、写作背景 接触小程序一年多,真实体验就是小程序开发门槛相对而言确实比较低。不过小程序的开发方式,一直是开发者吐槽的,如习惯了 Vue,React 开发的开发者经常会吐槽小程序一个 Page 必须由多个文件组成,组件化支持不完善或者说不能非常愉快的开发组件。在以前小项目中没太大感觉,从加入有赞,参与有赞微商城小程序的开发,是真切的体会到对于大型小程序项目开发的复杂性。 有赞从微信小程序内测就开始开发小程序,在不支持自定义组件的时代,只能通过 import 的形式拆分模块或实现组件。在业务复杂的页面,可能会 import 非常多的模块,而相应的 wxss 也需要 import 样式,除了操作繁琐,有时候也难免遗漏。 作为开发者,我们当然希望可以让工作更简单,更愉快,也希望改善我们的开发方式。所以希望能够更了解微信小程序框架,减少不必要的试错,于是有了一次对小程序框架的 debug 之旅。(基础库 1.9.93) 通过三周空余时间的 debug,也算对小程序框架有了一些浅显的认识,达到了最初的目的;对小程序启动,实例,运行等有了真切的体会。这篇文章记录了小程序框架的基本代码结构,启动流程,以及程序实例化过程。 本文的目的是希望把我看到的分享给对小程序感兴趣或者正在开发小程序的读者,主要解答“框架对传入的对象等到底做了什么”。 二、从启动流程一窥小程序框架细节 在开发者工具中使用 help() 方法,可以查看一些指令和方法。使用其中的 openVendor 方法可以打开微信开发者工具在小程序框架所在目录。其中以包括以基础库命名的目录和其他帮助文件,如其中有两个工具 wcc,wcsc。wcc 可把 wxml 转换为对应的 JS 函数 —— $gwx(path, global),wcsc 可将 wxss 转换为 css。而基础库目录包括 WAService.js 和 WAWebview.js 文件。小程序框架在开发者工具中以 WAService.js 命名(WAWebview.js 不知其作用,听说在真机环境使用该文件)。 在开发中工具命令行使用 document.head 可以查看到小程序的启动流程大致如下: [图片] 以小节的方式分别介绍这些流程,小程序是如何处理的(小节编号与图中编号相同)。 1、初始化全局变量 下图是小程序启动是初始化的一些全局的变量: [图片] 那些使用“__”开头,未在文档中提及可使用变量是不建议使用的,wxAppCode 在开发者工具中分为两类值,json 类型和 wxml 类型。以 .json 结尾的,其 key 值为开发者代码中对应的 json 文件的内容,.wxml 结尾的,其 key 值为通过调用 $gwx(’./pages/example/index.wxml’) 将得到一个可执行函数,通过调用这个函数可得到一个标识节点关系的 JSON 树。 [图片] 2、加载框架(WAService.js) 使用工具对 WAService.js 进行格式化后进行 debug。可以发现小程序框架大致由: WeixinJSBridge、 NativeBuffer、 wxConsole、 WeixinWorker、 JavaScript兼容(这部分为猜测)、 Reporter、 wx、 exparser、 virtualDOM、 appServiceEngine 几部分组成。 其中除了 wx 和 WeixinJSBridge 这两个基础 API 集合, exparser, virtualDOM, appServiceEngine 这三部分作为框架的核心, appServiceEngine 提供了框架最基本的接口如 App,Page,Component; exparser 提供了框架底层的能力,如实例化组件,数据变化监听,view 层与逻辑层的交互等;而 virtualDOM 则起着链接 appServiceEngine 和 exparser 的作用,如对开发者传入 Page 方法的对象进行格式化再传入 exparser 的对应方法处理。 框架对外暴露了以下API:Behavior,App,Page,Component,getApp,getCurrentPages,definePlugin,requirePlugin,wx。 3、业务代码的加载 在小程序中,开发者的 JavaScript 代码会被打包为 [代码]define('xxx.js', function(require, module, exports, window, document, frames, self, location, navigator, localStorage, history, Caches, screen, alert, confirm, prompt, fetch, XMLHttpRequest, WebSocket, webkit, WeixinJSCore, Reporter, print, WeixinJSBridge) { 'use strict'; // your code }) [代码] 这里的 define 是在框架中定义的方法,在框架中提供了两个方法:require 和 define 用来定义和使用业务代码。其方式有些像 AMD 规范接口,通过 define 定义一个模块,使用 require 来应用一个模块。但是也有很大区别,首先 define 限制了模块可使用的其他模块,如 window,document;其次 require 在使用模块时只会传入 require 和 module,也就是说参数中的其他模块在定义的模块中都是 undefined,这也是不能在开发者工具中获取一些浏览器环境对象的原因。 在小程序中,JavaScript 代码的加载方式和在浏览器中也有些不同,其加载顺序是首先加载项目中其他 js 文件(非注册程序和注册页面的 js 文件),其次是注册程序的 app.js,然后是自定义组件 js 文件,最后才是注册页面的 js 代码。而且小程序对于在 app.js 以及注册页面的 js 代码都会加载完成后立即使用 require 方法执行模块中的程序。其他的代码则需要在程序中使用 require 方法才会被执行。 下面详细介绍了 app.js,自定义组件,页面 js 代码的处理流程。 4、加载 app.js 与注册程序 在 app.js 加载完成后,小程序会使用 require(‘app.js’) 注册程序,即对 App 方法进行调用,App 方法是对 appServiceEngine.App 方法的引用。 下图是框架对于 App 方法调用时的处理流程: [图片] App 方法根据传入的对象实例化一个 app 实例,其生命周期函数 onLaunch 和 onShow 因为使用不同的方式获取 options的参数。在有些需要根据场景值来实现需求的,或许使用 onShow 中的场景值更合适。 在实际开发过程中发现,在微信顶部唤起小程序和在小程序列表唤起的 options 也是不一样的。在该案例中通过点击分享的小程序进入后,关闭小程序,再通过不同方式进入小程序,通过顶部唤起的还是 options 的 path 属性还是分享出来的 path,但是通过列表中打开直接回到了首页,这里 App 中的 onShow 就会获取到不同的 options。 5、加载自定义组件代码以及注册自定义组件 自定义组件在 app.js 之后被加载,小程序会在这个过程中加载完所有的自定义组件(分包中自定义组件没有有测试过),并且是加载完成后自动注册,只有注册完成后才会加载下一个自定义组件的代码。 下图是框架对于 Component 方法处理流程: [图片] 图中介绍了框架如何对传入 Component 方法的对象的处理,其后面还有很多深入的对于组件实例化的步骤没有在图中表示出来,具体可以在文章最后的附件中查看。 自定义组件在小程序中越来越完善,其拥有的能力也比 Page 更强大,而后面会提到在使用自定义组件的 Page 中,Page 实例也会使用和自定义组件一样的实例化方式,也就是说,他拥有和自定义组件一样的能力。 6、加载页面代码和注册页面 加载页面代码的处理流程和加载自定义组件一样,都是加载完成后先注册页面,然后才会加载下一个页面。 下图是注册一个页面时框架对于 Page 方法的处理流程: [图片] Page 方法会根据是否使用自定义组件做不同的处理。使用自定义组件的 page 对象会被处理为和自定义组件的结构,并在页面实例化时使用不同的处理流程进行实例化。当然对于开发而言没任何不同。 从图中可以发现 Page 传入的(生命周期)代码并不会在这里被执行,可以通过下面小节了解 Page 实例化的详细过程。 7、等待页面 Ready 和 Page 实例化 还记得上面介绍的启动流程中最后一步等待页面 Ready?严格来讲是等待浏览器 Ready,小程序虽然有部分原生的组件,不过本质上还是一个 web 程序。 在小程序中切换页面或打开页面时会触发 onAppRoute 事件,小程序框架通过 wx.onAppRoute 注册页面切换的处理程序,在所有程序就绪后,以 entryPagePath 作为入口使用 appLaunch 的方式进入页面。 下图是处理导航的程序流程: [图片] 从图中可以看出页面的实例化是在进入页面时进行,下图是具体的实例化过程: [图片] 下图是最终可得到 Page 实例: [图片] 可以发现其中多了 onRouteEnd API,实际该接口不会被调用。其中以 component 标记的表示只有在使用了自定义组件时才会有的方法和属性。在前面第 5 小节提到了对于使用自定义组件的页面会按照自定义组件方式解析,这些属性和方法与自定义组件表现一致。 8、关于 setData 小程序框架是一个以数据驱动的框架,当然不能少了对他如何实现数据绑定的探索,下图是 Page 实例的 setData 执行流程: [图片] 其中 component:setData 表示使用自定义组件的 Page 实例的 setData 方法。 三、写在最后 这是一次不完全的小程序框架探索,是在微信开发工具中 debug 的结果。虽然对于实际开发没有什么太大的帮助,但是对框架如何对开发的 js 代码进行处理有了一个很明确的认识,在使用一些 js 特性时可以有明确的感知。如果你还疑惑“小程序框架对传入的对象等到底做了什么”那一定是我表达能力太差,说声对不起。 通过这一次 debug ,也给我引入了新的问题,还希望能够有更多的讨论: · 自定义组件太多启动时会耗时处理自定义组件 · 文件太多会耗时读文件 · 合理的设计分包很重要 当然最后对于框架中已有的能力,还是非常希望微信可以开放更多稳定的接口,并在文档中告知开发者,让开发变得简单一些。
2019-03-05 - 多次点击按钮 调用订阅消息,wx.requestSubscribeMessage方法失效?
情景描述: 用户勾选了 ‘总是保持以上选择’,然后进行多次点击调用订阅消息,就会出现 点击后,并没有走wx.requestSubscribeMessage方法 <view catchtap="news_look">测试订阅消息</view> data:{ zl_n:0 //初始化 0 } //订阅消息 news_look() { var that = this; that.setData({ zl_n: that.data.zl_n+1 }) var news_id = [ 'wUtY5GZoAoIn8eZ5hQs3JDyHRmM4LO82oPjkNtOhJ0o', // 周报 '95zYfq0I83ZgtlF_zR5dsdFJiykkR6-rn8YJVaT7kXE', //月报 'jipK7X6qhJJY0gg7Cxn-v2dnr4D5qEDwktsqREY-rXI', //纪念日通知 ] wx.requestSubscribeMessage({ tmplIds: news_id, success(res) { console.log('允许使用订阅消息') console.log(res) }, fail(res) { console.log('fail 失败') console.log(res) logger.warn('订阅消息fail', res) }, complete(res) { console.log('complete 调用完成') wx.showToast({ title: '' + that.data.zl_n, }) } }) }, //这段代码 出现无效的次数更频繁 [图片] [图片] [图片] [图片]
2019-11-18 - 小程序模板消息能力调整通知
小程序模板消息能力在帮助小程序实现服务闭环的同时,也存在一些问题,如: 1. 部分开发者在用户无预期或未进行服务的情况下发送与用户无关的消息,对用户产生了骚扰; 2. 模板消息需在用户访问小程序后的 7 天内下发,不能满足部分业务的时间要求。 为提升小程序模板消息能力的使用体验,我们对模板消息的下发条件进行了调整,由用户自主订阅所需消息。 一次性订阅消息 一次性订阅消息用于解决用户使用小程序后,后续服务环节的通知问题。用户自主订阅后,开发者可不限时间地下发一条对应的服务消息;每条消息可单独订阅或退订。 [图片] (一次性订阅示例) 长期性订阅消息 一次性订阅消息可满足小程序的大部分服务场景需求,但线下公共服务领域存在一次性订阅无法满足的场景,如航班延误,需根据航班实时动态来多次发送消息提醒。为便于服务,我们提供了长期性订阅消息,用户订阅一次后,开发者可长期下发多条消息。 目前长期性订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放,后期将逐步支持到其他线下公共服务业务。 调整计划 小程序订阅消息接口上线后,原先的模板消息接口将停止使用,详情如下: 1. 开发者可登录小程序管理后台开启订阅消息功能,接口开发可参考文档:《小程序订阅消息》 2. 开发者使用订阅消息能力时,需遵循运营规范,不可用奖励或其它形式强制用户订阅,不可下发与用户预期不符或违反国家法律法规的内容。具体可参考文档:《小程序订阅消息接口运营规范》 3. 原有的小程序模板消息接口将于 2020 年 1 月 10 日下线,届时将无法使用此接口发送模板消息,请各位开发者注意及时调整接口。 微信团队 2019.10.12
2019-10-13 - 社区每周 | 同层渲染、实时日志功能更新、活动获奖公示与上周社区问题反馈(10.21-10.25)
各位微信开发者: 以下是上周小程序相关能力更新、活动获奖公示及我们在社区收到的问题反馈、需求的处理进度,希望同大家一同打造小程序生态。 特别提醒基础库下个大版本号为 2.10.0,请开发者注意小程序中版本号大小判断是否有误。相关指引 同层渲染进度同步为了解决小程序原生组件存在的一些使用限制,我们对原生组件引入了同层渲染。支持同层渲染的原生组件层级与非原生组件一致,可直接使用非原生组件(如 view、image)结合 z-index 对原生组件进行覆盖,而无需使用 cover-view 或 cover-image。此外,同层渲染的原生组件也可被放置在 scroll-view、swiper 或 movable-view 容器中。目前,以下组件已支持同层渲染: 支持同层渲染的原生组件最低版本videov2.4.0mapv2.7.0canvas 2d(新接口)v2.9.0live-playerv2.9.1live-pusherv2.9.1其他原生组件(textarea、camera、webgl 及 input)也会在近期逐步支持同层渲染。 欢迎广大开发者体验,如有问题,可在本帖下方留言反馈给我们。 小程序实时日志功能更新1 . 为满足第三方服务商和开发者分析日志的需求,小程序新增实时日志查询接口,开发者可通过实时日志查询接口查询小程序打印的实时日志。详情可查看 《实时日志查询接口》和《实时日志开发文档》。 2.每个小程序账号每天可打印的日志条数提升至500万条,日志保存天数提升至7天。 2019中国高校计算机大赛微信小程序应用开发赛文章征集活动获奖公示2019中国高校计算机大赛微信小程序应用开发赛文章征集 活动,按照“文章内容(40%)、产品/技术干货(50%)、排版(10%)”的规则,经微信技术专家综合评估,以下3篇文章作品被评为“优秀作品”(排名不分先后): 【大赛文章征集】八“粤”你好——浅谈Attack 足球 一场比赛,一窥小程序的有限与无限 【大赛文章征集】微信小游戏 《时空异闻录》(技术篇) 获奖“优秀作品”将获得未来大赛官网专题页展示、推荐至微信开放社区的「精选文章」版块,作者将获得微信限量版T恤一件。 感谢大家对大赛及征文活动的大力支持,共同学习协力成长! 1024话题活动获奖公示在10月的24日的程序员节当天,社区发起了一次1024话题有奖活动,标题为“1024到了,你觉得哪些工作表现,成为了你程序猿生涯中的高光时刻?“。 截止到10月31日,共有3811 人浏览,93 人参与,共收到69个回答。在此,非常感谢社区小伙伴的积极参与和支持。 在众多的回答中,其中有4个回答,描述详细、语词真切、紧扣主题。被评本次1024话题活动的优质回答,作者将获得微信正版周边精美礼品一份。 1024话题活动的优质回答获奖名单如下: Hanks、Cooper、小满、烬 希望大家在未来的社区活动中,积极参与、乐于分享、勇于发言。社区,等你来共同建设! 上周问题反馈和处理进度(10.21-10.25)已修复的问题修改简称确认按钮点不动的问题 查看详情 小游戏mp后台统计-收入分析 中 虚拟支付和广告收入金额显示异常的问题 查看详情 开发工具更新到1.02.1910120版本后代码上传失败的问题 查看详情 运维中心错误查询页面无提示内容的问题 查看详情 无法进入体验版小程序 查看详情 小程序审核 反馈页面 不填写版本描述不能提交 ,版本描述对话框不让打字 查看详情 下个基础库修复swiper 的 bindanimationfinish 方法的问题 查看详情 小程序 editor 插入图片后图片直接插到前面了 查看详情 lazy-load 属性的问题 查看详情 textarea 中 iOS 和 Android 中 bindfocus 和 bindinput 的问题 查看详情 安卓版微信扫描 data matrix 类型二维码,数据被逗号截取的问题 查看详情 修复中的问题关于 input 真机聚焦的问题 查看详情 video 组件播放视频,同一个源 iOS 正常播放,安卓无法播放的问题 查看详情 camera 权限 bug 的问题 查看详情 微信小游戏版本更新后,有的玩家的游戏版本没有更新的问题 查看详情 关于小程序setData在安卓微信上赋值失败问题 查看详情 微信小游戏虚拟支付问题 查看详情 云开发环境下,多集合执行失败的问题 查看详情 Worker 文档页中,存在跳转链接404的情况 查看详情 cover-image 加载得图片不能在安卓手机上滑动的问题 查看详情 CSS3 动画,在 iOS 出现了跳帧和溢出的问题 查看详情 wx.requestMidasPayment 回调出错的问题 查看详情 自动化工具 callWxMethod(setStorage) 存储的数据在重新启动后回退的问题 查看详情 微信小游戏后台广告收入、内购收入数据出现异常的问题 查看详情 小游戏id,提示为小程序id,导致无法建立小游戏项目的问题 查看详情 网页版客服没有状态栏的问题 查看详情 游戏广告问题的问题 查看详情 微信公众号管理后台官方文档页面404的问题 查看详情 分包加载失败的问题 查看详情 cocos creator 导出的小游戏在 iOS 上可以正常运行,android上加载到100%无法运行 查看详情 关于 websocket 连接,微信是不是在同一个 APPID 缓存了 websocket 某种状态的问题 查看详情 GameRecordShareButton 无法设置宽度的问题 查看详情 开发工具中小游戏无法本地存储的问题 查看详情 需求反馈已支持swiper 的 bindanimationfinish 方法的需求 查看详情 迭代跟进中camera 组件可变焦的需求 查看详情 订阅消息模板审核的相关需求 查看详情 需求评估中微信小程序 支持腾讯云实时音视频 可以配置画面质量的需求 查看详情 关于小程序广告组件审核流程的优化 查看详情 企业微信 连续的扫码推事件(弹框)scancode_waitmsg 的需求 查看详情 微信小程序的地图组件功能的需求 查看详情 wx.hideHomeButton 可以全局取消的需求 查看详情 小程序 picker type=time 范围支持跨度2天的需求 查看详情 原生与 web-view 之间的通讯的相关需求 查看详情 editor 组件插入音频视频的需求 查看详情 微信小程序可以开放瓦片地图功能的需求 查看详情 用户接收到公众号的回复通知可以持续高亮显示的需求 查看详情 微信团队 2019.10.31
2019-10-31 - 登录优化1.0:你的小程序将会赢得更多用户的青睐!
今天,说一个能为你“拉好感”的改动。 小程序帐号登录功能进行全新的规范升级,包括但不限于手机号登录、邮箱登录等。划重点:从2019年9月1日开始,对于未满足登录规范要求的小程序,我们将会在后续的代码审核环节进行规则提示和修改要求反馈。 用户使用登录功能就像“面基”,第一印象很重要。这几个小改动在提升小程序使用的流畅体验、避免用户对数据采集授权担忧的同时,也将驱动用户更乐意尝试使用小程序服务。来,通过三个问题来解锁正确启用帐号登录的姿势。 跟败好感”的姿势告别 问题一 : 在用户清楚知悉、了解小程序的功能之前,就要求用户进行帐号登录会怎样? [图片] (错误示范:在用户打开小程序后立刻弹出授权登录页) 用户好感-1。刚见面就要牵手未免太尴尬,与其打开小程序后立即跳转提示登录或打开小程序后立即强制弹窗要求登录,不如把主动权交给用户。 用户体验小程序功能后,可以主动点击登录按钮来触发登录流程,也可以选择不登录。 [图片] Tips: 适用于对外开放用户注册流程、无需验证特定范围用户,且注册后即可提供线上服务的小程序。 有个特例, 为学校系统、员工系统、社保卡信息系统等提供服务的小程序,倒是可以直接引导用户进行帐号登录。 [图片] 问题二 : 线上仅提供注册功能,服务依赖其他方式提供的小程序,如ETC注册申请、信用卡申请,在用户未获取任何信息时,首页直接弹框要求登录注册会怎样? [图片] (错误示范:用户进入ETC小程序时立刻弹出授权登录页) 用户好感再-1 。“神秘感”能营造好氛围,但你的小程序都如此优秀了,可以直接告诉用户原因再让他们接受—— 用户在小程序首页了解要求使用帐号登录功能的原因后,可通过登录或注册按钮进行登录操作。 [图片] 问题三 : 在需要登录环节直接跳转登录页面,只给用户一个登录选项会怎样? [图片] (错误示范:登录页面只有登录选项) 用户好感再-N。“霸道总裁”不要太用力,多给些温柔的选项,用户会更快爱上你。 在需帐号登录的环节中,用户可以主动点击登录,或点击取消登录,没有强制登录的行为。 [图片] 姿势掌握了吗?我们希望帮助开发者们能根据正确姿势示范,调整小程序的帐号登录功能,优化用户使用帐号登录功能的体验,更好地与用户相处,同时赢得更多用户的青睐。
2021-06-23 - 登录优化:2.0:让你的小程序与用户做朋友
上一篇小程序登录相关的学院课程,我们围绕小程序如何通过优化登录“拉好感”提了几点建议。 前方再次预告,开发人员请及时到场:9月1日起,小程序登录规范规则正式开始执行,未满足登录规范要求的小程序将会被代码审核拦截,请尽快优化。 下面,我们来复习下正确的登录优化姿势。 从陌生人到“知己” 想要“拉好感”并不难,秘诀就在于跟用户做朋友。开发者可以站在用户的角度体验小程序,从而更了解自己的产品。 攻略一:互相认识从自我介绍开始。对于线上仅提供注册功能,服务依赖其他方式提供的小程序,可先让用户知悉小程序功能,再引导用户进行授权。 下面这个ETC小程序,就“秀”了一波:用户可在首页了解小程序相关功能及使用帐号登录的原因,并可先办理ETC再登录。 [图片] [图片] [图片] [图片] [图片] 攻略二:做完介绍,先别急着登录,让对方花点时间了解你。对于服务范围开放的小程序,可先让用户体验了解小程序功能,与其只给用户一个登录选项,不如用“个人魅力”吸引他们。 例如,在这个DJ小程序中,用户可先听音乐蹦迪授权登录后,还能关注作者、风格及电台,或购买周边商品,享受更多服务。 [图片] [图片] [图片] 不过,如果服务范围是特定的,可以直接让用户登录,毕竟你和用户已经是知根知底的“老熟人”了。 攻略三:退一步,给对方留点拒绝的余地。在小程序登录页提供可取消或拒绝的选项按钮,反而更能留下好印象。 以这个拼单小程序为例,用户可先浏览商品信息,查看商品详情。如果用户心动了,点击“我的”进入个人中心授权登录即可下单;如果用户犹豫不决,还可以退出登录页面继续逛。 [图片] [图片] [图片] [图片] 登录优化的Q&A 对规则仍然有疑惑的开发人员,我们也补充了详细的问题解答,希望对你们有帮助—— Q:9月1日后,开发者该如何获得用户的UnionID?用户不登录就没有UnionID,怎么办? UnionID是作为微信体系内,用户帐号在同一主体下不同公众号、小程序及App之间实现数据互通的识别凭证,这个信息本身是匿名化、不敏感且不可反推的。但用户如果在不知情的情况下被获取,并且开发者完成了跨平台或者跨产品的打通,会使得用户产生困惑,为什么同一个用户在帐号A的信息会在帐号B中被展示。 站在用户体验和隐私保护的角度来看,每个人都不希望自己的个人信息在不知情的情况下被获取。因此,开发者要在用户授权登录后,才能获取UnionID 如果用户曾经授权登录过同主体App或关注了同主体公众号,则表示用户已经知情并同意登录,这时开发者可以直接获得UnionID。点击这里查看详情。 如果用户未授权登录,开发者可根据前面的攻略,进一步优化登录体验,让用户更乐意登录使用你的小程序。 unionid就像大型连锁超市(微信内同主体帐号)给客户(用户)发放会员卡(nionid),客户持有会员卡可在连锁超市内享受会员权益。 而用户不知情即被获取unionid,就好比在连锁超市购物后,没有任何信息说明,超市就要求留下手机号码等身份凭证识别信息。下次用户去另一家连锁超市时,超市已清晰记录用户之前的消费记录。这是我们不提倡的。 因此,我们希望在用户对小程序的业务有了解之后,开发者明确告知用户会在什么功能或业务使用unionid打通不同帐号之间的数据。 Q:怎么划分服务范围开放和服务范围特定呢? 举个简单的例子,当你在餐厅、商店消费时,服务员不会要求查看你的身份证明,再为你提供服务,但当你进入学校或公司时,则需先登记才能进去。 因此,服务范围开放是指完全对外开放注册,无需进行特殊身份验证,注册后即可提供线上服务体验的小程序,例如电商、外卖等小程序;服务范围特定则需要进行特殊身份验证,且线上服务仅供特殊身份用户体验,例如学校教学系统、公司员工系统等小程序。 Q:服务范围开放的小程序,可以使用仅提供注册功能小程序的调整方案吗? 如果小程序服务范围属于完全开放,线上仅提供注册功能,其他服务均需以其他方式提供的,例如ETC小程序,可以在首页介绍小程序的服务功能,说明要求使用帐号登录功能的原因后,让用户主动选择登录。 反之则需要让用户进入小程序体验并了解平台功能,在使用需要注册登录才能体验的功能时,才触发登录注册流程。 Q:如果小程序不调用微信个人信息授权,只使用帐号密码或手机号码登录,需要优化吗? 小程序帐号登录,是指开发者在小程序内提供的帐号登录功能,包括但不限于手机号登录、getuserinfo形式登录、邮箱登录等形式。因此,开发者也需根据规范进行优化 再次划重点,请未满足小程序帐号登录规范的开发者们尽快完成优化,为你的小程序增加更多好感度。 未来,我们还将不断优化小程序使用体验,希望开发者与我们一起,让平台生态更加绿色健康。如果你对新规范还有什么疑惑,欢迎在评论区聊聊。
2021-06-23 - 小程序·云开发实战 - 校园约拍小程序
创意来源于生活,之所以开发这个校园约拍小程序,是因为在摄影选修课上常听老师抱怨外出写生老找不到模特,许多大学生都想拥有一套专属自己记忆的摄影作品,记录下不会磨灭的美好回忆,可如何找到让自己满意的摄影师是他们的难题。悦拍屋是一个校园摄影o2o的约拍平台,提供全方位的约拍服务,同时提供一个自我展示,学习交流,互动娱乐的平台。接下来我将结合项目的讲解给大家分享一些实用技术和对于云开发的一些经验,希望对正在学习小程序的你有帮助。 前言 在开发一个项目之前首先要进行技术选型从而降低产品开发的技术风险和提高开发效率,技术选型必须得紧紧围绕着业务场景来选择。 产品原型设计:墨刀 UI组件库 1.微信原生样式库[代码]WeUI[代码],让用户使用感知更加统一 2.注重视觉交互体验的[代码]ColorUI[代码]组件库,在感知统一的基础上视觉元素多样化 前端 1.小程序原生语法以及[代码]API[代码] 2.[代码]Promise[代码]实现异步调用 3.[代码]ES6[代码]编写页面交互逻辑 后端 1.云函数:无需自建服务器,在云端运行的代码,微信私有协议天然鉴权,开发者只需编写自身业务逻辑代码 2.云数据库:无需自建数据库,一个既可在小程序前端操作,也能在云函数中读写的 [代码]JSON[代码] 数据库 3.云存储:实现小程序前端直接上传/下载云端文件,在云开发控制台可视化管理 4.云调用:由原生微信服务集成,基于云函数免鉴权使用小程序开放接口的能力,包括服务端调用、获取开放数据等能力 其他 1.使用微信提供的云测试对未上线的小程序进行缺陷测试、性能数据分析、机型覆盖测试,确保小程序上线后正常运营 2.使用基于云开发的[代码]AI视觉能力[代码]-身份证识别实现实名认证,智能鉴黄结合人工完成发布信息的审核 3.开发工具:微信开发者工具、VScode 4.部分图标使用自阿里巴巴矢量图标库 总体设计 功能结构图 大家可以通过此图了解整个项目的主要功能点 [图片] 产品原型图 此处给出一张主页原型图示例,墨刀还是挺好用的 [图片] 色彩设计图 悦拍屋的整体色调为浅蓝色,各位小伙伴在开发自己项目的时候可以根据色彩标准搭配来设计项目所采用的色彩,合适的色彩搭配可以给用户良好的视觉体验 [图片] 功能模块详解 接下来我会对部分功能模块以图文结合的形式详细描述,将其中涉及的技术、知识分享给大家 约拍邀请 用户可在首页查看约拍需求,并点击查看需求详情,用户在了解需求后,若自己符合条件即可提交约拍信息,等待发布者的回复,可将此需求收藏方便查看 [图片] 技术分享:自定义顶部导航栏 官方默认的导航栏只能对背景颜色进行更改,对于想要在导航栏添加一些比较酷炫的效果则需要通过自定义导航栏实现 实现原理:通过设置[代码]app.json[代码]中页面配置的[代码]navigationStyle[代码](导航栏样式)配置项的值为[代码]custom[代码],即可实现自定义导航 [代码]"window":{ "navigationStyle":"custom" } [代码] 本项目的部分页面自定义导航栏实现使用了[代码]ColorUI[代码]的导航栏组件,在完成上一步属性设置后再引入导航栏组件即可 [代码]"usingComponents":{ "cu-custom":"/colorui/components/cu-custom" //该路径替换为自己项目内ColorUI组件所在位置 } [代码] 主页自定义导航栏通过设置背景图片加上GIF波浪效果 [代码] <view class='page__bd'> <view class="bg-img padding-tb-xl" style="background-image:url('http://wx4.sinaimg.cn/mw690/006UdlVNgy1g2v2t1ih8jj31hc0p0qej.jpg');background-size:cover;"> <view class="cu-bar"> <view class="content text-bold text-white"> 悦拍屋 </view> </view> </view> <view class="shadow-blur"> <image src="https://image.weilanwl.com/gif/wave.gif" mode="scaleToFill" class="gif-black response" style="height:100rpx;margin-top:-100rpx;"></image> </view> </view> [代码] 效果图 [图片] 使用组件定义的导航栏 [代码]<cu-custom bgImage="https://s2.ax1x.com/2019/05/02/Etiyng.jpg" isBack="{{true}}"> <view slot="backText">返回</view> <view slot="content">认证信息说明 </view> </cu-custom> [代码] 效果图 [图片] [代码]特别提醒1:使用自定义导航后,页面的返回需要在自定义导航栏中自行设置 [代码] [代码]特别提醒2:导航栏组件需要自行引入ColorUI组件库后才能使用,具体引入教程地址在附录中给出 [代码] 发布约拍 选择发布约拍功能填写约拍需求,提交审核通过后可在首页实时查看发布结果 [图片] 技术分享:入场动画 额。。录制可能略微有点卡顿,实际效果挺流畅的,各位大佬有什么好的录制工具推荐可以在评论中回复 实现原理:通过[代码]toggleDelay[代码]的布尔值为真动态添加动画类名,在生命周期函数[代码]onReady[代码]中控制[代码]toggleDelay[代码]的值从而控制整个动画过程(原理与[代码]Vue[代码]的动态类名相似) [代码]data:{ toggleDelay;false }, onReady:function(){ let that = this //toggleDelay的值为真,动画开始 that.setData({ toggleDelay: true }) //控制整个动画的时长 setTimeout(function() { that.setData({ toggleDelay: false }) }, 2000) } [代码] [代码]<view class="padding-xs {{toggleDelay?'animation-slide-bottom':''}}" style="animation-delay: {{item.time}}s;" wx:for="{{list}}" wx:key="{{index}}"> <image class="img" id='img{{index}}' src="{{item.src}}" mode="widthFix" /> </view> [代码] [代码]//所有动画的定义 [class*=animation-] { animation-duration: .5s; animation-timing-function: ease-out; animation-fill-mode: both } //animatioon-slide-bottom所定义的动画 .animation-slide-bottom { animation-name: slide-bottom } //动画效果 @keyframes slide-bottom { 0% { opacity: 0; transform: translateY(100%) } 100% { opacity: 1; transform: translateY(0) } } [代码] [代码]animation-slide-bottom[代码]是动画类名,[代码]animation-delay[代码]是每一个卡片动画执行的延迟时间,每一个动画的执行时长为0.5s,所以延迟时间是以0.5s递增的,三个卡片的动画总时长就为2s,即2s后就执行[代码]onReady[代码]中的[代码]settimeout[代码]事件结束动画 [代码]特别提醒:动画的延迟时间,执行时间可以自行设计,动画效果过渡自然即可 [代码] [代码]特别提醒:由于触发动画的钩子函数定义在页面初次渲染的生命周期函数中,故只有在页面初次渲染时才执行,避免每次显示页面时加载动画造成用户的视觉疲劳 [代码] 智能推荐约拍对象 系统会根据约拍需求自动推荐约拍对象(个人开发精力有限,推荐算法后续推出。。。) [图片] 技术分享:CSS3实现酷炫搜索动画 在模态框内放置两个[代码]view[代码]标签,以下是标签定义 [代码] <view id='preloader'> //外围的圆形框定义 <view id='loader'></view> //内部的线条定义 </view> [代码] [代码]#preloader { width: 150px; height: 150px; border-radius: 50%; border: 1px solid #97b2ff; } #loader { //中间线条定义 display: block; position: relative; left: 50%; top: 50%; width: 150px; height: 150px; margin: -75px 0 0 -75px; border-radius: 50%; border: 3px solid transparent; border-top-color: #97b2ff; -webkit-animation: spin 2s linear infinite; animation: spin 2s linear infinite; } #loader:before { //通过伪类元素定义外围线条 content: ""; position: absolute; top: 5px; left: 5px; right: 5px; bottom: 5px; border-radius: 50%; border: 3px solid transparent; border-top-color: #97b2ff; -webkit-animation: spin 3s linear infinite; animation: spin 3s linear infinite; } #loader:after { //通过伪类元素定义最内部线条 content: ""; position: absolute; top: 15px; left: 15px; right: 15px; bottom: 15px; border-radius: 50%; border: 3px solid transparent; border-top-color: #97b2ff; -webkit-animation: spin 1.5s linear infinite; animation: spin 1.5s linear infinite; } [代码] 实名认证 [图片] 嘿嘿,由于懒得给个人信息打码,就暂时不给大家演示认证过程了。。 技术分享:Ai视觉能力 很多小伙伴都有过在自己项目中使用AI技术的想法,但又因为入门AI的难度比较大,并且需要的时间较长就放弃了,现在给大家安利一个可以直接使用的AI服务,让AI不再具有神秘感(AI大佬可以忽略此部分。。) 方案一 在腾讯云中搜索身份证识别,上面会有详细的API文档以及测试工具帮助你快速使用 [图片] 点击查看腾讯云-身份证识别 方案二 方案一是以提供API接口的形式提供身份证识别服务,而接下来要介绍的方案真的就比较简单了,在腾讯云中搜索智能图像,其中的增值服务AI智能图像能力,你可以通过云函数和云存储实现相应功能,基于小程序云开发的 AI DEMO中开发好了部分功能,你只需通过教程将云函数和组件引入你的项目即可使用 [图片] 点击查看腾讯云-智能图像 点击查看基于小程序云开发的 AI DEMO [代码]特别提醒:当然使用这些服务也并非是完整的解决方案,对于身份证信息的加密、存储方案、安全协议等还是需要各位小伙伴自行设计解决方案哦。 [代码] 云开发 云开发为开发者提供完整的原生云端支持和微信服务支持,弱化后端和运维概念,无需搭建服务器,使用平台提供的 API 进行核心业务开发,即可实现快速上线和迭代,同时这一能力,同开发者已经使用的云服务相互兼容,并不互斥。 官方文档中API被分为了小程序端和服务端,一开始看过两端的API之后,感觉好像没有什么不同啊,在查阅相关资料以及实际开发中某些业务的处理总结出一些经验后才明白了两者的不同,下面给各位具体说说两者的不同之处,应该能帮助大家在使用云开发实战时少踩一点坑 初始化的不同 小程序端 全局声明一次 [代码]if (!wx.cloud) { console.error('请使用 2.2.3 或以上的基础库以使用云能力') } else { wx.cloud.init({ env:'xxx', traceUser: true, }) } [代码] 服务端 每个云函数中声明一次 [代码]const cloud = require('wx-server-sdk') cloud.init() [代码] 权限不同 小程序端 在小程序端可以选择直接操作数据库,但由于是前端操作数据库存在一些安全问题,有较多的权限限制,在云控制中可对每个集合进行权限设置,这也就是为什么有小伙伴在小程序端对某些数据进行更新,显示更新成功但并未更新数据,就是因为小程序端默认只能更新当前用户写入的数据 [图片] [代码]特别提醒:在小程序端使用创建者的权限对数据进行修改时一定要确保该集合中有_openid字段,否则系统在权限判断时是没有办法识别当前操作为创建者的,数据修改无法执行 [代码] 服务端 服务端拥有管理员的权限,对所有数据拥有读写权限 语法支持不同 小程序端 在微信开发者工具里,以及Android端手机(浏览器内核是QQ浏览器的X5),[代码]async[代码]/[代码]await[代码]是天然支持的,但 iOS 端手机在较低版本则不支持,因此需要引入额外的[代码]polyfill[代码]。可以在有使用[代码]async[代码]/[代码]await[代码] 的文件当中引入[代码]polyfill[代码]文件。 [代码]const runtime = require('相对路径/lib/runtime') [代码] 服务端 在云函数里,由于 Node 版本最低是 8.9,因此是天然支持 async/await 语法的 示例:获取约拍需求列表 [代码]//云函数入口文件 const cloud = require('wx-server-sdk') //初始化 cloud.init() //连接数据库 const db = cloud.database() async function getAll(){ const result = await db.collection('ypList') .orderBy('cameraInfo.launchTime','desc').where({}).get() return result } // 云函数入口函数 exports.main = async (event, context) => { //此处的action是用来判断该调用哪一个方法 if(event.action === 'getAll'){ return getAll() } } [代码] 结语 一个人手撸个全栈项目确实很辛苦,但收获也很多。至少对于小程序的实战开发更为熟练了,对MVVM的思想的理解也更加深刻了。技术发展得很快,学习一项技术如果不深入其本质,那么技术是学不完的。深入学习就是个解决问题的过程,或是帮助别人解决问题,或是借助他人的力量解决问题。目前在正在学习Vue、React、TypeScript等技术,后续会推出相关技术的项目解析文章,希望对于同样在学习的你有帮助。 [代码]特别说明:本项目已参加2019届中国高校计算机-微信应用开发赛完,开源至github,感兴趣的小伙伴可以看看 [代码] 附录 在此提供一些本项目涉及到的技术、工具等链接供大家学习使用 产品原型设计工具:墨刀 色彩搭配设计:配色网 在线作图:ProcessOn UI样式库:WeUI UI样式库:ColorUI 图标库:Iconfont阿里巴巴矢量图标库 开发工具:微信开发者工具 开发者工具:Vscode 腾讯云服务:身份证识别 腾讯云服务:智能图像 API文档:微信官方文档.小程序 技术文档:ES6 源码链接 https://github.com/TencentCloudBase/Good-practice-tutorial-recommended 如果你有关于使用云开发CloudBase相关的技术故事/技术实战经验想要跟大家分享,欢迎留言联系我们哦~比心! [图片]
2019-08-05 - 小程序开发之 web-view 的进阶玩法
背景 半年前写过一个项目,在京东手机的小程序里内嵌老罗的锤子发布会的活动页。前几天老罗又发布了他的加湿器,而这份关于锤子项目的迟到的总结,经过这几天在全网搜索的相关问题来看,依然有必要写一下。 本文主要从 web-view 与 JSSDK 的实现来展开,顺带过一下 web-view 的基础,最后在文末发放一些实用的小糖豆。 ok,废话不多说,开始吧。 web-view 中可用的 JSSDK 接口 1. web-view 的本质 与 JSSDK 我们已知,web-view 是闭环的小程序对外开启的一扇窗户,是小程序承载网页链接的容器。web-view 就像小程序里内置的浏览器内核,可以运行网页,其实 web-view 本质即是微信的 WKWebview 的实现。 区别:小程序框架系统包括两部分,视图层和逻辑层,两者对应的技术实现分别是 webview 和 JSCore;web-view本质上就是一个浏览器,承载网页,包括视图和逻辑实现。 [图片] 微信Webview 不仅应用于小程序的 web-view,也应用于公众号等所有微信里可以打开网页的位置。 微信Webview 不仅集成了普通 webkit 引擎的基础功能,还注入了微信JSBridge(JS-SDK)相关的脚本,提供给开发者更多高效的能力,如:拍照、语音、位置基于手机系统的能力;扫一扫、微信分享、卡券、支付等微信个性化能力。 而基于微信Webview 的 web-view 组件,除开放承载页面的功能外,也被赋予了一些 JS-SDK 的使用能力,尽管有一定的限制,但整理来看也使 web-view 的能力变得强大了。 2. web-view 中可用的 JSSDK 接口 本文从两个维度介绍 JSSDK 的接口。只简单列举几个,更多可支持的接口还请查看web-view的文档。 [图片] 1) 可用的通用JSSDK接口 接口模块 接口说明 接口名称 判断客户端是否支持js checkJSApi 图像接口 拍照或上传 chooseImage 图像接口 预览图片 previewImage 图像接口 上传/下载图片 uploadImage/downloadImage 图像接口 获取本地图片 getLocalImgData 音频接口 开始/停止录音 startRecord/stopRecord 音频接口 播放/暂停/停止语音 playVoice/pauseVoice/stopVoice 地理位置 使用内置地图/获取地理位置 getLocation/openLocation 蓝牙接口 开启/关闭/监听 start/stopSearchBeacons/onSearchBeacons 扫码 微信扫一扫 scanQRCode 卡券 列表/添加/打开 chooseCard/addCard/openCard 长按 小程序圆形码 智能接口 识别音频 translateVoice 2)与小程序相关的接口 除通用的JSSDK接口外,web-view 还支持和小程序跳转相关的接口,比如:navigateTo、redirectTo、switchTab、navigateBack,类似这种。具体写法都是加上 wx.miniProgram. 这样。 此外,关于小程序和web-view 的通信需要请求:wx.miniProgram.postMessage 方法,小程序侧进行侦听即可,具体方法可参看公众号的另一篇文章。 3)这些接口的可用性? 能够运行这些接口的最前提的条件就是,需要在小程序的环境里进行。那如何判断是否在小程序的环境里? 有两种方法: wx.miniProgram.getEnv [代码]wx.miniProgram.getEnv(function(res) { console.log(res.miniprogram) // true }) [代码] window.__wxjs_environment [代码]console.log(window.__wxjs_environment === 'miniprogram') [代码] web-view 如何使用 JSSDK 接口? 了解 web-view 可用的API 后,我们知道,在嵌入的H5 页面里,可以从相机里选择图片,或使用扫一扫的功能,那具体我们该如何实现呢? [图片] 微信公众平台给出了详尽的 JS-SDK 的实现方法,我们这里将几个当年踩过的要点给出。 1)绑定域名。 首先需要登录相关联的公众号,嗯!你没有看错,确实是公众号,(有很多人吐槽此事,但这确实是目前的事实。)登录后进入“公众号设置”-“功能设置”,填写“JS接口安全域名”。 [图片] 这一行为,建立了网页域名和 appId 之间的绑定关系,即,该appId 下可以打开这几个域名白名单里的网页。 同web-view 的业务域名配置一样,也需要将生成的校验文件拷贝到域名指向的 web 服务器的目录下。 2)签名的实现。 [图片] 签名是进入下一步的必要条件,这部分交由后端实现,了解它会提升你们的联调能力。 第一步,获取微信网页授权,拿到access_token值。 接口: https请求方式: [代码]GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET [代码] 参数 是否必须 说明 grant_type 是 获取access_token填写client_credential appid 是 第三方用户唯一凭证 secret 是 第三方用户唯一凭证密钥,即appsecret 公众号和小程序均可以使用 AppID 和 AppSecret 调用本接口来获取access_token。 AppID和AppSecret可在“微信公众平台-开发-基本配置”页中获得(需要已经成为开发者,且帐号没有异常状态)。 需要设置IP白名单:登录“微信公众平台-开发-基本配置”提前将服务器IP地址添加到IP白名单中,点击查看设置方法,否则将无法调用成功。小程序无需配置IP白名单。 入口: [图片] 具体设置: [图片] 第二步,获得jsapi_ticket。 用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket): [代码]https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi [代码] [代码]{ "errcode":0, "errmsg":"ok", "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA", "expires_in":7200 } [代码] 第三步,生成签名。 初始字段:noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分)。 [代码]noncestr=Wm3WZYTPz0wzccnW jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg timestamp=1414587457 url=http://mp.weixin.qq.com?params=value [代码] 中间过程:对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串。 [代码]jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value [代码] 生成签名:对生成的字符串作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。 [代码]0f9de62fce790f9a083d5c99e95740ceb90c27ed [代码] 3)当前页面注入权限验证配置。 所有需要使用 JSSDK 的页面必须首先注入配置信息,否则无法调用 JSSDK 的 API。在2)中我们有生成的签名和生成签名依赖的时间戳和随机串,这些都是我们进行配置的必要入参。具体如下: [代码]wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: '', // 必填,公众号的唯一标识 timestamp: , // 必填,生成签名的时间戳 nonceStr: '', // 必填,生成签名的随机串 signature: '',// 必填,签名 jsApiList: [] // 必填,需要使用的JS接口列表 }); [代码] 其中 apilist 是本页面里支持使用的 JSSDK 的 API,如果不声明,是不可以被调用使用的。 在下一步4)中会有一个实例。 4)万事俱备之后 config 接口是异步请求的,所以增加 ready 的接口来判定config 是否已经具备;同时,也提供了error 接口来实现 config 失败后的处理。 哈哈,以上基本就是 JSSDK 在小程序 web-view 里的打通实现,因为中间牵扯前后端的实现,看起来篇幅长且凌乱,不知道你还能不能看到这里呢? 如果你是前端童鞋,先跟你报个喜,绑定域名和实现签名这些都不是你需要做的事情,把这些丢给你的后端童鞋,让他们来实现吧。但我还是提个醒,这些我们有必要知道,因为你在打通 web-view 和 JSSDK 时,可能无从下手。 5)一个例子帮你搞定 以下我们用一个例子,把前端方案的实现串起来,给大家一个直观的展示。 引入微信 JSSDK 库: [图片] 请求后端生成签名的接口,获取相关config依赖的字段: [图片] 在ready后,使用 wx.chooseImage() 选择本地相册的图片。 [图片] ok,到此为止,我们基本把 JSSDK 在 web-view 里的应用实现介绍完了。 总的来说,这是一个看起来比较简单,但实现起来可能有很多不可知问题的事情,我们当年苦于不了解需要在公众号下申请各种资源,不知道使用哪个 JSSDK 走了许多弯路,后来还踩过设置IP白名单的问题。这些都还是比较好解决的,本文也基本把这些很详尽的做了描述。在签名的实现中,还会有很多问题,还好我们当时也根据文档附录中的指点一一解除。 长征路漫漫,还好有分享~ 糖豆:web-view 在实际场景中的应用问题 [图片] 在这些和 web-view 相伴相生的日子里,也逐渐总结了一些问题,大致分为了几类,列举如下: 1. 开放能力的问题: 是否开放支付,是否支持直播,是否支持h5里添加分享按钮? 答案否! 插件禁用 webview 组件 个人账号可以测试,无法上线 小程序无法读取 web-view 的 cookie。 小程序不可以触发模板消息 类似以上问题,都可以归结为小程序的 web-view 对 JSSDK 的开放能力,须严格按微信的JSSDK提供的能力检查是否可行。 能否嵌套了其他的第三方网站的页面?答案:一切h5里引入的链接都需要加业务域名。 喜报:支持打开相关联公众号的文章!! web-view 对外部网页的开放能力都是基于业务域名的白名单设置! 感谢开放关联公众号的打开权限,运营小伙伴可以玩起来。 2. 白屏问题? 紧接上文,强化一下业务域名配置问题。很多业务域名配置失败的直接症状就是白屏,然后给一句话,引用非业务域名。问题直接明了!那如何解决? 1)优先查看业务配置是否ok,是否是https等。2)不能解决问题继续查看其他证书,如TSL版本。具体可查阅小程序HTTPS证书的约定。 3. 跳转问题。 首页是web-view 时没有回退按钮?层级过深时,回退过多? 这个是经常被问到的问题,首页web-view 没有回退,官方没有给出很明确的说法;而非首页的 web-view 一旦路由跳转建立起来,web-view 里的路由就默认加入了路由栈中。有什么好办法解决? 这个已跟小程序没关系了,唤醒你在浏览器里的处理吧。 4. 缓存、网页不刷新问题? 这个也可以归结为浏览器里如何处理缓存的问题,类似浏览器网页中的缓存,可以通过时间戳。另外看看是不是你的CDN 缓存了内容? 5. 分享问题? 分享接口拿到的 webViewUrl 只是第一个 url,如果你的页面已经进入到它的子页面中,再次分享时,这时候你分享得到的 url 没有变化。这时候 你需要在子页面中使用 postMessage,捕获到当前页面的路径,传递给小程序。当用户触发分享时,只要读取消息队列最近的一条数据即可。 记得拼接参数时需要encodeURIComponent。 6 web-view 改宽高? 不可以。默认铺满整屏。web-view 和 其他UI组件的关系是互斥的,并且小程序会优先选择展示 web-view。如果你想放多个web-view,很抱歉,它默认只展示第一个web-view 的内容,还会在控制台给个大大的报错。 7 web-view 提示“未绑定网页开发者”? 没有开发该网页的权限!需要在公众号的开发者工具里绑定开发者微信号。 8 web-view 的校验文件是什么格式? 官方回答:是一个含有普通字符串的txt文件,只是一个随机的字符串,与appid无关。放心使用~ 好啦~以上是对 web-view 常见问题的总结,总结不敢保证全对,另外一定是会过时的,所以,这只是你遇到问题的一个思考方向,具体方案还要请参看小程序官方文档。 如果你有更好的方案,欢迎回复我们,超级无敌感谢! 最后,感谢你能够读到这里,也愿你不枉此行。 扩展阅读 [1] 微信JS-SDK说明文档 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115 [2] 微信小程序开放能力-web-view https://developers.weixin.qq.com/miniprogram/dev/component/web-view.html 文章原载于公众号:全栈探索。
2019-02-21 - 微信支付分通用化常见技术问题
商户小程序跳转支付分小程序问题: 1, Q:商户小程序跳转支付分小程序确认订单页报错“商户请求错误,错误码:4190”怎么解决? A:1)错误码271314190的原因:商户package中的服务订单号非法 2, Q:商户小程序跳转支付分小程序确认订单页报错“商户请求错误,错误码:4185”怎么解决? A:1)错误码271314185的原因:商户package为空,如果调的是调起支付分小程序-确认订单接口,请检查传入businessType或path是否按照文档要求规范传入 3, Q:商户小程序跳转支付分小程序确认订单页报错“商户请求错误,错误码:4186”怎么解决? A:1)错误码271314186的原因:商户package非法 4, Q:商户小程序跳转支付分小程序确认订单页报错“商户请求错误,错误码:4108”怎么解决? A:1)错误码271314108的原因:商户package中appid非法 2) 错误码271314108的原因:获取package中的appid与实际拉起支付分小程序时的appid不一致 5, Q:商户小程序跳转支付分小程序确认订单页报错报错“商户请求错误,错误码:4189”怎么解决? A:1)错误码271314189的原因:商户package中serverid非法 6, Q:商户小程序跳转支付分小程序报错“商户请求错误,错误码:4188”怎么解决? A:1)错误码271314188的原因:商户账号信息不匹配,或appid没有开通权限(传入的mchid、appid与实际service_id(服务ID)里配置不一致) 7, Q:商户小程序跳转支付分小程序报错“商户请求错误,错误码:3961”怎么解决? A:1)错误码271313961的原因:服务ID不正确或单号不存在 8, Q:商户小程序跳转支付分小程序(确认页、详情页,授权页)报错“体验版小程序无体验权限,请联系小程序管理员”怎么解决? A:1)检查下envVersion参数用的是否是release,目前只支持打开支付分小程序正式版 9, Q:商户小程序跳转支付分小程序确认订单页后,怎样确认用户点击的是确认按钮,而不是返回按钮? A:1)因为只有用户点击微信侧小程序页面内确认按钮或者返回按钮时,才会带上返回参数;如果用户点击页面左上角的返回图标按钮,则不会带上返回参数 ,所以如果用户点击了确认订单按钮,商户会在app.js中的onshow的res中收到query_id,商户可以使用query_id去查询订单状态,如果订单状态是USER_ACCEPTED:用户成功使用服务,表示用户点击的是确认按钮 10, Q:用户点击确认按钮后,支付分小程序返回商户小程序,商户没有收到返回参数,怎么处理? A:1)onshow的代码是定义在全局app.js中的,不能定义在页面中的js 11,Q:假如用户拉起支付分确认页面之后,没有点击确认,还可以再次请求吗 A:1)不可以,进入确认页面就已经绑定用户了,拉起支付分package只能使用一次 12,Q:商户小程序navigator组件点击后就直接跳转微信支付分小程序了,商户怎样实现在点击的时候商户先调用商户的接口创建支付分订单呢? A:1)这里的跳转小程序有两个方式:1. navigator组件2. api调用(wx.navigateToMiniProgram),如果商户有以上诉求,可以用api调用这种方式 13,Q:用户确认订单页授权不了支付分,点击返回,回到商户小程序产品页,然后商户支付系统调微信查询接口进行轮询查状态,比如10秒或者15秒,再跳到押金页进行押金支付,造成了用户体验不好,这里可以怎么优化? A:1)这里分为两种情况,一种点击左上角返回,这时没有extraData参数返回,商户可以让用户进行押金支付,一种点击页面下的返回,这时有extraData参数返回,商户需要调用查询接口判断下,因为用户没有点击确认使用服务按钮返回商户小程序,微信侧订单状态不会更新为USER_ACCEPTED,这里商户一直轮询来查询微信侧的订单状态并不会改变,所以只要返回商户小程序,用户就没有入口确认使用服务,商户查到订单状态不为USER_ACCEPTED时直接进行押金支付即可 14,Q:支付分小程序返回商户小程序后,场景值1038,appid也可以获取到,但是到我们的小程序后无论哪个页面,从后台切到前台,场景值1038,appid都不会变 ,这就会造成前端无法准确识别是从后台来的还是支付分小程序来的。 A:1)原因请参看文档链接https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/scene.html,这里建议商户通过返回值1038+appid+extradata值主动查询的方式,如果没有用户确认订单状态,就出押金入口 15,Q:商户小程序跳转支付分小程序(确认页、详情页,授权页)报错“未通过申请,当前服务未上线? A:1)检查测试微信是否开通白名单,提供服务id和微信号联系运营开通白名单 [图片] 16, Q:商户小程序跳转支付分小程序(详情页)报错“无法查看他人的服务订单”怎么解决? A:1)商户跳转的订单号不属于这个微信用户的订单号,商户内部订单号关联可能混乱了,请商户自行检查 17, Q:商户小程序、jsapi、APP跳转支付分小程序(确认页、详情页、授权页)报错“系统繁忙,请重新尝试”怎么解决? A:1)检查下商户号和appid是否入驻支付分(必须和申请支付分服务权限时提供的信息保持一致) 2)检查下extraData参数的子参数是否少了字段 3)检查下签名是否正确,这里的sign是前端自己的,不能用后台的sign,可以让后台按前端的参数协助生成下,商户key要参与签名,并且key用的是api秘钥,不是apiv3秘钥,请注意api秘钥是32位的。签名方式和api秘钥设置路径参看文档指引https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3,商户可以用在线工具自行校验,工具地址https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1 4)跳转支付分小程序的appid要和创建订单请求的appid保持一致 5)检查下timestamp是否是string类型 18,Q:开启服务支付分小程序android返回了openid,ios不返回,sdk能力没有对齐吗? A:1)目前android确实是会返回,但建议商户自己可以维护一个唯一字段来维护。 19,Q:开启服务支付分小程序返回errcode为-2是什么意思? A:1)-2表示用户是通过左上角返回按钮返回的 20,Q:商户小程序跳转支付分小程序报错“非法的参数,请返回商户重新发起”怎么解决? A:1)检查下extraData参数的子参数里是不是少了mch_id参数 2)检查下timestamp是否是string类型 21,Q:调起支付分小程序授权页后展示解除授权页的原因是什么? A:同一用户微信号在商户同一服务ID下重复签约会直接拉起支付分解除授权页。 商户h5跳转支付分小程序问题: 1, Q:商户小程序跳转支付分小程序确认订单页后,怎样确认用户点击的是确认按钮,而不是返回按钮? A:1)因为只有用户点击微信侧小程序页面内确认按钮或者返回按钮时,才会带上返回参数;如果用户点击页面左上角的返回图标按钮,则不会带上返回参数 ,所以如果用户点击了确认订单按钮,商户会在app.js中的onshow的res中收到query_id,商户可以使用query_id去查询订单状态,如果订单状态是USER_ACCEPTED:用户成功使用服务,表示用户点击的是确认按钮 2,Q:假如用户拉起支付分确认页面之后,没有点击确认,还可以再次请求吗 A:1)不可以,进入确认页面就已经绑定用户了,拉起支付分package只能使用一次 3,Q:用户确认订单页授权不了支付分,点击返回,回到商户小程序产品页,然后商户支付系统调微信查询接口进行轮询查状态,比如10秒或者15秒,再跳到押金页进行押金支付,造成了用户体验不好,这里可以怎么优化? A:1)这里分为两种情况,一种点击左上角返回,这时没有extraData参数返回,商户可以让用户进行押金支付,一种点击页面下的返回,这时有extraData参数返回,商户需要调用查询接口判断下,因为用户没有点击确认使用服务按钮返回商户小程序,微信侧订单状态不会更新为USER_ACCEPTED,这里商户一直轮询来查询微信侧的订单状态并不会改变,所以只要返回商户小程序,用户就没有入口确认使用服务,商户查到订单状态不为USER_ACCEPTED时直接进行押金支付即可 4,Q:商户H5跳转支付分小程序(开启页)报错“请在合法渠道打开页面”? A:1)检查下调错接口没,小程序,app,h5应调对应场景的接口 2)检查下queryString是对值做urlencode编码,不是对整个url编码 5,Q:开启服务支付分小程序返回errcode为-2是什么意思? A:1)-2表示用户是通过左上角返回按钮返回的 6, Q:商户h5跳转支付分小程序(确认页、详情页、授权页)报错“商户请求错误,错误码:4188”怎么解决? A:1)错误码271314188的原因:商户账号信息不匹配,或appid没有开通权限 7,Q:调起支付分小程序授权页后展示解除授权页的原因是什么? A:同一用户微信号在商户同一服务ID下重复签约会直接拉起支付分解除授权页。 商户app跳转支付分小程序问题: 1, Q:商户小程序跳转支付分小程序确认订单页后,怎样确认用户点击的是确认按钮,而不是返回按钮? A:1)因为只有用户点击微信侧小程序页面内确认按钮或者返回按钮时,才会带上返回参数;如果用户点击页面左上角的返回图标按钮,则不会带上返回参数 ,所以如果用户点击了确认订单按钮,商户会在app.js中的onshow的res中收到query_id,商户可以使用query_id去查询订单状态,如果订单状态是USER_ACCEPTED:用户成功使用服务,表示用户点击的是确认按钮 2,Q:假如用户拉起支付分确认页面之后,没有点击确认,还可以再次请求吗 A:1)不可以,进入确认页面就已经绑定用户了,拉起支付分package只能使用一次 3,Q:用户确认订单页授权不了支付分,点击返回,回到商户小程序产品页,然后商户支付系统调微信查询接口进行轮询查状态,比如10秒或者15秒,再跳到押金页进行押金支付,造成了用户体验不好,这里可以怎么优化? A:1)这里分为两种情况,一种点击左上角返回,这时没有extraData参数返回,商户可以让用户进行押金支付,一种点击页面下的返回,这时有extraData参数返回,商户需要调用查询接口判断下,因为用户没有点击确认使用服务按钮返回商户小程序,微信侧订单状态不会更新为USER_ACCEPTED,这里商户一直轮询来查询微信侧的订单状态并不会改变,所以只要返回商户小程序,用户就没有入口确认使用服务,商户查到订单状态不为USER_ACCEPTED时直接进行押金支付即可 4,Q:商户app、小程序、公众号跳转支付分小程序(授权页、确认订单页、订单详情页)报错“暂无法使用此服务,微信支付分逐步开放中”? A:1)没在微信白名单内,配置微信白名单指引参考:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter3_1_5.shtml 2)在白名单内仍然不行,请换个实名了的并绑银行卡了的账号来申请白名单再测试,这账号要经常使用微信支付并且无违规记录,以免综合评估不通过 [图片] 5,Q:开启服务支付分小程序返回errcode为-2是什么意思? A:1)-2表示用户是通过左上角返回按钮返回的 6,Q:商户app调用openBusinessView接口返回errcode为0是什么意思? A:1)商户app调用openBusinessView接口返回errcode为0只代表调用接口成功,支付分申请是否成功和这里无关 7,Q:商户app跳转支付分小程序报错“非法的参数,请返回商户重新发起”怎么解决? A:1)检查下query参数的子参数是不是少了mch_id参数 2)检查下timestamp是否是string类型 8, Q:商户app跳转支付分小程序(确认页、详情页、授权页)报错“商户请求错误,错误码:4188”怎么解决? A:1)错误码271314188的原因:商户账号信息不匹配,或appid没有开通权限 9,Q:调起支付分小程序授权页后展示解除授权页的原因是什么? A:同一用户微信号在商户同一服务ID下重复签约会直接拉起支付分解除授权页。 10,Q:调用跳转微信支付分小程序接口调不起来微信客户端,手动切换到微信客户端才能正常跳转到支付分小程序是什么原因? A:请检查当前使用的opensdk版本,建议使用最新的opensdk版本后再进行重试。opensdk资源下载地址:https://developers.weixin.qq.com/doc/oplatform/Downloads/iOS_Resource.html 查询用户是否可使用服务问题: 1,Q:app怎么获取用户openid? A:1)可以使用微信OAuth2.0登陆方式,参看app获取openid文档指引https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317851&token=&lang=zh_CN 2,Q:公众号h5怎么获取用户openid? A:1)参看文档指引https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html 3,Q:小程序怎么获取用户openid? A:1)参看文档指引https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html 支付分接口问题: 1,Q:创建支付分订单返回{"code":"NO_AUTH","message":"商户暂无权限使用此服务"}? A:1)检查商户号和appid是否和申请支付分权限时填写的appid和商户号一致(必须和申请支付分服务权限时提供的信息保持一致) 2)如果商户开通的是免确认订单权限,创建订单时need_user_confirm只能传false,如果商户开通的是含确认订单权限,创建订单时need_user_confirm只能传true 3)如果商户开通的是免确认订单权限,创建订单时风险金名称name只能用先享模式,如果商户开通的是需确认订单权限,创建订单时风险金名称name只能用先免模式 2,Q:创建支付分订单返回{"code":"PARAM_ERROR","message":"订单风险金额不符合要求"}? A:1)检查商户号开通的是哪种模式的权限,目前只有需确认模式和免确认模式,可以联系微信侧运营确认和配置 2)免确认模式只能传:“ESTIMATE_ORDER_COST:预估订单费用” 3)需确认模式可传先免模式中的:“DEPOSIT:押金,ADVANCE:预付款,CASH_DEPOSIT:保证金”任意一个 3,Q:创建支付分订单返回{"code":"INVALID_REQUEST","message":"非支付分通用场景的订单"}? A:1)检查订单是否用的通用化文档接口创建的订单,order_id为100000开头是通用化订单,order_id为000开头是非通用化订单 4,Q:支付分开启/解除授权服务回调通知、确认订单回调通知、支付成功回调通知一直收不到该怎么处理? A:1)没设置apiv3秘钥是不发送回调的,需要在商户平台设置APIv3密钥,服务商模式下需要用服务商商户号登录服务商平台设置apiv3密钥,详情参考文档指引。http://kf.qq.com/faq/180830E36vyQ180830AZFZvu.html 5,Q:需确认订单模式,同一个用户可以下多少笔免押订单,如果该用户有未完结的支付分订单,会不会影响用户下一笔订单免押 A:1)同一个用户可以确认免押订单进行中的笔数是3笔,待支付的笔数是1笔(未完结&未支付的订单笔数,产品策略,可能会调整);如超过限制则需交押金使用 6,Q:免确认订单模式创建支付分订单报错{"code":"INVALID_REQUEST","message":"综合评估不通过"}是什么原因? A:1)免确认流程创单用户被不对外风控拦截 7,Q:商户调用完结支付分订单接口,金额传0元会有支付成功回调吗? A:1)有收款成功回调 8,Q:商户调用修改订单金额接口,金额传0元会有支付成功回调吗? A:1)有收款成功回调 9,Q:商户调用同步服务订单信息接口,会有支付成功回调吗? A:1)没有收款成功回调 10,Q:商户调用完结支付分订单返回{"code":"INVALID_REQUEST","message":"付费项目size不在1,100之间"}? A:1)可检查下post_payments后付费项目参数是否符合文档要求规范传参 11,Q:apiV3签名失败,报错{"code":"SIGN_ERROR","message":"错误的签名,验签失败"} A:签名要注意: 1) 签名与生成Authorization用的同一个时间戳跟随机串 2) 构造签名串时,里面的url不需要ToLowCase(),不用UrlEncode(),商户请求的url后缀是什么,签名用的url后缀就是什么 3) 查询订单使用的是GET,构建签名串时,里面用的请求报文为空(但是那个换行符还是要有哈) 4)检查证书和商户号是否正确,这里用申请的商户号和此商户号的证书(特约商户别用错成服务商的证书了) 5) 具体可参考该文档:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay7_1.shtml 12,Q:创建支付分订单,报错{"code":"INVALID_REQUEST","message":"存在未完结订单\n"}是什么原因? A:1)是否待完结的订单超过限制(3条),待支付的订单超过限制(1条),用户可进入微信点击【我->钱包->支付分->全部订单类型->进行中】,进行查询。 13,Q:查询支付分订单报错{"code":"PARAM_ERROR","message":"参数或字段"商户服务订单号"不接受设置多次值,但是被设置了多次。请检查请求数据包中(包括但不限于URL/QueryString/Header/Cookie/包体)中是否多次设置了此字段"}是什么原因? A:1)商户服务订单号(out_order_no)传参有误,该参数只需在请求URL中传参,无需再次在body中的json传参 14,Q:支付分的订单是否支持退款?用哪个接口发起退款? A:1)支持,需用V2或者V3版本的申请退款接口发起。 15,Q:支付分的订单能否用商户服务单号发起退款 A:1)不支持,需要用支付分微信支付交易单号( transaction_id)发起退款, 只有单据状态为USER_PAID,且收款成功渠道为支付分渠道,收款金额大于0,才会返回微信支付交易单号。 16,Q:调用支付分创单接口报错返回“mch_id和appid未绑定”如何处理? A:1)请商户自行检查mch_id和appid是否有对应的绑定关系。绑定步骤参考:https://kf.qq.com/faq/1801116VJfua1801113QVNVz.html 17,Q:完结支付分报错返回“实际结束时间不能晚于使用完结接口的时间”如何处理? A:1)请保证接口传入的服务结束时间<调用接口时间。 2)请确认调用方本地时间或服务器是否准确。 18,Q:创建支付分订单返回:{"code":"INVALID_REQUEST","message":"待支付订单过多"} A:用户待支付订单超出限制,需用户完成待支付订单后才可创建新的支付分订单。默认限制待支付1笔,但策略可能会有调整,请以实际情况为准 19,Q:为什么对账单中以及商户平台看到的商户订单号与创建订单时传入的商户服务单号不一致? A:商户订单号是微信支付分在轮询扣款时主动生成,商户服务单号是商户在调用创建支付分订单时传入,所以不一样是正常的。具体可下载支付分对账单详情了解 20,Q:为什么商户后台看到很多订单的交易状态都是已撤销? A:支付分在轮询扣款失败时产生,商户侧应以交易对账单的交易成功数据或支付分查单接口查询到的状态为准,商户平台展示撤销的订单商户侧可不用关注。 [图片] 21:Q:对账单中没有商户服务单号,商户应该如何对账? A:可通过对账单中的微信订单号及商户号关联对账单文件中商户数据包里的第三个数据,第三个数据就是创单时传入的商户服务单号。 [图片] 22:Q:支付分的账单示例可以在哪里下载? A:1)支付分账单示例 23:Q:支付分查询用户授权记录接口返回{"code":"ORDER_NOT_EXIST","message":"请求操作的授权记录不存在"}是什么原因? A:这个是正常的返回,用户从未产生授权记录:返回状态码 404,错误码为ORDER_NOT_EXIST,用户授权过后解除授权,当前未授权时:返回状态码200,返回参数中”授权状态 authorization_state“为【UNAVAILABLE】。 24:Q:调用支付分完结接口报错返回"{"code":"PARAM_ERROR","message":"订单重入参数校验失败"} "如何处理? A:当前这次请求改变了第一次调用完结成功传入的参数,也就是首次成功调用这个接口后,后续再次请求时改变了首次请求成功的入参,请商户自行确认下订单状态,如果是已完结待支付的状态,建议商户等待微信侧轮询扣款或定时查单即可,扣款失败后微信侧会按照一定频率进行重试扣款,直到成功。重复调用完结订单接口并不会起到催收作用,所以重复完结并没有任何意义。 25;Q:调用支付分创单或创单结单合并API报错返回{"code":"APPID_MCHID_NOT_MATCH","message":"总金额超过此服务的服务风险金额"} A:创单或创单结单合并传入的总金额(total_amount)超过了服务风险金额。 26;Q:用户微信被封了,导致微信支付分订单无法收款成功,需要怎么处理。 A:商户侧可通过非支付分渠道进行收款,收款成功之后可调同步订单接口来结束该订单。 27;Q调用完结订单接口报错返回”服务真实结束时间非法“如何解决? A:请检查完结时传入的结束时间格式是否与创单传入预计的结束时间格式一致。 28;用户微信上显示有进行中的支付分订单,点击进去没有查看到任何订单信息需要怎么处理? A: 用户实名下有多个微信号,订单在用户的另一个微信号上,可让用户自行核实 29;Q:{"code":"INVALID_REQUEST","message":"非支付分通用接口创建的订单,请使用对应的行业化接口"} A:老接口创建的订单只能用老的支付分接口完结、取消等操作。 30;Q:用户微信被封了,导致微信支付分订单无法收款成功,需要怎么处理。 A:商户侧可通过非支付分渠道进行收款,收款成功之后可调同步订单接口来结束该订单。 31;Q:跳转支付分小程序-授权返回页面停留时间过长,请重试该如何解决? A:传入的apply_permissions_token 失效了,预授权获取到的apply_permissions_token 有效期只有一个小时。 32;Q:用户开通支付分返回暂无法查看微信支付分,当前未满足查看条件,请保持稳定的实名信息,多使用微信支付进行消费是什么原因? A: 用户不满足使用支付分的条件,请保持稳定的实名信息,多使用微信支付进行消费 33;Q:支付分查询订单接口返回{"code":"INVALID_REQUEST","message":"与现有记录冲突,且service_id与已存在记录不同"}是什么原因? A:同一商户创建和查询支付分订单时的service_id不一致导致,查询时的service_id需和创单时保持一致 34;Q:用户在微信内解约支付分协议或商户主动调解约接口解约,接收解约回调地址在哪里配置? A:1)解约回调地址目前默认取的是用户授权成功的回调地址,即请求预授权时传入的notify_url 35;Q:微信支付分是否支持使用代金券? A:1)目前完结接口的goods_tag 只支持全场券 36;Q:调用完结订单接口报错:实际服务开始时间不得早于或等于创建订单填写的服务开始时间 A:1)完结时传的实际服务开始时间不能<=创单传入的服务开始时间,如与创建订单填写的“服务开始时间”一致时,不填写。请调整时间后重试。 37;Q:调用完结接口报错返回:创单时填写了服务开始地点,结单才能传入服务结束地点。 A:1)只有创单时传了start_location(服务开始地点),完结的时候才可以传入end_location(服务结束位置) 38;Q:调用同步接口报错返回:用户实际付款成功时间不能早于商户“完结订单"时间 A:1)请求传入的收款成功时间paid_time 需要>完结订单时间 配置及其他问题: 1,Q:模版消息的内容是怎么生成的? A:1)模版消息的内容是商户入驻的时候指定的。 2,Q:联系公众号在哪里设置? A:1)请联系微信支付的运营同学填写入驻申请表配置。 3,Q:如果支付分订单扣款失败,微信支付会重试扣款吗? A:1)微信支付会按照一定频率持续扣款直到成功 4,Q:apiv3秘钥怎么设置? A:1)请联系微信侧运营帮忙开通商户后台设置入口,然后参照指引文档设置http://kf.qq.com/faq/180830E36vyQ180830AZFZvu.html 5,Q:开通支付分输入密码时有超时时长吗? A:1)输入密码有15分钟有效期,超时后会让用户重新开通,重新输入密码 6,Q:押金什么时候退回? A:1)零钱支付10min以内到账,银行卡支付3天内到账 7,Q:后台没看到apiv3秘钥设置按钮,怎么解决? A:1)需要联系微信侧开通白名单才会出现apiv3秘钥设置按钮 8,Q:安卓手机有个物理返回键,点击这个物理返回键,支付分小程序会有extraData参数返回吗? A:1)不会 9,Q:appid-mchid在哪里设置? A:1)请联系微信支付的运营同学填写入驻申请表配置。 10,Q:服务名称在哪里设置? A:1)请联系微信支付的运营同学填写入驻申请表配置。 11,Q:服务logo在哪里设置? A:1)请联系微信支付的运营同学填写入驻申请表配置。 12,Q:行业归属在哪里设置? A:1)请联系微信支付的运营同学填写入驻申请表配置。 13,Q:分数标准在哪里设置? A:1)请联系微信支付的运营同学填写入驻申请表配置。 14,Q:权益说明在哪里设置? A:1)请联系微信支付的运营同学填写入驻申请表配置。 15,Q:用户开启服务成功通知的回调地址在哪里设置? A:1)请联系微信支付的运营同学填写入驻申请表配置。 16,Q:service_id怎么获得? A:1)请联系微信侧运营协助配置获取 17,Q:商户登录微信商户管理后台,为什么看不见“证书升级”的按钮? A:1)权威CA证书目前在灰度中,如果商户看不见证书升级按钮,可以把商户号发给微信侧运营配置升级入口白名单。 18,Q:调用支付分接口是否必须要升级证书,证书升级会影响交易吗? A:1)调用支付分接口必须升级证书,只影响原来调用接口的时候使用了API证书的接口,证书升级之后,需要在14天内替换原来旧的API证书,详情参看文档指引http://kf.qq.com/faq/180824BrQnQB180824m6v2yA.html 19,Q:哪里可以查询到商户私钥证书序列号? A:1)管理员帐号登录微信商户管理后台,在API安全里面点击“查看证书” 20,Q:支付分支持使用分账吗? A:1)支持,商户需要在完结订单时传入分账标识profit_sharing,然后再调用分账的接口进行分账 21,Q:支付分商户后台上的商户订单号是商户传的out_order_no字段吗 A:1)不是,微信商户平台上支付分订单中的商户订单号是由微信侧生成的,与商户创单时的商户服务订单号无关 22,Q:支付分支持下载对账单接口吗? A:1)支持 23,Q:退款金额有包括企业打款吗? A:不包含,企业打款不算退款 24,Q:小程序BUG怎么上传日志给微信侧定位问题? A:客户端上传日志步骤: 1)ios:“通讯录”--右上角“添加好友”按钮--在输入框里输入“:up”--“上传日志” 2)Android:“我”--“设置”--“帮助与反馈”--右上角“工具”按钮--“上传日志” 25,Q:怎样调用支付分小程序、h5的wx.openBusinessView和wx.navigateToMiniProgram,wx.openBusinessView接口不成功,报错devchongdianviph5.winbons.com“err_msg":"openBusinessView:fail_the permission value is offline verifying"怎么解决? A:1)按步骤引入,具体参数文档指引https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#3 [图片] 26,Q:用户微信零钱里有钱,但扣款失败是什么原因? A:这个case是支付分轮询到银行卡上了,银行还在处理中未明确结果,暂时无法轮询零钱,辛苦指引一下用户,在微信-我-支付-右上角...-扣费服务-微信支付分免密支付-扣款方式,修改为零钱优先,然后再到,微信-我-支付-钱包-支付分-订单列表里找到这笔待支付订单,重试扣款 27,Q:你好,请问支付分相关接口,每个接口大概时间响应是多长,建议的超时时间是多少? A:大部分API请求会在500ms内返回,商户可以参考该数值,并考虑网络耗时配置超时时间。 28, Q:android手机上商户app跳转支付分小程序不能原路返回,apple手机可以,怎么解决? A:1)检查下是不是少配置了android:taskAffinity,android:launchMode等参数,请参看文档https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=1417751808&token=&lang=zh_CN [图片] 29,Q:商户跳转支付分小程序报“当前服务未上线”,怎么解决? A:1)检查是否更换了serviceid 2)是否使用的测试白名单中的微信号,请联系微信侧运营开通白名单 30,Q:商户如果有3个端:h5、app、小程序,对应的openid是不同的,怎么实现相同微信号,在某个端已经授权,在其他端可以共同享有授权的方案? A:1)方案一:用户微信授权是绑定在唯一的服务id下的,每个商户的服务id不同,商户需要将商户号和appid配置在同个服务id下,即可享受不同场景的共同授权 31:Q:如果用户零钱余额不足的情况下,支付分是否会尝试从客户绑定的其它卡种扣费? 如果用户默认的扣款方式扣款失败,微信会依次按以下顺序扣费:零钱、信用卡、借记卡。 32:Q:订单风险金额该怎么传比较好? A:1)、订单风险金额不宜比服务订单结算总金额高过多:订单风险金额越高,可获得权益的用户将越少,用户可享受权益的通过率将越低。 2)、订单风险金额不宜比服务订单结算总金额低过多:对于用户是否能享受权益,是基于订单风险金额来评估的,因此,订单风险金额预估比服务订单结算总金额越低,收款成功率可能会越低。因此,尽量准确、合理预估订单风险金额,以保证通过率和收款成功率 3)、完结订单金额小于或等于风险金额,但必须小于此服务风险金额的最大值 4)、风险金额必须小于此服务风险金额的最大值
2022-03-30 - [填坑手册]小程序Canvas生成海报(一)--完整流程
[图片] 海报生成示例 最近智酷君在做[小程序]canvas生成海报的项目中遇到一些棘手的问题,在网上查阅了各种资料,也踩扁了各种坑,智酷君希望把这些“填坑”经验整理一下分享出来,避免后来的兄弟重复“掉坑”。 [图片] 原型图 这是一个大致的原型图,下面来看下如何制作这个海报,以及整体的思路。 [图片] 海报生成流程 [代码片段]Canvas生成海报实战demo demo的微信路径:https://developers.weixin.qq.com/s/Q74OU3m57c9x demo的ID:Q74OU3m57c9x 如果你装了IDE工具,可以直接访问上面的demo路径 通过代码片段将demo的ID输入进去也可添加: [图片] [图片] 下面分享下主要的代码内容和“填坑现场”: 一、添加字体 https://developers.weixin.qq.com/miniprogram/dev/api/canvas/font.html [代码]canvasContext.font = value //示例 ctx.font = `normal bold 20px sans-serif`//设置字体大小,默认10 ctx.setTextAlign('left'); ctx.setTextBaseline("top"); ctx.fillText("《智酷方程式》专注研究和分享前端技术", 50, 15, 250)//绘制文本 [代码] 符合 CSS font 语法的 DOMString 字符串,至少需要提供字体大小和字体族名。默认值为 10px sans-serif 文字过长在canvas下换行问题处理(最多两行,超过“…”代替) [代码]ctx.setTextAlign('left'); ctx.setFillStyle('#000');//文字颜色:默认黑色 ctx.font = `normal bold 18px sans-serif`//设置字体大小,默认10 let canvasTitleArray = canvasTitle.split(""); let firstTitle = ""; //第一行字 let secondTitle = ""; //第二行字 for (let i = 0; i < canvasTitleArray.length; i++) { let element = canvasTitleArray[i]; let firstWidth = ctx.measureText(firstTitle).width; //console.log(ctx.measureText(firstTitle).width); if (firstWidth > 260) { let secondWidth = ctx.measureText(secondTitle).width; //第二行字数超过,变为... if (secondWidth > 260) { secondTitle += "..."; break; } else { secondTitle += element; } } else { firstTitle += element; } } //第一行文字 ctx.fillText(firstTitle, 20, 278, 280)//绘制文本 //第二行问题 if (secondTitle) { ctx.fillText(secondTitle, 20, 300, 280)//绘制文本 } [代码] 通过 ctx.measureText 这个方法可以判断文字的宽度,然后进行切割。 (一行字允许宽度为280时,判断需要写小点,比如260) 二、获取临时地址并设置图片 [代码]let mainImg = "https://demo.com/url.jpg"; wx.getImageInfo({ src: mainImg,//服务器返回的图片地址 success: function (res) { //处理图片纵横比例过大或者过小的问题!!! let h = res.height; let w = res.width; let setHeight = 280, //默认源图截取的区域 setWidth = 220; //默认源图截取的区域 if (w / h > 1.5) { setHeight = h; setWidth = parseInt(280 / 220 * h); } else if (w / h < 1) { setWidth = w; setHeight = parseInt(220 / 280 * w); } else { setHeight = h; setWidth = w; }; console.log(setWidth, setHeight) ctx.drawImage(res.path, 0, 0, setWidth, setHeight, 20, 50, 280, 220); ctx.draw(true); }, fail: function (res) { //失败回调 } }); [代码] 在开发过程中如果封面图无法按照约定的比例(280x220)给到: 那么我们就需要处理默认封面图过大或者过小的问题,大致思路是:代码中通过比较纵横比(280/220=1.27)正比例放大或者缩小原图,然后从左上切割,竟可能保证过高的图是宽度100%,过宽的图是高度100%。 在canvas中draw图片,必须是一个(相对)本地路径,我们可以通过将图片保存在本地后生成的临时路径。 微信官方提供两个API: wx.downloadFile(OBJECT)和wx.getImageInfo(OBJECT)。都需先配置download域名才能生效。 三、裁切“圆形”头像画图 [代码]ctx.save(); //保存画图板 ctx.beginPath()//开始创建一个路径 ctx.arc(35, 25, 15, 0, 2 * Math.PI, false)//画一个圆形裁剪区域 ctx.clip()//裁剪 ctx.closePath(); ctx.drawImage(headImageLocal, 20, 10, 30, 30); ctx.draw(true); ctx.restore()//恢复之前保存的绘图上下文 [代码] 使用图形上下文的不带参数的clip()方法来实现Canvas的图像裁剪功能。该方法使用路径来对Canvas话不设置一个裁剪区域。因此,必须先创建好路径。创建完整后,调用clip()方法来设置裁剪区域。 需要注意的是裁剪是对画布进行的,裁切后的画布不能恢复到原来的大小,也就是说画布是越切越小的,要想保证最后仍然能在canvas最初定义的大小下绘图需要注意save()和restore()。画布是先裁切完了再进行绘图。并不一定非要是图片,路径也可以放进去~ 小程序 canvas 裁切BUG [代码]ctx.setFillStyle("#fff"); ctx.fillRect(0, 0, 320, 500); //第一个填充矩形 wx.downloadFile({ url: headUri, success(res) { ctx.beginPath() ctx.arc(50, 50, 25, 0, 2 * Math.PI) ctx.clip() ctx.drawImage(res.tempFilePath, 25, 25); //第二个填充图片 ctx.draw() ctx.restore() ctx.setFillStyle("#fff"); ctx.fillRect(0, 0, 320, 500); ctx.draw(true) ctx.restore() } }) [代码] clip裁切这个功能,如果有超过一张图片/背景叠加,则裁切效果失效。 错误参考:http://html51.com/info-38753-1/ 四、将canvas导出成虚拟地址 [代码]wx.canvasToTempFilePath({ fileType: 'jpg', canvasId: 'customCanvas', success: (res) => { console.log(res.tempFilePath) //为canvas的虚拟地址 } }) res: { errMsg: "canvasToTempFilePath:ok", tempFilePath: "http://tmp/wx02935bb29080a7b4.o6zAJswFAuZuKQ5NZfPr….cGnD1a02PlVC0b3284be3a41d08986c2477579a5fd8e.jpg" } [代码] 这里需要把canvas里面的内容,导出成一个临时地址才能保存在相册,比如: http://tmp/wx02935bb29080a7b4.o6zAJswFAuZuKQ5NZfPr5UfJVR4k.cGnD1a02PlVC0b3284be3a41d08986c2477579a5fd8e.jpg 五、询问并获取访问手机本地相册权限 [代码]wx.getSetting({ success(res) { console.log(res) if (!res.authSetting['scope.writePhotosAlbum']) { //判断权限 wx.authorize({ //获取权限 scope: 'scope.writePhotosAlbum', success() { console.log('授权成功') //转化路径 self.saveImg(); } }) } else { self.saveImg(); } } }) [代码] 判断是否有访问相册的权限,如果没有,则请求权限。 六、保存到用户手机本地相册 [代码]wx.saveImageToPhotosAlbum({ filePath: res.tempFilePath, success: function (data) { wx.showToast({ title: '保存到系统相册成功', icon: 'success', duration: 2000 }) }, fail: function (err) { console.log(err); if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") { console.log("当初用户拒绝,再次发起授权") wx.openSetting({ success(settingdata) { console.log(settingdata) if (settingdata.authSetting['scope.writePhotosAlbum']) { console.log('获取权限成功,给出再次点击图片保存到相册的提示。') } else { console.log('获取权限失败,给出不给权限就无法正常使用的提示') } } }) } else { wx.showToast({ title: '保存失败', icon: 'none' }); } }, complete(res) { console.log(res); } }) [代码] 保存到本地需要一定的时间,需要加一个loading的状态。 七、关于组件中引用canvas [代码]let ctx = wx.createCanvasContext('posterCanvas',this); //需要加this [代码] 在components中canvas无法选中的问题: 在components自定义组件下,当前组件实例的this,表示在这个自定义组件下查找拥有 canvas-id 的 <canvas> ,如果省略则不在任何自定义组件内查找。
2021-09-13 - 小程序构建骨架屏的探索
首屏 一般情况下,在首屏数据未拿到之前,为了提升用户的体验,会在页面上展示一个loading的图层,类似下面这个 [图片] 其中除了菊花图以外网上还流传这各种各样的loading动画,在PC端上几乎要统一江湖了,不过最近在移动端上面看到不同于菊花图的加载方式,就是这篇文章需要分享的Skeleton Screen,中文称之为"骨架屏" 概念 A skeleton screen is essentially a blank version of a page into which information is gradually loaded. 在H5中,骨架屏其实已经不是什么新奇的概念了,网上也有各种方案生成对应的骨架屏,包括我们经常使用的知乎、饿了么、美团等APP都有应用骨架屏这个概念 图片来源网络,侵删 [图片] 方案 先从H5生成骨架屏方案开始说起,总的来说H5生成骨架屏的方案有2种 完全靠手写HTML和CSS方式给每个页面定制一套骨架屏 利用预渲染的方式生成静态骨架屏 第一套方案,毫无疑问是最简单最直白的方式,缺点也很明显,假如页面布局有修改的话,那么除了修改业务代码之外还需要额外修改骨架屏,增加了维护的成本。 第二套方案,一定程度上改善了第一套方案带来的维护成本增加的缺点,主要还是使用工具预渲染页面,获取到DOM节点和样式,保留页面结构,覆盖样式,生成灰色块盖在原有文本、图片或者是canvas等节点上面,最后将生成的HTML和CSS打包出来,就是一个带有骨架屏的页面。最后再利用webpack工具将生成的骨架屏插入到HTML里面,详细的话可以看看饿了么的分享,这里就不多描述了。 调研了下H5生成骨架屏的方案,对于小程序生成骨架屏的方案也有了一个大致的想法,主要有2个难点需要实现 预渲染 获取节点 预渲染 再说回饿了么提供的骨架屏的方案,使用 puppeteer 渲染页面(或者使用服务端渲染,vue或者react都有提供相应的方案),拿到DOM节点和样式,这里有一点需要注意的是,页面的渲染是需要初始化的数据,数据的来源可以是初始化的data(vue)或者mock数据,当然小程序是无法直接使用 puppeteer 来做预渲染(有另外的方案可以实现),需要利用小程序初始化的 data + template 渲染之后得到一个初始化结构作为骨架屏的结构 [代码]//index.js Page({ data: { motto: 'Hello World', userInfo: { avatarUrl: 'https://wx.qlogo.cn/mmopen/vi_32/SYiaiba5faeraYBoQCWdsBX4hSjFKiawzhIpnXjejDtjmiaFqMqhIlRBqR7IVdbKE51npeF6X1cXxtDQD2bzehgqMA/132', nickName: 'jay' }, lists: [ 'aslkdnoakjbsnfkajbfk', 'qwrwfhbfdvndgndghndeghsdfh', 'qweqwtefhfhgmjfgjdfghaefdhsdfgdfh', ], showSkeleton: true }, onLoad: function () { const that = this; setTimeout(() => { that.setData({ showSkeleton: false }) }, 3000) } }) //index.wxml <view class="container"> <view class="userinfo"> <block> <image class="userinfo-avatar skeleton-radius" src="{{userInfo.avatarUrl}}" mode="cover"></image> <text class="userinfo-nickname skeleton-rect">{{userInfo.nickName}}</text> </block> </view> <view style="margin: 20px 0"> <view wx:for="{{lists}}" class="lists"> <icon type="success" size="20" class="list skeleton-radius"/> <text class="skeleton-rect">{{item}}</text> </view> </view> <view class="usermotto"> <text class="user-motto skeleton-rect">{{motto}}</text> </view> <view style="margin-top: 200px;"> aaaaaaaaaaa </view> </view> [代码] 有了上面的 data + template 之后,就有了一个初始化的页面结构,接下来就需要拿到节点信息 节点 小程序基础库1.4.0之后小程序基础库提供了一组新的API,可用于获取节点信息,具体API戳这里。 跟H5方式一样,根据class或者id获取节点信息,不同的是只能获取到当前的节点信息,无法获取到其父或者子节点信息,所以只能手动给需要渲染骨架屏的节点添加相应的class或者id [代码]<view class="container"> <view class="userinfo"> <block> <image class="userinfo-avatar skeleton-radius" src="{{userInfo.avatarUrl}}" mode="cover"></image> <text class="userinfo-nickname skeleton-rect">{{userInfo.nickName}}</text> </block> </view> <view style="margin: 20px 0"> <view wx:for="{{lists}}" class="lists"> <icon type="success" size="20" class="list skeleton-radius"/> <text class="skeleton-rect">{{item}}</text> </view> </view> <view class="usermotto"> <text class="user-motto skeleton-rect">{{motto}}</text> </view> <view style="margin-top: 200px;"> aaaaaaaaaaa </view> </view> [代码] 约定2个特殊的class作为获取节点信息的标记[代码]skeleton-rect[代码]和[代码]skeleton-radius[代码],在页面中获取相应的[代码]top[代码]、[代码]left[代码]、[代码]width[代码]、[代码]height[代码]进行骨架屏的绘制 结果 [图片] 具体的调用方式和源码,请看 github ,最后求start 总结 上文有说到小程序也可以使用 page-skeleton-webpack-plugin 方式一样生成骨架屏,最重要的一点就是需要将小程序跑在chrome上面,后面的流程就一样了,至于怎么将小程序跑在chrome上面呢?可以利用 wept ,缺点就是目前作者已经停止维护这个工具了,不支持新版小程序的API。 说回来我这个生成骨架屏的方案,其实跟 page-skeleton-webpack-plugin 有点相似,不同的是,page-skeleton-webpack-plugin 采用离线渲染的方式生成静态骨架屏插入路由中,而我采用运行时先渲染页面默认结构,然后根据默认结构再绘制骨架屏。从性能角度出发确实不如 page-skeleton-webpack-plugin,但是也差不了多少了,主要还是小程序并没有提供类似服务端渲染的方案。目前从使用上来讲,还是有点小麻烦,需要默认数据撑开页面结构,需要给相应的节点添加class,后面有时间再研究下有没有更好的方案吧~~~
2019-02-20