- textarea 光标 阴影 ?
基础组件,真机上 页面创建 textarea 时候,会在最右边有个贯标一样的阴影,这个是啥
2021-02-24 - 如何在小程序通过<web-view>标签跳转到指定公众号文章中?
如何在小程序通过<web-view>标签跳转到指定公众号文章中?知道链接是 https://mp.weixin.qq.com/s?XXXXXXXXXXXXXXXXX,可以实现跳转,但是需要将https://mp.weixin.qq.com添加到小程序后台的业务域名中吗?
2023-08-01 - Android app可以跳转到公众号页面吗? 有没有对应的api?
Android app可以跳转到公众号页面吗? 有没有对应的api?
2023-07-26 - 小程序隐私保护指引设置的调试心得
微信官方于8月10日发布了《关于小程序隐私保护指引设置的公告》,但是就目前大家的开发、调试以及产品上的问题,并没有做出统一的答复,这里我开一个专门的文章,来记录接口调试过程中的问题,以及找一找大家的问题,尝试做一个整理。 开发历程 ——8月22日晚—— 官方更新了文档,目前已经可以正常开发调试了: 以下指南中涉及的 getPrivacySetting、onNeedPrivacyAuthorization、requirePrivacyAuthorize 等接口目前可以正常接入调试。调试说明: 在 2023年9月15号之前,在 app.json 中配置 __usePrivacyCheck__: true 后,会启用隐私相关功能,如果不配置或者配置为 false 则不会启用。 在 2023年9月15号之后,不论 app.json 中是否有配置 __usePrivacyCheck__,隐私相关功能都会启用。 ——8月16日中午—— 【BUG】微信回滚了代码,此时 wx.getPrivacySetting 接口获取到的 needAuthorization 始终为 false,估计是为了解决上午开发版、体验版小程序报错的问题。 ——8月16日上午—— 此时 wx.getPrivacySetting 接口获取到的 needAuthorization 为 true,但是所有开发版、体验版小程序若未完成隐私保护接入,都会报错:errMsg: "requirePrivacyAuthorize:fail privacy permission is not authorized" errno: 104 【BUG】在 wx.onNeedPrivacyAuthorization 回调后获取到了 resolve 对象,并在用户点击同意后进行了回调,但是发现当buttonId指定错的时候接口报错:errMsg: "requirePrivacyAuthorize:fail privacy permission is not authorized or buttonId is wrong" errno: 104 诡异的是就算报错了,调用隐私接口时也能够成功。 ——8月15日—— 开发过程中发现的问题: 【8月16日官方已解决】调用 wx.requirePrivacyAuthorize 后始终会进入到 success 回调,无法触发 wx.onNeedPrivacyAuthorization 回调,并且 wx.getPrivacySetting 接口获取到的 needAuthorization 始终为 false。 提问 【问】onNeedPrivacyAuthorization触发时机:开发者调用需要授权的方法有组件(camera等)和api(getLocation等)形式,是在组件初始化、API调用时触发?还是要开发者主动调用requirePrivacyAuthorize才会触发,未授权的时候组件、API都无法调用?(来自 @金瓜兜儿) 【官方答复】api是在api调用时触发事件,组件是在组件初始化时机会触发事件,以上是被动触发的方式; 如果要主动触发,用户可以主动调用requirePrivacyAuthorize触发事件,这是两种方式,根据这个原则由用户自行判断执行逻辑;未授权时组件api都无法调用,授权后才可调用 ———————————————— 【问】兼容问题:相关接口从基础库2.33.0 开始支持,如果用户基础库低于这个版本,相关的组件使用、api调用都会失败吗?(来自 @金瓜兜儿) 【官方答复】不会 【解析】目前基础库2.33.0以上的版本分布(https://developers.weixin.qq.com/miniprogram/dev/framework/client-lib/version.html) 占比为86.84%,基本涵盖了绝大部分用户。开发的时候,调用onNeedPrivacyAuthorization可以简单地通过: if (wx.onNeedPrivacyAuthorization) 来处理兼容性逻辑。 低于2.33.0以下的用户调用隐私接口、隐私组件不受影响。 ———————————————— 【问】onNeedPrivacyAuthorization在用户同意过后,如果小程序有新增需要用户授权的功能,更新了小程序用户隐私保护指引,是不是会再次触发需要用户再次同意?(来自 @金瓜兜儿) 【官方答复】更新了之后 只有新增的接口需要再次触发用户同意 ———————————————— 【问】如果用户同意了授权,再调用camera等组件、getLocation等API,自带的授权弹窗是否还会再次弹出?(来自 @金瓜兜儿) 【官方答复】会的 【解析】为了防止多个弹窗影响用户体验,建议在进入到有类似功能的页面前,主动调用wx.requirePrivacyAuthorize触发主动授权。 ———————————————— 【问】如果小程序功能是地图相关,进入小程序首页就需要用户同意,如果用户不同意就只能退出小程序、或者重复提示用户同意隐私声明,小程序审核时会不会因为强制用户授权而被审核人员驳回?(来自 @金瓜兜儿) 【官方答复】如为地图类小程序,确有定位展示内容等则可弹窗告知用户。但若用户不同意后,未涉及定位展示内容则需要让用户正常体验 ———————————————— 【问】api在调用时触发,回调是会进入fail还是一直等待开发者resolve后返回success?(来自 @金瓜兜儿) 【答】经过8月16日上午的测试,wx.requirePrivacyAuthorize调用后会一直等待开发者resolve({ event:'agree' })之后才会进入到success流程,如果resolve({ event:'disagree' })则进入到 fail 流程。 ———————————————— 【问】未授权用户同时调用10个不同的隐私接口,会触发多少次onNeedPrivacyAuthorization?(来自@georgejinme-) 【答】待验证。 ———————————————— 【问】组件在初始化时触发,触发之后组件是什么状态,需不需要开发者重新渲染?还是说resolve之后会自动渲染处理? (来自 @金瓜兜儿) 【答】待验证。 ———————————————— 【问】每个页面调用隐私api的地方都未知, 比如a页面我调用了3个api, 我是不是要在a页面准备一个隐私弹窗, 其他bcdef页面都要准备隐私弹窗组件?(来自 @axing) 【答】可以参考 @一笑皆春 写的《关于新版隐私协议接口wx.onNeedPrivacyAuthorization的适配解读以及实现代码》(https://developers.weixin.qq.com/community/develop/article/doc/000c0680fe02e02201308a4c961813),每个页面都准备一个统一的隐私弹窗组件,并且在 onShow 中注册 onNeedPrivacyAuthorization,这会覆盖监听。 我本人还有两个思路,第一种是在用户进入小程序的首页时,主动调用requirePrivacyAuthorize触发隐私授权,这样只需要在首页编写一个隐私弹窗组件,但缺点是若您的小程序有多个入口时,这个方法可能也会较为麻烦。此外,有wx.login这个接口的前车之鉴,用户一进入小程序就要求授权,很可能微信审核不予通过。 第二种是不使用弹窗,而是用一个单独的页面进行用户授权,这时在 app.js 中注册 wx.onNeedPrivacyAuthorization 即可,一旦触发就跳转至该页面。 ———————————————— 【问】请问,我在小程序后台隐私指引里列出了3个隐私接口,比如A B C 。现在用户在某页面触发了A接口,然后用户同意授权了。此时微信侧记录的用户授权了A接口还是A B C三个接口都授权了?(来自 @BOBO) 【答】经过8月16日上午的测试,无论有多少个隐私接口,只要用户授权过一次,后续的所有隐私接口都能授权。但是调用在隐私协议中未列出的隐私接口将直接失败,不会触发 onNeedPrivacyAuthorization。
2023-08-24 - 小程序web-view的H5页面使用localstorage的问题
web-view内部的H5页面,使用localstorage存储数据,部分安卓机型 偶现 此问题: 杀掉小程序的进程,H5页面的localstorage数据会全部丢失。(暂不清楚不杀掉进程,放后台是否也会丢失) 想咨询一下,web-view内部的H5页面使用localstorage,能否实现持久化存储,小程序保存web-view内部网页localstorage数据的时机是什么时候(因为同一机型有时丢失有时不丢失)
2019-03-05 - history模式,IOS弹框显示config:invalid signature,realAuthURL?
安卓直接拿windows.localtion.href 假如是 https://developers.weixin.qq.com/community/article/edit/000204985a07402dc83ef365a57013 那是没问题的。 但如果是苹果,会出现realAuthURL:" https://developers.weixin.qq.com"签名失败,只要将 https://developers.weixin.qq.com/community/article/edit/000204985a07402dc83ef365a57013 改成 https://developers.weixin.qq.com 去配置就行了
2022-07-15 - 小程序使用webview嵌套H5中使用iframe真机无法跳转 wx.miniProgram.getEnv等失效问题分享
小程序使用webview嵌套H5真机无法跳转 wx.miniProgram.getEnv、wx.miniProgram.navigateTo等失效无响应问题分享 原因分析:由于页面使用了iframe导致在子页面中真机无法准确获取页面运行环境(开发者工具中无影响); 解决方案:在调用方法前加一个 parent. 在父页面中调用方法即可正常运行; 过程:尝试过切换jweixin代码版本但是问题依旧; 分享:遇到同类问题用这个方法解决了的小伙伴欢迎评论区留言点赞👍! <script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script> <script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script> 核心代码: var ua = navigator.userAgent.toLowerCase(); if(ua.match(/MicroMessenger/i)=="micromessenger") { //由于页面是iframe 所以在调用wx.miniProgram.getEnv的时候直接调用会没反应,需要加一个parent父组件调用即可成功调起来。(开发者工具可以成功跳转但是真机没办法跳转1.3.2-1.6.0的js都试过问题依旧) parent.wx.miniProgram.getEnv((res)=>{ if (res.miniprogram) { // alert("在微信内,在小程序内") // console.log('在小程序内') // alert("在小程序内") parent.wx.miniProgram.navigateTo({ url: "/pages/minipay/minipay?outTradeNo="+outTradeNo+"&type=miniapp&code=" , //小程序的支付地址,queryParam是需要传递的商品id等数据 fail: function(err){ alert("跳转小程序失败!") }, }); return false; } else{ alert("在微信内,但是不在小程序内") console.log('在微信内,但是不在小程序内')//嵌入公众号 return false; } }) } else{ console.log('在微信外') if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) { console.log("移动") // 支付在同一页面打开 // return; } else { console.log("PC") // 支付在同一页面打开 // return; } return false; }
2020-12-21 - 小程序加入企业微信中 登录问题处理汇总
【企业微信】&【小程序】 [图片] [图片] 企业微信 直接关联的小程序是企业内部使用的,第三方应用关联的小程序可以上线给其他企业使用,调用wx.qy.login的话获取到的都是userid小程序的微信用户(openid)与企业微信用户(userid):用手机号关联,而且企业微信绑定不到微信开放平台https://work.weixin.qq.com/api/doc/90000/90136/92370 官方:小程序关联到企业网微信https://work.weixin.qq.com/api/doc/90000/90136/91505 官方:小程序在企业微信上的登录流程https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html【官方】小程序在微信中登录临时登录凭证 code 只能使用一次用户唯一标识 OpenID 和 会话密钥 session_keyhttps://developers.weixin.qq.com/miniprogram/dev/dev_wxwork/ 【官方】小程序与企业微信兼容可通过接口调用查看enviroment 便可知道小程序登录的是【微信】还是【企业微信】https://developers.weixin.qq.com/miniprogram/dev/dev_wxwork/dev-doc/qywx-api/foundation/wxgetsysteminfo.html通过接口 调用 企业微信中 企业成员手机号 https://developers.weixin.qq.com/miniprogram/dev/dev_wxwork/dev-doc/qywx-api/corpmemberinfo/wxqygetmobile.html
2020-05-19 - 产品原型设计实战
3.1学习对象+课程目的+推荐工具 [视频] 3.2用户体验地图及功能页面归纳 [视频] 3.3墨刀原型工具介绍(1) [视频] 3.3墨刀原型工具介绍(2) [视频] 3.3墨刀原型工具介绍(3) [视频] 3.4手把手1注册页(1) [视频] 3.4手把手1注册页(2) [视频] 3.5自主实操1登录页(1) [视频] 3.5自主实操1登录页(2) [视频] 3.6手把手2底部菜单栏(1) [视频] 3.6手把手2底部菜单栏(2) [视频] 3.6手把手2底部菜单栏(3) [视频] 3.7手把手3发布树洞(1) [视频] 3.7手把手3发布树洞(2) [视频] 3.8手把手4树洞广场、点赞(1) [视频] 3.8手把手4树洞广场、点赞(2) [视频] 3.9自主实操2我的树洞(1) [视频] 3.9自主实操2我的树洞(2) [视频] 3.10课后小练(1) [视频]
2021-09-15 - 小程序开发实战
高校大赛系列课程之“小程序开发实战”,是由清华大学和微信团队共制作的小程序学习教程。通过需求分析、原型设计、小程序前端实现、后台接口开发、小程序对接接口,逐步教大家如何“从无到有”完成小程序项目
2021-11-25 - 2019 微信公开课:九个案例讲透小程序留存
学会这 9 个案例,做好小程序留存。
2021-12-16 - 2021 微信公开课PRO
2021微信公开课的主题是“激发WeBuild”, 站在新十年的起点,微信希望通过小程序、视频号等产品,让每一种能力都拥有绽放的舞台,人人可以经营,人人可以创作,新的创造和新的想象力将被无限激发。
2022-06-27 - web性能优化之渲染性能优化
引子: 笔者在业务开发过程中,需要一个vue版的无限滚动组件,从github上找了一些组件后发现效果都不太好(主要是卡顿),最后自己查阅一些渲染性能优化的文章后,基于iScroll二次开发了一个组件,自己觉得效果还不错,主要是利用了硬件渲染加速和dom元素的复用,有同样需求的朋友可以试一下。(https://github.com/zuolei828/vue-virtual-infinite-scroll) 针对这次组件的优化,记录一下渲染性能优化的比较系统的知识,个人能力所限,很多方面理解的可能不对,欢迎大家指正! 一个web页面的性能优化,包括加载(loading)性能优化以及渲染(rendering)性能优化,关于加载性能的优化在另一篇文章中讨论(加载优化),这里来整理一下渲染性能优化的相关知识。 浏览器多进程模型 为了方便后面优化知识的阐述,这里先简单介绍下浏览器的多进程模型(以chrome为例)。 [图片] 主要进程如图所示: Browser进程:浏览器的主进程,负责浏览器界面的显示,各个页面的管理,其他各种进程的管理; Renderer进程:页面的渲染进程,负责页面的渲染工作,Blink的工作主要在这个进程中完成(主要分成render主线程和合成器线程); NPAPI插件进程:每种类型的插件只会有一个进程,每个插件进程可以被多个Render进程共享; GPU进程:最多只有一个,当且仅当GPU硬件加速打开的时候才会被创建,主要用于对3D加速调用的实现; Pepper插件进程:同NPAPI插件进程,不同的是为Pepper插件而创建的进程 页面渲染过程 页面渲染中每一帧的渲染最多进行了如下五个步骤。 [图片] JavaScript:通常我们会使用 JavaScript 来实现页面视觉变化的效果。比如做一个动画或者往页面里添加一些 DOM 元素等。 Style:计算样式,这个过程是根据 CSS 选择器,对每个 DOM 元素匹配对应的 CSS 样式。 Layout:在知道对一个元素应用哪些样式之后,浏览器即可开始计算它要占据的空间大小及其在屏幕的位置。网页的布局模式意味着一个元素可能影响其他元素,例如 body 元素的宽度一般会影响其子元素的宽度以及树中各处的节点,因此对于浏览器来说,布局过程是经常发生的。 Paint:绘制是填充像素的过程。它涉及绘出文本、颜色、图像、边框和阴影,基本上包括元素的每个可视部分。绘制一般是在多个层(Layer)上完成的。 Composite:由于页面的各部分可能被绘制到多层,由此它们需要按正确顺序绘制到屏幕上,以便正确渲染页面。对于与另一元素重叠的元素来说,这点特别重要,因为一个错误可能使一个元素错误地出现在另一个元素的上层。 换成这个图来看渲染引擎的处理流程 [图片] 这个过程比较复杂,详细的留在后面介绍Composite优化的时候再阐述。先简单说一下中间步骤,DOM树构建完成后,等待JS和CSS一起合成了Render树,每一个DOM节点对应一个Render Object,根据RenderObject的样式属性,可能将多个或者单个的object转换成RenderLayer,通常,渲染引擎的软件渲染到这就结束了,在开启硬件加速后,某些RenderLayer才会被转换成GraphicsLayer,最后利用GPU来进行合成和最终呈现。 如何检测render性能 上面说的渲染的五个步骤中的每一个都有可能造成卡顿,当然根据css属性的不同,可能会跳过layout或者paint阶段(具体每个css属性影响哪些阶段,请查看css触发器,注意chrome现在用的是blink内核),那么如何知道页面runtime中触发了哪些步骤以及各自性能了,最好的方法就是使用chrome devtool中的performance来记录分析。 打开chrome开发者工具,切换到performance tab,点击record按钮,这时你对页面的操作就会被记录下来,点击stop后就能看到性能火焰图等信息了,点击Frames中的一帧,下方的Main区域就会集中到这一帧的运行过程,如下图所示。(红圈区域即为选中一帧) [图片] 黄色为JS,紫色为Style和Layout,绿色为Paint和Composite部分,选中每个部分会显示各自的花费时间等信息,可以看出这个图片中JS运行的时间太长。目前的显示设备一般刷新率是60FPS,所以理想中每帧的时间最好为16毫秒,利用performance就能很直观的看出渲染中哪一步骤出现问题,下面介绍如何对每个步骤进行优化。 优化JS执行 JS 经常会触发视觉变化。有时是直接通过样式操作,有时是会产生视觉变化的计算,例如搜索数据或将其排序。时机不当或长时间运行的 JS 可能是导致性能问题的常见原因。通常可以通过以下几个方法来优化JS的执行。 对于动画效果的实现,避免使用 setTimeout 或 setInterval,请使用 requestAnimationFrame。 将长时间运行的 JavaScript 从主线程移到 Web Worker。 使用微任务来执行对多个帧的 DOM 更改。 使用requestAnimationFrame来执行视觉变化 先看一张图 [图片] 为了避免显示撕裂,开启垂直同步后,显示器每16ms(假设为60HZ)会发出一个VSync信号,浏览器收到信号后开启一帧的渲染,中间过程可能只用CPU完成软件渲染,也可能利用GPU硬件渲染,最终将渲染结果绘制到帧缓冲区,在下一个VSync信号到来时,显示器显示最新的渲染结果,并通知开启下一帧渲染。 在16ms的间隔中,如果一帧没有渲染完,那么这一帧就会被丢弃,显示器还是显示之前的画面,就会造成掉帧;同时如果16ms内如果完成多次渲染,显示器也只会更新一次画面,多次的渲染就会造成CPU和GPU的资源浪费。所以最理想的情况就是每16ms只渲染一次,一些老的框架会使用setTimeout来实现出这个间隔,但是会出现下图的问题。 [图片] 由于不能保证renderer主线程的运行时间,有可能setTimeout的回调会正好在间隔的中间被执行,如果渲染不能在下次间隔前完成,还是会造成卡帧。为了保证每次渲染都在一帧的开始来执行,requestAnimationFrame是唯一正确的方法,但是在使用时候也要注意一点,在requestAnimationFrame的回调执行之前,如果多次调用requestAnimationFrame,也会导致下一帧开始时多次执行这个回调,造成结果的不正确,所以需要加一下类似下面代码的控制。 [代码]function onScroll (evt) { // Store the scroll value for laterz. lastScrollY = window.scrollY; // Prevent multiple rAF callbacks. if (scheduledAnimationFrame) return; scheduledAnimationFrame = true; requestAnimationFrame(readAndUpdatePage); } window.addEventListener('scroll', onScroll); [代码] 分割长时间的JS的执行 由于长时间的JS执行会阻塞渲染,要尽量缩减一帧中JS的执行时间,不需要DOM权限的操作可以移到web worker中,但是通常我们的JS代码都会造成视觉变化,所以可以将一个耗时任务拆分成若干微任务,并利用requestAnimationFrame来执行,如下代码所示。 [代码]var taskList = breakBigTaskIntoMicroTasks(monsterTaskList); requestAnimationFrame(processTaskList); function processTaskList(taskStartTime) { var taskFinishTime; do { // Assume the next task is pushed onto a stack. var nextTask = taskList.pop(); // Process nextTask. processTask(nextTask); // Go again if there’s enough time to do the next task. taskFinishTime = window.performance.now(); } while (taskFinishTime - taskStartTime < 3 && taskList.length > 0); if (taskList.length > 0) requestAnimationFrame(processTaskList); } [代码] 优化样式的计算过程 通过添加和删除元素,更改属性、类或通过动画来更改 DOM,全都会导致浏览器重新计算元素样式。计算样式通过两个阶段来完成,首先浏览器计算出给指定元素应用哪些类、伪选择器和 ID,然后从匹配选择器中获取所有样式规则,并计算出此元素的最终样式。在Chrome的Performance记录区域,可以看到每一帧的渲染中,都有一个recalculate style的紫色矩形,记录的就是此次重新计算的耗时及影响到的元素数量等信息。通常采用下述两个方法来优化计算过程: 降低选择器的复杂性 减少必须计算其样式的元素数量 有时候我们喜欢用p:nth-of-type(2),:nth-child(n)等选择器来书写css内容,因为这样方便我们在一个父元素的所有子元素中找出一个特例来修改样式,但是这样会增加计算的复杂度,浏览器要知道其它所有子元素的情形,通常还是建议给元素一个明确的类选择器,例如BEM。 优化布局 布局是浏览器计算各元素几何信息的过程:元素的大小以及在页面中的位置。如何优化需要做到以下几点。 尽可能避免触发布局 因为布局几乎总是作用到整个文档。 如果有大量元素,将需要很长时间来算出所有元素的位置和尺寸。修改元素的几何属性(大小,位置等)都会导致整个文档重新布局,这个时候可以利用tranform的位移,放大缩小等操作来避免重新布局(前提是开启了硬件加速),这部分会在后面的composite优化部分详细描述,下面看两个demo demo1(更改top属性导致重新布局) demo2(利用translate不会导致重新布局) [图片] [图片] 利用performance分析能看出demo2没有触发layout 使用flex布局而不是浮动 早些年因为兼容性的问题,喜欢用float来实现布局,现在请使用flexbox,布局的性能会得到显著提升,看一下两个demo demo1(使用float布局) demo2(使用flex布局) 利用performance来分析,为了模拟手机上的效果,请将cpu 4x down降速 [图片] float是26.77ms [图片] flex是13.43ms 提升了一倍,看下flexbox目前的兼容性 [图片] 非IE的情况下,大家请安心使用吧(吐槽下,为啥还有人用IE),再贴一张最近一年桌面浏览器占有率 [图片] 避免强制同步布局 回忆下帧的渲染步骤,JS先运行,然后计算样式,再来布局,然而,JS可以强制布局提前,这被称为强制同步布局,看下代码。 [代码]// Schedule our function to run at the start of the frame. requestAnimationFrame(logBoxHeight); function logBoxHeight() { box.classList.add('super-big'); // Gets the height of the box in pixels and logs it out. console.log(box.offsetHeight); } [代码] JS运行时,来自上一帧的浏览器的布局信息是已知的,但是例子中的回调方法先增加了一个类,这个时候浏览器必须先应用样式修改,再重新布局,然后才能输出高度信息。通常上一帧的布局信息已经够用,这种强制同步布局会造成性能浪费。 4. 避免布局抖动 有一种情况会频繁的强制同步布局,看一下代码。 [代码] function resizeAllParagraphsToMatchBlockWidth() { // Puts the browser into a read-write-read-write cycle. for (var i = 0; i < paragraphs.length; i++) { paragraphs[i].style.width = box.offsetWidth + 'px'; } } [代码] 此代码循环处理一组段落,并设置每个段落的宽度以匹配一个称为“box”的元素的宽度。这看起来没有害处,但问题是循环的每次迭代读取一个样式值 (box.offsetWidth),然后立即使用此值来更新段落的宽度 (paragraphs[i].style.width)。在循环的下次迭代时,浏览器必须考虑样式已更改这一事实,因为 offsetWidth 是上次请求的(在上一次迭代中),因此它必须应用样式更改,然后运行布局。每次迭代都将出现此问题! [代码]此示例的修正方法还是先读取值,然后写入值: [代码] [代码]// Read. var width = box.offsetWidth; function resizeAllParagraphsToMatchBlockWidth() { for (var i = 0; i < paragraphs.length; i++) { // Now write. paragraphs[i].style.width = width + 'px'; } } [代码] 优化绘制与合成 绘制是填充像素的过程,像素最终合成到用户的屏幕上。 它往往是渲染过程中运行时间最长的任务,应尽可能避免此任务。合成是将页面的已绘制部分放在一起以在屏幕上显示的过程。这两个过程通常需要放在一起优化,而且是渲染过程中最需要关注的优化点,所以一起来详细阐述下。在介绍优化之前,我们要了解一下Blink的渲染基础知识,再来回顾一下之前放的一张图。 [图片] 这张图展示了Blink从最初的DOM树如何转换到最终的用于合成的Graphics Layer树,具体是如下步骤: Nodes 和 DOM树 网页内容在Blink内部以Node为节点的树形结构存储,称为DOM树。网页中的每一个HTML 元素,包括元素之间的text都和一个Node相关联。DOM tree的最顶层Node 永远是Document Node. From Nodes to RenderObjects DOM树中每一个可视化的Node 节点都对应着一个RenderObject。RenderObject 也存储在一棵对应的树结构中,称为Render树。 RenderObject 知道如何在一个显示设备上绘制(paint) Node 节点的内容。它通过调用GraphicsContext提供的绘制接口来完成绘制过程。GraphicsContext最终负责将像素写入一块bitmap,这块bitmap会被显示在屏幕上。在Chrome中,GraphicsContext 封装了Skia( 2D图形库)。 之前对GraphicsContext的大多数调用都转变成对SkCanvas或SkPlatformCanvas的接口调用。不过为了把绘制的实际过程移出主线程(后面会详细讲),现在这些调用命令被替换成记录到SkPicture。SkPicture是一个能够记录command,最后可以replay这些command的有序数据结构,类似于display list。 From RenderObjects to RenderLayers 每一个RenderObject 都关联着RenderLayer。这种关联是通过祖先RenderObject 节点直接或间接地建立的。分享同一坐标系的RenderObject(比如被同一CSS transform属性影响的元素)必然位于同一RenderLayer。 正是由于RenderLayer的存在,网页上的元素才可以按照正确的顺序合成,从而恰当的显示有交叠的内容,和半透明元素等效果。通常来讲,满足下列条件之一时,RenderObject就会创建RenderLayer: 根节点 有明确的CSS定位属性(relative, absolute) 透明的(opacity 小于 1) 有overflow, an alpha mask or reflection 有CSS filter 有2D加速Context或者3D(webGL)context的 canvas 元素对应的 有video元素的 需要注意的是RenderObject和RenderLayer之间并不是一一对应的。 RenderObject 或者与它所创建的RenderLayer相关联(如果它创建了的话),或者与它的第一个拥有RenderLayer的祖先RenderObject创建的RenderLayer相关联。 RenderLayer 也会形成一个树型层次结构。这个树结构的根节点是与网页的根元素相对应的RenderLayer。每一个RenderLayer 节点的后代都是包含在父亲RenderLayer内的可视化的RenderLayer. 每一个RenderLayer的子节点都被存储在两个按升序排列的有序表中。negZOrderList 有序表中存储的子节点是z-index值为负的子RenderLayer,所以这些RenderLayer在当前RenderLayer的下面;posZOrderList有序表中存储的子节点是z-index值为正的RenderLayer,所以这些RenderLayer在当前RenderLayer的上面。 事实上,在老版本的chrome里(15年之前),有一个软件渲染路径的概念,就是不需要硬件加速的情况下,渲染到这里结束了,放一张图来简单了解一下。 [图片] 所有的RenderLayer构建完成后,浏览器渲染进程调用Skia递归的将layer树绘制到共享内存中的单个位图,然后通过IPC传递到Browser Process,最终由Browser Process负责将位图drawing到屏幕。 4. From RenderLayers to GraphicsLayers 为了有效利用GPU硬件加速渲染,Blink又引入了一个新的GraphicsLayer,并且专门独立了一个专门的Compositor(合成器) Thread来管理GraphicsLayer以及协调帧的生命周期(后面会专门介绍这个合成器)。作为一个前端开发,你会经常听到用transform: translateZ(0)来开启所谓的硬件加速,实质上就是提升成了GraphicsLayer。 每一个RenderLayer或者拥有自己的GraphicsLayer(如果这个RenderLayer是compositing Layer的话),或者是使用它的第一个拥有GraphicsLayer的祖先节点的GraphicsLayer. RenderLayer与GraphicsLayer的关系类似于RenderObject与RenderLayer之间的关系。每个GraphicsLayer都拥有一个GraphicsContext,与这个GraphicsLayer相对应的每个RenderLayer都绘制到这个GraphicsContext上。合成器会负责将多个的GraphicsContext输出的位图最终合成一个最终的image。 理论上讲,每一个RenderLayer都可以将自己绘制到一个单独的backing surface上以避免不必要的重绘。但是在实际中,这种做法会导致内存的大量浪费(尤其是VRAM)。在当前的Blink实现中,只有满足以下条件之一,RenderLayer才会拥有它自己的compositing layer。 layer 有3D或者perspective transform 属性值 layer是硬解码的video 元素使用的 layer是拥有3D context或2D加速context的Canvas标签使用的 layer是一个合成的插件使用的 layer使用了动画表示它的透明度,或者使用了动画形式的webkit 变换 layer 使用了加速的CSS 滤镜 拥有compositing layer后代的layer 渲染在compositing layer之上的layer(overlap) 最后一个overlap为啥会产生合成层了?看一个例子。 [图片] 图中蓝色矩形覆盖在绿色矩形之上,同时它们的父元素是一个GraphicsLayer,假设绿色矩形也是一个GraphicsLayer,如果蓝色不是,那么它将和父元素公用一个合成层,既变成如下图情形。 [图片] 绿色矩形覆盖了蓝色矩形,渲染的顺序就发生了错误,所以为了保证正确,overlap也必须提升为合成层。 5. Layer Squashing overlap引起的合成层提升经常出现,就会导致有很多的合成层,岂不是会造成内存大量浪费,所以Blink专门有Layer Squashing(层压缩)的处理。看一下demo(层压缩)。 打开chrome的Performance工具来分析,选中一帧后,会看到下方工具栏出现一个layer tab,选中这个tab就能看到页面对应的合成层信息。 [图片] 红色圈中部分是显示有几个合成层,右侧绿色圈中部分显示这个合成层形成的原因和大小等信息。很明显,中间可视区域的深蓝色的矩形因为开启3D加速的原因被提升为合成层,绿色,红色,浅蓝三个矩形因为overlap的原因被提升成了合成层。 当我们把鼠标移到绿色矩形上,对应的CSS属性也修改成3Dtransform,所以绿色矩形也被提升为合成层,剩下的红色和浅蓝还是因为overlap被提升为另一个合成层,如下图所示。 [图片] 每一个GraphicsLayer都有对应的Composite Layer,这样Chrome的合成器才知道如何对这个GraphicsLayer进行处理,下面我们就来阐述下什么是合成器。 合成器(Compositor) Chrome的合成器是一个用来管理GraphicsLayer树和协调帧的生命周期的软件库。最初合成器也是被设计在渲染进程的主线程中的,现在合成器被拆成了两部分,一半在主线程里面,负责绘制(painting),主要工作就是把layer树的信息记录到SkPicture中,并没有实际上产生像素;另一半变成了单独的Compositor Thread(简称为cc),也被称为impl thread,这部分是真正的drawing,负责将painting中记录的layer信息经过光栅,合成等操作,最终显示到屏幕。下面分步骤来详细阐述合成器的工作。 Recording: Painting from Blink’s Perspective 兴趣区域(interest area)是要被记录到SkPicture中的viewport附近的区域。每当DOM元素改变,Blink会把兴趣区域中失效的部分layer树信息记录到 SkPicture-backed GraphicsContext。记住,这一步并没有真正的绘制像素,只是记录了可以replay出像素的命令的一个display list。 The Commit: Handoff to the Compositor Thread 合成器线程的一个关键特性就是它维护了主线程状态的一个复制,因此可以根据这个复制来生成帧而不用去询问主线程。主线程的状态信息就是一个LayerChromiumtree,对应的合成器线程复制的是CCLayerImpltree,这两棵树理论上是彼此独立的,这就意味着合成器线程可以在主线程阻塞的情况下使用当前的复制信息执行drawing内容到屏幕。 而当主线程产生了新的兴趣区域,合成器线程如何知道去修改它所维持的树的状态了?合成器线程有一个专门的调度器,使用commit来定期同步两棵树的状态。commit会将主线程更新过的LayerChromiumtree的状态以及新的SkPicture命令传给合成器线程,并同时block主线程来达成同步。这也是主线程在一个帧的生成过程中的最后一步。由于合成器线程独立于主线程,而且专门负责实际的drawing,所以浏览器传来的用户输入都是直接传到合成器线程的,一些不需要主线程参与的交互,例如用户键盘输入等,合成器线程可以直接处理完成页面的更新,但是如果主线程注册了事件的回调,这时候合成器线程就必须将更新的CCLayerImpltree状态以及一些额外任务反向commit给主线程。 Tree Activation 当合成器线程通过主线程的commit同步到更新后的layer tree信息后,会检查哪些layer是失效的并且重新光栅化这些layer。这时active tree是合成器线程保留的上一帧的layer tree信息,而新光栅化的layer tree信息被称为pending tree。为了保持展示内容的一致性,只有当pending tree已经完全光栅化后才会转换成新的active tree,从pending到active的过程被称为tree activation。 需要注意的非常重要的一点是有可能屏幕会滚动到当前的active tree之外,因为主线程只记录viewport周围的兴趣区域。这个时候合成器线程就会询问主线程去记录和commit新区域的信息,但是如果新的pending tree没能及时激活,用户就会滚动到一个所谓的 checkerboard zone。 为了减轻checkerboard zone,chrome将pending tree的光栅化分成低分辨率的部分和高分辨率的部分,当要出现checkerboard zone的时候优先光栅化低分辨率的部分并激活用来展现,这也就是为什么有时候有些页面在快速滚动时候会变模糊(例如google地图)。这部分工作是一个专门的tile manager来管理的(下一节的内容)。 Tiling 光栅化整个页面的layer tree是非常浪费CPU和内存的,所以合成器线程将layer tree分割成多个小的tile,设定好各个tile的优先级(根据离viewport的远近等因素来设置),并且专门创建了tile worker线程(一个或者多个)来执行这些tile的光栅化。在chrome的performance分析中能看到页面的tile,如图所示,勾选rending选项中的红色区域,就能看到页面中绿色border的tile。 [图片] Rasterization: Painting from cc/Skia’s perspective 主线程记录的SkPicture的display list,合成器线程通过两种方式来转变成最终上传到GPU的纹理(texture)。一种是基于CPU、使用Skia库的Software Rasterization,首先绘制进位图里,然后再作为纹理上传至GPU。这一方式中,Compositor Thread会创建出一个或多个Compositor Tile Worker Thread,然后多线程并行执行SkPicture records中的绘画操作,以之前介绍的Graphics Layer为单位,绘制Graphics Layer里的Render Object。同时这一过程是将Layer拆分为多个小tile进行光栅化后写入进tile对应的位图中的。另一种则是基于GPU的Hardware Rasterization,也是基于tile worker线程,也是分tile进行,但是这个过程不是像Software Rasterization那样在CPU里绘制到位图里,然后再上传到GPU中作为纹理。而是借助Skia’s OpenGL backend (Ganesh) 直接在GPU中的纹理中进行绘画和光栅化,填充像素。 Drawing on the GPU 一旦所有的纹理已经被填充,GPU进程就能使用深度优先遍历来遍历layer树的信息,然后调用GL/D3D命令来draw每个layer到帧的缓冲池,当然实际上每个layer的drawing还是分成tiles来进行的。下面这张图展示了GPU进程如何进行drawing。 [图片] 好了,到这里整个Compositor的部分阐述完了,我们也就知道了如何对帧渲染步骤中的绘制和合成来进行优化了–将页面频繁变化的部分提升到合成层,通常使用transform: translateZ(0),利用GPU渲染加速来进行合成。总结下,主要有以下几个优点。 合成层的位图,会交由 GPU 合成,比 CPU 处理要快 当需要 repaint 时,只需要 repaint 本身,不会影响到其他的层 对于 transform 和 opacity 效果,不会触发 layout 和 paint 当然,不能盲目的增加合成层数量,因为增加一个合成层就意味着更多的内存分配(特别是GPU内存)和更复杂的合成管理。我们应该专注于那些频繁变化的区域来进行优化。 帧的整个渲染步骤的优化都阐述完了,下面贴一张完整的流程图来总结一下。 [图片] 注意并不是每一帧中这些步骤都会发生,最多的步骤如下: Frame Start. 合成器线程收到来自浏览器的Vsync信号和Input data,一帧开始。 Input event handlers. Input data被合成器线程传给了主线程,注册的事件回调被执行,注意这里合成器线程做了优化,保证一帧中最多只会触发一次event handler,所以自带了requestAnimationFrame的节流效果。 requestAnimationFrame. 如果之前注册了raf回调,会在这里执行,这是最完美的执行更新视觉的地方。唯一要注意的就是避免发生强制布局,即导致样式计算和布局提前(红线所示)。 Parse HTML. 新增的html会在这里被解析,生成对应DOM元素。大部分你会在page load和appendChild之类操作后见到它。 Recalc Styles. 如果你在JS执行过程中修改了样式或者改动了DOM,那么便会执行这一步,重新计算指定元素及其子元素的样式。 Layout. 如果有涉及元素位置信息的DOM改动或者样式改动,那么浏览器会重新计算所有元素的位置、尺寸信息。 Update Layer Tree. 这一步实际上是更新Render Layer的层叠顺序关系,保证层叠的正确。 Paint. paint操作实际上有两步,第一步是主进程将layer tree的相关信息记录到SkPicture中,类似一个display list;第二部是合成器线程replay这个记录list来光栅化和填充上传纹理。主线程的paint只是第一步。 Composite. 这里其实也分两步,主线程这里计算出每个Graphics Layers的合成时所需要的data,包括位移(Translation)、缩放(Scale)、旋转(Rotation)、Alpha 混合等操作的参数,然后就是图中我们看到的第一个commit,主线程通知合成器线程去同步layer tree的信息。然后主线程此时会去执行requestIdleCallback。这一步并没有真正对Graphics Layers完成位图的composite。 Raster Scheduled and Rasterize。 第8步生成的SkPicture records在这个阶段被执行。合成器线程创建出若干个Compositor Tile Worker Thread,利用CPU软件光栅化或者GPU的硬件光栅化,最终将纹理写入了GPU内存中。 Frame End. 合成器线程已经完成paint和composite的工作,这时会发送一个commit给GPU进程,告诉他可以进行draw了,同时会传达主线程一个commit done,如果一个帧中视觉的变化没有主线程参与,这里合成器线程也会同步更新后的合成器layer tree信息给主线程。 draw. GPU进程按照深度优先遍历将最后的纹理draw到帧缓冲区,等待显示器的下一个Vsync到来时去显示。 结语 整个浏览器页面渲染的过程以及优化都阐述完了,性能优化是一门艺术,本文也只是很浅显的探讨了其中的一些基本概念和设计思想,如果想深入理解具体的架构和实现过程,还是要去阅读一下chrome的内核源码。对于我们前端开发来说,切忌的是为了优化而优化,实际开发过程中碰到了页面卡顿的情况,利用performance来分析找出卡顿的原因,针对卡顿的步骤不断进行改进测试,才是正确的优化方法。 参考引用 GPU Accelerated Compositing in Chrome compositor-thread-architecture rendering-performance the-anatomy-of-a-frame 无线性能优化:Composite
2019-03-15 - 复制任意微信小程序页面路径
以下以微信小程序“虎牙直播”为例,演示如何复制微信小程序页面的路径。 1.进入小程序的“关于虎牙直播”页面 [图片] 2.点击右上角的“…”进入“更多资料”页面 [图片] [图片] [图片] 3.复制AppID:wx74767bf0b684f7d3 4.进入小程序后台输入appid并搜索,然后点下一步 [图片] 5.鼠标移动到“获取更多页面路径”,在弹出窗口输入当前登陆的小程序的任意开发者微信号,然后点击开启,出现顶部的“开启入口成功”就可以使用手机访问“虎牙直播”任意页面进行复制了 [图片] 6.某个直播间的页面路径:pages/main/liveRoom/index.html?anchorUid=1678113423&source=search[图片] PS:复制出来的页面路径在小程序里使用的时候记得删除 .html 才能正常访问。
2020-01-16 - 直播间直播数据分享后台 互动数据 分享次数 不增加?
直播间分享多次,在后台显示分享数据不增加?这个分享次数是以什么来进行计算的?
2020-09-14 - 这里有一份最全的小程序直播插件开播实操指南
文章较长,图文视频并茂,先放个大纲。 (由于每篇文章最多只能放三个视频, 所以准备工作的视频不放了。) [图片] 01准备工作 首先在我们正式开始创建直播之前,我们需要提前做一些准备: 1.我们要准备好本次直播要推的商品,准备好它们的名称和图片。可以事先把商品图片都存到一个文件夹里,因为后续咱们还要对这些图片做进一步的处理。 2.我们要事先把这些商品通过我们的手机端或者电脑端,上传到我们的小程序商城的后台。 3.我们需要准备好到时候直播间的分享封面和直播间封面。可能第三点大家第一次听不知道这两个封面是什么以及怎么准备,没关系,在后续的创建直播的过程中会给大家讲解。 02 上架商品到商品库 [图片] 视频版 [图片] [图片] (因为这篇文章是我写在我的公众号的,视频直接传到公众号后台了,想看的直接扫码看吧) [图片] 图文版 [图片] 正式开始的第一步呢,我们需要登录到我们小程序的微信官方后台,然后点击功能里面的【直播】按钮,然后点击商品库,先将我们需要播的商品上传到商品库,注意,这一步必须操作,上直播间的商品必须要从商品库通过微信的审核。 [图片] 现在我们来上直播商品,在未入库这里点击【添加商品】,然后这里我们就看到了需要上传商品图片,填写商品名称,设置商品价格,还需要填写商品链接。 [图片] 我们一个个来填写 首先商品图片这里,注意,建议尺寸200* 200,大小不得超过50k,这个时候我们一般传上一张图片都会是不合格的,因为不在200*200的尺寸下的话,一般图片大小都超过50k了。那怎么办呢? [图片] 这个时候我们就得借用一个小程序来处理下图片了。 [图片] 这个小程序叫播播助手,微信直接搜索就可以搜到,我们用手机微信搜到后,然后把它发送给文件传输助手,然后用电脑微信打开这个小程序,方便我们在电脑上处理图片。 打开后我们来选择商品图片上传,将我们准备好的商品图片都上传上去,然后点击一键处理,然后再一一点击下载,下载到我们的桌面上。 [图片] 下载好后,我们就可以回到商品库这边上传商品了。首先将我们处理好的图片上传,然后依次填写商品名称,价格,到最后有一个商品链接获取。 [图片] 链接获取方法一 这种方法是最通用的,适用于自己开发的小程序或者所有模板小程序。 点击获取更多页面路径按钮,输入自己的微信号,然后开启入口,开启入口后,手机操作自己的商城小程序,找到自己现在要上架的这个商品,然后点击小程序右上角的三个点,然后再弹出来的按钮中选择复制页面链接,复制后发送到电脑,再到添加商品处的商品链接那里填写。 这里需要注意的是:指定的开启入口的微信用户必须是该小程序的项目成员,如果不是不可以开启入口,项目成员在后台成员管理处设置。 [图片] 链接获取方法二 (此方法适用于实体赋能小程序商城开通的小程序) 点击实体赋能商城后台的【商品管理】-【商品列表】,首先看下我们直播商品的商品ID都是多少,然后都先记下来。 [图片] 接下来点击【店铺管理】-【页面管理】里面的【小程序页面】的【商品详情】那里,然后填上商品库那边要添加的那个商品的ID,然后复制生成的路径。 [图片] 将复制的路径填到商品库添加商品那里,填上去的时候记得把路径最前面的斜杠去掉,填写上之后,这里会显示出来这个商品的二维码,此时我们扫一下,看下是不是相对应的商品,是的话直接保存并提审就可以了。 [图片] 其他需要入商品库的商品也按照上面的步骤进行操作一一添加保存提审就可以了。 03 创建直播间 [图片] 视频版 [图片] [图片] (因为这篇文章是我写在我的公众号的,视频直接传到公众号后台了,想看的直接扫码看吧) [图片] 图文版 [图片] 接下来我们就要创建我们的直播间了,还是在微信官方后台这里,然后点击【直播间管理】,点击【创建直播间】,此时会打开一个新的页面。 [图片] 在这里我们输上我们本次直播的标题,然后开播时间选择好,然后输上主播的昵称,再填写上主播的个人微信号,这个微信号一定要真实且是到时候直播的主播的微信号,否则会造成无法直播。 都填写上后,然后根据我们需要选择是否允许评论,默认的是是,然后下面就需要我们上传两张图片。 一张是分享卡片封面,这个图示一个接近于长方形的图,用于我们转发直播间到微信好友或群的时候小程序卡片的展示样式,直播间封面则是我们的用户进来观看我们直播的时候,在加载过程中展示的背景图片。 我们开播前准备的时候已经让大家准备了,准备的就是在这里用的,这时候我们来上传一下,如果可以成功上传的话那没问题,如果不行,还是再到播播助手里面处理下图片,然后再上传。 [图片] 全部填写完成后,我们的直播间就创建成功了,这个时候微信会提示,分享此直播间,去添加运营资源,查看推流小程序码等。 [图片] 我们先点分享此直播间,然后会得到一个直播间小程序码,我们可以把这个小程序码保存起来,发给我们的顾客或发到朋友圈,让他们扫码订阅直播,也可以用这个码自己去做一个海报,做的更炫酷一点。 [图片] 分享码如果之后还想下载,可以在直播间的操作的更多那里点击分享去下载。 分享码下载后,我们来点击直播间的运营,来添加我们本场直播的商品和抽奖活动。 [图片] 打开运营资源后,我们会看到两个栏目,一个是商品管理,一个是抽奖池,我们先来设置商品,点击从商品库中导入商品,就可以看到我们已经通过审核入库的商品,我们勾选上添加就可以了。 [图片] [图片] 商品添加完成后,我们切换到抽奖池,然后添加抽奖活动 抽奖活动目前有两种形式,一种是点赞抽奖,一种是评论抽奖。每场直播可以最多添加30个抽奖活动,我们来点击创建新抽奖来创建一个抽奖活动。 [图片] 可以选择抽奖形式,然后抽奖名称填写上,抽奖名称这里建议写【(活动形式)抽X人送XXX】,比如点赞抽5个人送花茶,我们就写【点赞抽5人送花茶】,这样观众也明白抽奖形式和奖品及数量。 活动时长自己填写,活动时长指的就是从主播发起抽奖到开奖所需的时间,这里建议弄个8分钟,不长不短,也能充分让观众多停留一会。 时长设置完毕后,选择用户兑奖形式,如果是到店兑奖的,可以只选择兑奖码,到时候凭兑奖码来兑奖即可,如果是邮寄的奖品,就选兑奖码+主动提交邮寄地址。 备注可以不填写,这里用于开播的时候自己来分辨活动或者特殊备注。 [图片] 全部填写完成后,我们就可以选择完成添加,为这场直播添加一个抽奖活动了。 如果打算直播过程中有多场活动,那就还是按照刚才的步骤多添加几个活动就可以了。 当抽奖和商品我们都添加好后,我们就完成了开播前的所有准备工作。 04开播! [图片] 视频版 [图片] [图片] (因为这篇文章是我写在我的公众号的,视频直接传到公众号后台了,想看的直接扫码看吧) [图片] 图文版 [图片] 准备工作都做完后,到了我们最后的开播啦。 开播的时候建议有一个人在后台跟主播协作完成直播,为什么这么说呢,下面你就明白了。 开播前10分钟在直播间那里点击【开播码】获取主播开播的推流码,注意,太早获取的直播码可能会失效。 [图片] 主播这边拿到开播码后,就可以拿创建直播时填写的微信号扫描开播码,然后进入开播页面开播,如果这个主播是首次开播,那还需要完成人脸识别实名认证环节,主播这边正常开播就可以了,更多的工作其实是在直播间运营这块。 跟主播配合的人这块,点击直播间的【控制台】可以进到直播控制台界面,这里可以看到本场直播的所有信息。包括直播状态,时长,当前时间等基础信息,也要数据面板可以看到观看数据,互动数据,商品数据,订阅数据四个维度的直播详细信息。 [图片] 以上是信息这一块。 另一块就是需要着重操作的推送控制了。 顾名思义,这里是控制台,也就是要帮主播在后台控制商品的推荐和抽奖活动的发起。 开播后,当主播讲到某个商品时,后台可以点击商品后面的推送,将这个商品在直播间突出浮动出来,可以多次推送,每次推送显示时长60s。 [图片] 抽奖的话,也是后台推送,目前不能由主播自己发起,后台推送抽奖后,主播端就有了一个礼物盒子的图标,主播点击图标就可以开始抽奖了。 [图片] 教程就讲到这里, 祝大家在用微信小程序直播插件做出更好成绩! 有不懂的可以加树袋熊的私人微信交流沟通, 拉你进直播插件学习交流社群! 微信号:guoweigang1994 ---------------------------------------- 本文适合于已经开通小程序直播插件的各位朋友和客户 如果想要了解如何开通及此插件的详情, 看看微信官方文章 小程序直播,你关心的都在这https://mp.weixin.qq.com/s/B6tVH7awQC-mBSg_f3yezA
2020-03-14 - 用“实时数据推送”,轻松做小程序弹幕、实时排名
为什么要做实时数据推送?简单来说,使用实时数据推送可以更有效率的拉取数据,在某些场景会非常有用,比如可以用来做弹幕,聊天室,协同办公,做实时排名更新,做实时刷新,可以帮助我们做小程序动态页面,用户的体验更加流畅。 话不多说,我用一个demo演示来做个对比。demo模拟的是一个投票场景,比如我们常见的票选班干部。 Demo演示1 - 常规数据库操作1)用户登入。 2)用户进行投票。 3)后端数据库新增投票记录。 4)前端统计投票结果,生成排名和投票记录。 [图片] 可以看到常规的数据库操作,它是没有实时更新数据的,用户投票后,需要重新加载页面才能看到最新的结果。 而如果用实时数据库操作,页面又会是怎样一种效果? Demo演示2 - 实时数据推送1)用户登入。 2)监听数据库数据变化。 3)用户进行投票。 4)后端数据库新增投票记录。 5)后端推送数据变化结果给到前端。 6)前端接收数据,生成实时排名结果和投票记录。 [图片] 这里我用了两个模拟设备进行演示,可以看到当有用户进行投票时,数据能够马上更新上来,无需重新加载页面,其他用户也能实时看到数据的变化。 这样一对比,实时数据推送对小程序开发的作用就很明显了,简单罗列几点特点: 1)自动接收数据更新推送。 2)前端页面实时更新。 3)用户体验提升。 4)提高页面的响应速度(无需重载)。 实时数据库(WebSocket)对于不懂后端的小伙伴,想要用实时数据推送功能,可以用知晓云SDK来做,核心功能是知晓云的实时数据库(WebSocket)。 知晓云的实时数据库功能可以实现订阅数据表的数据增删改变化,当表数据改变时,小程序端可以实时接收到数据的变化。 [图片] 实时数据推送的应用场景十分丰富。比如聊天室、弹幕、文章新评论、文档协作等等场景就十分需要。
2020-08-07 - 微信开发者工具 1.03.2011111 RC 更新说明
下载地址Windows 64、Windows 32、macOS1、支持设置插件页面为自定义编译条件的启动页面 [图片] 2、第三方平台小程序支持使用企业微信模拟器进行调试 企业微信的服务商与微信小程序的第三方平台不是一个体系,为小程序接入企业微信,需要走企业微信的服务商模式。 但是还是可以先在开发者工具上进行适配调试 本次更新放开了第三方平台小程序无法显示企业微信模拟器的限制。 3、优化新建项目流程 为了简化新建和导入小程序、小游戏项目的操作,开发者工具优化了创建项目的流程。除了可以更快的从导入按钮选择文件夹进行导入之外,在创建时,工具亦会自动区分本次操作是新建还是导入。 [图片] 4、保留上次预览的二维码 为了避免开发者因预览准备耗时过长,无法收起预览面板处理其他事务,我们对预览浮窗进行了改造,支持在预览浮窗收起的状态下,继续执行生成预览二维码处理流程,预览按钮的图标显示为对应的处理状态。 [图片] 再次点击预览时,将展示上次生成的预览二维码。 需要点击刷新二维码,才会主动触发再次预览 [图片] 本功能可在 设置 -> 通用设置 -> 保留上次的预览二维码 中启用。 [图片] 5、云开发控制台文件存储配置 云开发存储功能在使用时,可能会遇到 CDN 缓存更新不及时的问题,导致用户查看的文件版本较旧。在存储 -> 存储配置中,现已提供缓存配置,可以针对不同的文件、文件后缀和文件目录设定缓存时间,从而保证缓存的有效性。 [图片] 6、修改 appid支持下拉选取最近使用 在 详情 -> 基本信息 面板中,点击修改appid时,支持下拉选择最近使用的appid。 [图片] 7、体验评分支持导出报告运行完体验评分之后支持导出报告内容。 [图片] 8、支持切后台后可以获取用户位置 增加 wx.startLocationUpdateBackground 等相关位置 API 支持 工具设置页位置消息交互对齐客户端 [图片] 9、云开发静态网站托管支持自定义域名 静态网站托管是云开发为开发者提供的 Web 资源托管服务,网站的静态资源(HTML、JavaScript、CSS、图片、音频、视频等)可以托管在该服务上,并享有 CDN 加速、免鉴权打开小程序等能力。除了使用静态网站托管提供的默认域名外,现在你还可以绑定自己拥有的域名到静态网站托管,绑定之后,访问该域名即可访问静态网站托管中的所有资源文件。详情。 [图片] 10、静态网站和云存储支持上传文件夹 将文件夹 / 文件拖入控制台即可上传文件夹所有内容至静态网站/云存储。在拖入文件/文件夹后会出现确认框并支持自定义配置。 [图片] 11、云开发拓展功能入口优化 随着云开发拓展功能的增多,云开发控制台提供了用户自定义顶部工具栏的能力,可以将常用的功能固定到顶部工具栏中快速查看,也可以隐藏平时不需要的功能。 [图片] 12、云开发支持云托管云托管是云开发为开发者提供的原生容器服务,用户可面向代码/镜像等多种方式使用,无需维护复杂的容器环境,可专注于自身的业务,一键开通后即可享受能自动扩缩容的容器资源,并享有更多微信相关能力。 [图片]
2020-11-17 - 小程序给图片加水印
1.效果(位置+当前时间) [图片][图片] 2.代码实现 <canvas class='canvas' style="width:{{canvasWidth}}px;height:{{canvasHeight}}px;top:{{canvasHeight*2}}px;"canvas-id"firstCanvas"></canvas> [图片][图片]
2020-01-07 - 微信小程序查看原生组件的代码结构
大家在开发过程中大多数有遇到过想修改微信小程序的原生组件样式的时候吧 比如修改复选框的样式如下: [图片] 这几个 css 类官方明明没有提供,在网上百分之九十九的文章都是直接告诉你这么做,但是没人告诉你为啥这么做 有咩有和我一样第一次看到一脸懵逼的举个手😄 本着不抛弃不放弃的思想,终于在我不断探索下(其实是胡乱一蒙)找到了方法 进入复选框官方文档[图片] 2. 鼠标右键 审查示例代码(这里是个iframe) [图片] 3. 审查示例代码里的的复选框 [图片] 嘻嘻😁就能看到代码结构了 然后通过类名还能找到样式 完成!!!!
2020-03-30 - 针对新手很容易出现理解误区的微信小程序订阅消息模块
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 - 分享微信的9个好用技巧
今天@微信时刻 分享了一些好用的微信技巧,一起来看看其中有多少是你已经知道的吧。 01、快速定位未读信息 聊天列表一长,有时候寻找未读消息就成了一件头疼的事,其实你只需要双击底部导航栏的「微信」选项框,即可快速跳转至最新一条未读消息。 [图片] 02、「微信运动」也有「拉黑」功能 不想看到某个讨厌的人天天占领微信运动封面? 不想被爸妈知道自己周末只走了 100 步? 拉黑微信是是不可能的,这辈子都不可能,但你可以拉黑微信运动。 [图片] 打开微信运动>右上角齿轮>「隐私及提醒设置」>「不与他(她)排行」把好友添加到此「黑名单」,你和他(她)互相看不到对方步数,就此在运动榜上相忘于江湖吧。 03、如何触发「对方正在输入」? [图片] 「对方正在输入」的提示仅在好友收到消息后 10 秒内回复才会触发,还有以下限制条件: 回复的文字需要出现在输入框,仍位于输入法候选框无效仅限手机端微信网络通畅看缘份04、微信群可以只有一个人 点击主页右上角「+」>「发起群聊」>「面对面建群」>设置密码>「进入该群」。 [图片] 只要不将群密码分享出去,这个群就永远只有你一个人,文件、表情包、图片,随便发! 05、释放手机空间 聊天记录越来越多,珍贵的照片和视频难道只有删除和备份至电脑两种选择? 「腾讯相册」小程序了解一下,在线导入微信照片和视频,再也不怕过期了。 [图片] 如果你选择用 QQ 号登陆,还将解锁 QQ 空间相册,没准能找到小学初中的杀马特照片。 06、合并聊天记录转发的妙用 找不到聊天信息的发送时间?选中需要查看的信息,合并发送(可以选择发送给文件传输助手或自己),精确到秒的时间戳给你显示得明明白白。 [图片] 07、收藏夹还能这么用 1.日程管理 「我」>「收藏」,点击右上角「+」新建收藏,在下方工具栏中选择「列表」>「待办」,即可进行简单的日程管理,甚至可以将待办事项在聊天列表中置顶,时刻提醒自己不忘 deadline。 [图片] 2.拼图 新建收藏>插入多张图片>点击右上角「…」,保存为图片,即可生成长图。 [图片] 08、内置提醒功能长按对话框中的信息,在弹出的选项中选择「提醒」,指定提醒时间,最短可以是 1 小时以后,最长可设置到差不多一年以后。 [图片] 到了设定时间,你的微信就会收到相应提醒,点击可跳转至聊天内容。会议、约会、文件处理、回复信息……微信帮你安排得明明白白。 原文链接:https://mp.weixin.qq.com/s/756VLV9qzVOU_T2xuIjwcg
2020-05-15 - es6支持错误regeneratorRuntime is not defined
Promise现在可以使用了,但是yield 关键字被转码后,是这样的: var t1 = regeneratorRuntime.mark(function t1() { var l; return regeneratorRuntime.wrap(function t1$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return t; case 2: l = _context.sent; console.log(l); case 4: case 'end': return _context.stop(); } } }, t1, this); }); 代码执行报错: WAService.js:3 thirdScriptError regeneratorRuntime is not defined;at "pages/index/index" page lifeCycleMethod onLoad function ReferenceError: regeneratorRuntime is not defined 开发工具和手机上都这样
2017-04-05 - 获取直播房间列表接口能否返回该直播回放功能是否关闭字段?
需求:获取到直播间列表之后,我们需要判断该直播间是否开启直播回放功能,开启直播回放则显示“查看回放”按钮,跳转直播间查看回放。
2020-04-22 - 小程序直播销售的商品链接可以跳转到其他的小程序吗?
比如我是一个商超类的小程序,开通直播来进行商品的销售,商品链接可以设置成我们超市在京东到家的店铺里的商品吗?
2020-05-08 - 小程序video组件怎样设置只显示中间播放按钮?
[代码]<[代码][代码]video[代码] [代码]src[代码][代码]=[代码][代码]"{{item.video.url}}"[代码] [代码]loop[代码][代码]=[代码][代码]"{{true}}"[代码] [代码]enable-progress-gesture[代码][代码]=[代码][代码]"{{true}}"[代码] [代码]show-fullscreen-btn[代码][代码]=[代码][代码]"{{false}}"[代码] [代码]show-play-btn[代码][代码]=[代码][代码]"{{false}}"[代码] [代码]show-progress[代码][代码]=[代码][代码]"{{false}}"[代码] [代码]show-center-play-btn[代码][代码]=[代码][代码]"{{true}}"[代码] [代码]enable-play-gesture[代码][代码]=[代码][代码]"{{true}}"[代码] [代码]autoplay[代码][代码]=[代码][代码]"{{true}}"[代码][代码]/>[代码][代码]show-center-play-btn[代码][代码]=[代码][代码]"{{true}}" [代码][代码]这个加不加都没看到中间按钮[代码]
2019-10-09 - wx.getSystemInfo 获取不到手机类型?
[图片] [图片] 手机型号:iphone11 主要是底部那条横杠太蛋疼了,想根据手机型号做适配
2019-11-06 - 开发工具安装不了 ?
[图片]
2020-04-01 - 小程序如何把图片转换成base64
小程序chooseImage时如何把图片转换成base64
2017-07-31 - 小程序如何获取video的视频时长
小程序如何获取video的视频时长
2019-05-24 - 请问有没有方法来监听用户关闭或离开小程序?
请问有没有方法来监听用户关闭或离开小程序?
2019-11-29 - 微信小程序自定义导航栏组件(完美适配所有手机),可自定义实现任何你想要的功能
背景 在做小程序时,关于默认导航栏,我们遇到了以下的问题: Android、IOS手机对于页面title的展示不一致,安卓title的显示不居中 页面的title只支持纯文本级别的样式控制,不能够做更丰富的title效果 左上角的事件无法监听、定制 路由导航单一,只能够返回上一页,深层级页面的返回不够友好 探索 小程序自定义导航栏已开放许久>>了解一下,相信不少小伙伴已使用过这个功能,同时不少小伙伴也会发现一些坑: 机型多如牛毛:自定义导航栏高度在不同机型始终无法达到视觉上的统一 调皮的胶囊按钮:导航栏元素(文字,图标等)怎么也对不齐那该死的胶囊按钮 各种尺寸的全面屏,奇怪的刘海屏,简直要抓狂 一探究竟 为了搞明白原理,我先去翻了官方文档,>>飞机,点过去是不是很惊喜,很意外,通篇大文尽然只有最下方的一张图片与这个问题有关,并且啥也看不清,汗汗汗… 我特意找了一张图片来 [图片] 分析上图,我得到如下信息: Android跟iOS有差异,表现在顶部到胶囊按钮之间的距离差了6pt 胶囊按钮高度为32pt, iOS和Android一致 动手分析 我们写一个状态栏,通过wx.getSystemInfoSync().statusBarHeight设置高度 Android: [图片] iOS:[图片] 可以看出,iOS胶囊按钮与状态栏之间距离为:4px, Android为8px,是不是所有手机都是这种情况呢? 答案是:苹果手机确实都是4px,安卓大部分都是7和8 也会有其他的情况(可以自己打印getSystemInfo验证)如何快速便捷算出这个高度,请接着往下看 如何计算 导航栏分为状态栏和标题栏,只要能算出每台手机的导航栏高度问题就迎刃而解 导航栏高度 = 胶囊按钮高度 + 状态栏到胶囊按钮间距 * 2 + 状态栏高度 注:由于胶囊按钮是原生组件,为表现一致,其单位在各种手机中都为px,所以我们自定义导航栏的单位都必需是px(切记不能用rpx),才能完美适配。 解决问题 现在我们明白了原理,可以利用胶囊按钮的位置信息和statusBarHeight高度动态计算导航栏的高度,贴一个实现此功能最重要的方法 [代码]let systemInfo = wx.getSystemInfoSync(); let rect = wx.getMenuButtonBoundingClientRect ? wx.getMenuButtonBoundingClientRect() : null; //胶囊按钮位置信息 wx.getMenuButtonBoundingClientRect(); let navBarHeight = (function() { //导航栏高度 let gap = rect.top - systemInfo.statusBarHeight; //动态计算每台手机状态栏到胶囊按钮间距 return 2 * gap + rect.height; })(); [代码] gap信息就是不同的手机其状态栏到胶囊按钮间距,具体更多代码实现和使用demo请移步下方代码仓库,代码中还会有输入框文字跳动解决办法,安卓手机输入框文字飞出解决办法,左侧按钮边框太粗解决办法等等 胶囊信息报错和获取不到 问题就在于 getMenuButtonBoundingClientRect 这个方法,在某些机子和环境下会报错或者获取不到,对于此种情况完美可以模拟一个胶囊位置出来 [代码]try { rect = Taro.getMenuButtonBoundingClientRect ? Taro.getMenuButtonBoundingClientRect() : null; if (rect === null) { throw 'getMenuButtonBoundingClientRect error'; } //取值为0的情况 if (!rect.width) { throw 'getMenuButtonBoundingClientRect error'; } } catch (error) { let gap = ''; //胶囊按钮上下间距 使导航内容居中 let width = 96; //胶囊的宽度,android大部分96,ios为88 if (systemInfo.platform === 'android') { gap = 8; width = 96; } else if (systemInfo.platform === 'devtools') { if (ios) { gap = 5.5; //开发工具中ios手机 } else { gap = 7.5; //开发工具中android和其他手机 } } else { gap = 4; width = 88; } if (!systemInfo.statusBarHeight) { //开启wifi的情况下修复statusBarHeight值获取不到 systemInfo.statusBarHeight = systemInfo.screenHeight - systemInfo.windowHeight - 20; } rect = { //获取不到胶囊信息就自定义重置一个 bottom: systemInfo.statusBarHeight + gap + 32, height: 32, left: systemInfo.windowWidth - width - 10, right: systemInfo.windowWidth - 10, top: systemInfo.statusBarHeight + gap, width: width }; console.log('error', error); console.log('rect', rect); } [代码] 以上代码主要是借鉴了拼多多的默认值写法,android 机子中 gap 值大部分为 8,ios 都为 4,开发工具中 ios 为 5.5,android 为 7.5,这样处理之后自己模拟一个胶囊按钮的位置,这样在获取不到胶囊信息的情况下,可保证绝大多数机子完美显示导航头 吐槽 这么重要的问题,官方尽然没有提供解决方案…竟然提供了一张看不清的图片??? 网上有很多ios设置44,android设置48,还有根据不同的手机型号设置不同高度,通过长时间的开发和尝试,本人发现以上方案并不完美,并且bug很多 代码库 Taro组件gitHub地址详细用法请参考README 原生组件npm构建版本gitHub地址详细用法请参考README 原生组件简易版gitHub地址详细用法请参考README 由于本人精力有限,目前只计划发布维护好这2种组件,其他组件请自行修改代码,有问题请联系 备注 上方2种组件在最下方30多款手机测试情况表现良好 iPhone手机打电话和开热点导致导航栏样式错乱,问题已经解决啦,请去demo里测试,这里特别感谢moments网友提出的问题 本文章并无任何商业性质,如有侵权请联系本人修改或删除 文章少量部分内容是本人查询搜集而来 如有问题可以下方留言讨论,微信zhijunxh 比较 斗鱼: [图片] 虎牙: [图片] 微博: [图片] 酷狗: [图片] 知乎: [图片] [图片] 知乎是这里边做的最好的,但是我个人认为有几个可以优化的小问题 打电话或者开启热点导致样式错落,这也是大部门小程序的问题 导航栏下边距太小,看起来不舒服 搜索框距离2侧按钮组距离不对等 自定义返回和home按钮中的竖线颜色重了,并且感觉太粗 如果您看到了此篇文章,请赶快修改自己的代码,并运用在实践中吧 扫码体验我的小程序: [图片] 创作不易,如果对你有帮助,请移步Taro组件gitHub原生组件gitHub给个星星 star✨✨ 谢谢 测试信息 手机型号 胶囊位置信息 statusBarHeight 测试情况 iPhoneX 80 32 281 369 48 88 44 通过 iPhone8 plus 56 32 320 408 24 88 20 通过 iphone7 56 32 281 368 24 87 20 通过 iPhone6 plus 56 32 320 408 24 88 20 通过 iPhone6 56 32 281 368 24 87 20 通过 HUAWEI SLA-AL00 64 32 254 350 32 96 24 通过 HUAWEI VTR-AL00 64 32 254 350 32 96 24 通过 HUAWEI EVA-AL00 64 32 254 350 32 96 24 通过 HUAWEI EML-AL00 68 32 254 350 36 96 29 通过 HUAWEI VOG-AL00 65 32 254 350 33 96 25 通过 HUAWEI ATU-TL10 64 32 254 350 32 96 24 通过 HUAWEI SMARTISAN OS105 64 32 326 422 32 96 24 通过 XIAOMI MI6 59 28 265 352 31 87 23 通过 XIAOMI MI4LTE 60 32 254 350 28 96 20 通过 XIAOMI MIX3 74 32 287 383 42 96 35 通过 REDMI NOTE3 64 32 254 350 32 96 24 通过 REDMI NOTE4 64 32 254 350 32 96 24 通过 REDMI NOTE3 55 28 255 351 27 96 20 通过 REDMI 5plus 67 32 287 383 35 96 28 通过 MEIZU M571C 65 32 254 350 33 96 25 通过 MEIZU M6 NOTE 62 32 254 350 30 96 22 通过 MEIZU MX4 PRO 62 32 278 374 30 96 22 通过 OPPO A33 65 32 254 350 33 96 26 通过 OPPO R11 58 32 254 350 26 96 18 通过 VIVO Y55 64 32 254 350 32 96 24 通过 HONOR BLN-AL20 64 32 254 350 32 96 24 通过 HONOR NEM-AL10 59 28 265 352 31 87 24 通过 HONOR BND-AL10 64 32 254 350 32 96 24 通过 HONOR duk-al20 64 32 254 350 32 96 24 通过 SAMSUNG SM-G9550 64 32 305 401 32 96 24 通过 360 1801-A01 64 32 254 350 32 96 24 通过
2019-11-17 - 小程序能打开通讯录获取联系人信息吗【急求官方解答】
在微信小程序中,调用通讯录,当选中某个时,返回小程序界面并附带 联系人信息数据
2018-06-27 - 在小程序里,想做一个能够根据手机外壳颜色自动改变主题的功能。
阿斯达斯大所多大所大所多大所大所
2019-06-04 - switch组件无法修改关闭时的颜色
[图片] 要实现这样的效果发现switch组件只能改变开启时的颜色无法改变关闭时的颜色
2018-05-24 - 小程序怎么怎么保存PDF文件到手机的文件文件目录
现在小程序里面需要用到下载PDF表格到用户手机文件目录,试了一下调用wx.downloadFile和wx.saveFile发现不是自己想要的功能,这种不能保存在用户手机的文件目录。有没有人解决了下载PDF到手机文件目录的
2018-06-27 - 小程序能直接发送pdf给微信好友吗?
我的需求是这样的: 小程序有一个页面有生成报告按钮,是生成一个pdf报告的功能,现在是要点击分享或者通过其他途径,直接将pdf发送给微信好友,而不是分享一个展示那个pdf文件的小程序页面给好友。 预期效果: [图片] 实际效果: [图片]
2018-09-14 - 小程序打开PDF以后如何保存或者转发给好友?
[代码]wx.downloadFile({ // 示例 url,并非真实存在 url: 'http://example.com/somefile.pdf', success(res) { const filePath = res.tempFilePath wx.openDocument({ filePath, success(res) { console.log('打开文档成功') } }) } })[代码][代码] [代码] [代码] [代码] [代码]安卓手机打开pdf文件以后点击右上角三点按钮可以有发送给好友选项,但是苹果手机就没法任何选项了。如何给小程序打开的pdf文件发送或者保存下来?[代码]
2019-03-22 - 如何知道自己的小程序有没有被添加到桌面
官方有没有api支持查询自己的小程序是否已经被用户添加到我的小程序里面或者桌面上
2018-09-04 - 请问大众点评小程序打开“定位服务”设置这个是怎么做到的?
[图片] [图片] 大众点评小程序,如果手机设置没开启定位会提醒用户去设置里开启定位,请问打开系统设置这个是调用API实现的么?还是引入第三方的?谢谢 还有请问可以打开系统设置里微信应用的权限界面么? [图片]
2018-09-11