关于h5页面:IOS系统下开启键盘后顶部输入框掉下来了

通过初步排查,发现几个景象: 1 只在页面总长度超过屏幕长度时产生。2 只在开启键盘时产生。3 只在固定定位的页面顶部输入框获取焦点(focus)时产生。4 只在屏幕有滚动时产生。缺点有两个景象: 1 顶部DOM掉下来了,在大概屏幕两头的地位。2 此时如果持续滚动屏幕,顶部DOM不会再维持以后地位。也就是说,它“进入”了页面的文档流。咱们初步判断是顶部DOM失去了固定定位,起因未知。怎么解决呢? 咱们决定绕过这个问题,只有看起来是失常的就行。 当点击顶部DOM输入框、调出键盘的时候: 1 页面滚回到顶部;2 屏幕滚动时,敞开IOS输出面板。要害代码如下: $("#search_value").on("focus", function() { $(window).scrollTop(0) }) window.ontouchmove = function() { $('input').blur(); };

September 1, 2023 · 1 min · jiezi

关于h5页面:H5开屏从龟速到闪电企微是如何做到的

导读|H5开屏龟速常是令开发者头疼的问题。腾讯企业微信团队对该景象进行剖析优化,最终H5开屏耗时130ms,达到秒开成果!企微前端开发工程师陈智仁将分享可用可扩大的Hybird H5秒开计划。该团队应用离线包解决了资源申请耗时的问题,在这个根底上通过耗时剖析找到瓶颈环节,进一步采纳“预热”进行优化提速以解决了WebView初始化、数据预拉取、js执行(app初始化)耗时的问题。心愿这些通用办法对你有帮忙。 背景 服务端渲染(SSR)是Web支流的性能优化伎俩。SSR直出相比传统的SPA利用加载渲染躲避了首屏拉取数据和资源申请的网络往返耗时。团队针对Web开发也曾经反对了SSR能力。近期出于动态化经营的思考,咱们抉择了Web开发,同时咱们也接到了晋升体验的诉求。 以企业微信要开发的页面为例:采纳SSR计划,从用户点击到首屏渲染的耗时均值约600ms,白屏工夫的存在是能够感知到的。为了尽可能打消白屏达到秒开成果,咱们尝试做更多摸索。 计划思路 1) 计划选型如何实现页面秒开呢?从最直观的渲染链路来动手剖析。下图列出了从用户点击到看到首屏渲染可交互,一个SPA利用次要环节的加载流程。咱们调研了业内相干计划,从渲染链路的视角来看下常见计划的优化思路。 传统离线包在加载渲染过程中,网络IO是很显著的一个耗时瓶颈。传统的离线包计划思路很间接,如果网络耗时那就将资源离线,很好地解决了资源申请的耗时。用Service Worker也能达到离线包的成果,同时也是Web规范。首次渲染优化个别须要联合客户端配置预启动脚本来达到缓存资源的成果。 SSRSSR则从另外的角度登程,在申请页面的时候就进行服务端数据拉取和页面直出,首屏得以在一个网络往返就能够展现,无效地躲避了后续须要期待css/js资源加载、数据拉取的工夫。性能体验有比拟大的晋升,在BFF遍及的状况下开发模式简略,很受欢迎。 公司内相干工作思考到WebView的初始化(冷启动/ 二次启动)、页面网络申请、首屏数据接口的耗时,白屏工夫还是可感知地存在的。以咱们要开发的页面为例采纳SSR首屏耗时均值~600ms,可交互工夫均值~1100ms。如何进一步打消白屏?这里为各位介绍公司内外针对h5首屏性能优化的优良计划。 手Q团队的VasSonic是集大成者,次要思路是采纳WebView和数据预拉取并行的形式。这套计划须要客户端和服务端采纳指定协定革新接入,开发时也有肯定的革新工作。 微信游戏团队次要思路是利用jsCore做客户端预渲染,用户点击后间接上屏。这个办法也达到了很好的成果,首屏FCP工夫从1664ms升高到了411ms。 咱们做了一个简要的计划比照,能够看到每个计划都针对渲染链路的某个或多个环节做了优化,其中VasSonic的成果比较显著。不过联合企业微信业务理论状况,咱们列出了如下几点思考: 首先,接入对客户端和服务端有肯定的革新老本,业务开发也有肯定的革新工作。其次,咱们曾经有一套的对立公布平台,心愿能复用这套公布能力。最初,性能上有没有进一步优化的空间呢?业务需要对体验上的要求是心愿达到更好的性能成果或者说尽可能齐全地打消白屏 基于以上思考,咱们在上述计划的根底上做了进一步的实际摸索,以冀望达到更好的性能成果。 2)计划架构 为了达到尽可能齐全打消白屏,咱们还是从初始问题登程,联合渲染链路进行剖析,思路上针对每个环节采取对应的优化办法。 每个环节的优化在具体落地时会存在着计划的利弊取舍。比方预拉取数据个别的思路是交给客户端来做,然而存在着客户端申请和h5申请两套机制(鉴权、申请通道等方面)如何协调的问题。在渲染链路剖析时,如果业务的js执行也奉献了不少耗时,有没有可能从通用根底计划的角度来解决这个问题,同时也能缩小业务对性能优化的关注?这是个值得各位思考摸索的问题。具体的内容会在前面开展来说。 如图展现了计划的优化思路和主流程。计划应用离线包解决了资源申请耗时的问题,在这个根底上通过耗时剖析找到瓶颈环节,进一步采纳预热的思路进行优化提速,解决了WebView初始化、数据预拉取、js执行(app初始化)耗时的问题,最终达到了现实的性能体验。 图1 上屏流程 图2 计划架构 上面咱们具体介绍下计划,包含:离线包技术、预热提速和进一步的优化工作。 离线包减速 为了躲避资源申请耗时,咱们应用了离线包技术。离线包技术是比拟成熟的计划,相干打包、公布拉取的计划这里不多说了,次要说下计划中一些设计上的考量。 1)加载流程 咱们通过offid作为离线包利用的标识,fallback机制保障离线资源不可达时用户也能够失常拜访页面,通过离线包预拉取和异步检测更新机制进步了离线包命中率,尽可能打消了网络资源加载的耗时。 2)fallback机制因为用户网络情况的不确定性,离线包加载可能存在失败的状况。为了保障可用性,咱们确定了离线包加载不阻塞渲染的思路。当用户点击入口url,对应offid离线包在本地不存在时,会fallback申请现网页面,同时异步加载离线包。所以咱们针对离线包的打包构造,依照现网URL path来组织资源门路。这样客户端申请拦挡解决也会比拟不便,不须要了解映射规定。当发现离线包不匹配资源时,放过申请透到现网即可。如图展现了咱们的离线包构造示例。 3. 离线包生命周期为了进步离线包命中率,咱们会配置一些机会(e.g.入口曝光)来预拉取离线包。 离线包的更新机制:客户端加载时依据offid检测到本地离线包的存在,则间接应用拉起,同时启动异步版本检测和更新。如果新包版本号大于本地版本号则更新缓存,同时公布平台也反对辨别测试环境、正式环境以及按条件灰度。 上了离线包后,能够看到页面的首屏耗时均值从基准无优化的1340ms降到了963ms,离线包的预拉取和更新策略则使离线包命中率达到了95%。首屏耗时失去了肯定的升高,但也还有比拟大的优化空间,须要更一步的剖析优化。 预热提速 通过离线包的减速,咱们解决了资源申请耗时的问题,不过从整个渲染链路来看还有很大的优化空间,咱们做了具体的耗时剖析,找出耗时瓶颈,针对耗时环节做了进一步的优化提速。 1)耗时剖析离线包技术躲避了资源申请耗时,然而从整个渲染链路来看还有很大的优化空间,咱们做了耗时剖析如下。 Hybird利用中,WebView初始化是比拟耗时的环节,这里咱们针对iOS WebView做了测试。 数据拉取方面,不同入口页面的耗时不一,某些入口页面比拟重的接口耗时超过了1s。 此外,咱们发现js执行也奉献了不少耗时。以某入口页面为例,框架初始化工夫~10ms,app初始化工夫~440ms。 2)渲染链路预热提速预热流程咱们的指标是打消白屏,这里现实的计划是找到一种和业务无关的通用解法。计划的次要思路是预热,把能提前做的都做了。预热是不是就是把WebView提前创立进去就好了呢?不是的,这里的预热波及到多个渲染环节的优化组合。如图展现了预热的整体流程,上面一个个来解。 2)WebView预创立为了打消WebView的耗时,咱们采取了全局的预创立WebView,机会为配置入口曝光。不过全局复用预热WebView不可避免地会引入可能的业务内存泄露问题,下文会介绍对应的躲避计划。 数据预拉取数据拉取是页面渲染的一个耗时环节。为了打消数据预拉取耗时,在预创立WebView阶段咱们同时进行了数据预拉取。 数据预拉取常见的思路是交给客户端来做,然而存在着客户端申请和h5申请两套机制如何协调的问题,以申请鉴权为例,存在以下的问题: 第一,Web团队本身有一层node BFF,实现了相应的数据拉取业务逻辑,而客户端则走的公有协定通道申请C++后盾,二者是不同的鉴权机制。 第二,如果交给客户端来做,能够接入HTTP申请这套机制,革新老本比拟大,如果复用原有通道,则一份数据业务逻辑须要两套实现。 如何设计一套通用可扩大的计划?咱们心愿做到客户端只关注容器的能力(预热、资源拦挡等),屏蔽掉更深刻的对Web的感知,这样的解耦能够无效管制计划的复杂度。因而,这里咱们针对离线包配置项减少了preUrl字段,使客户端保护更通用的能力,数据预拉取交给业务团队来做,具体如下: 第一,客户端:拉取某个离线包配置项时会读取该字段,同时针对以后曝光的入口url可能存在多个有着不同的数据需要,这里会进行收集,将曝光url中的业务key参数拼接到preUrl来初始化WebView,这些作为通用能力。 第二,业务:preUrl页面在加载时会拉取相应的业务数据存到localStorage,理论的数据预拉取申请放到业务方发动,也能够很好地兼容已有的技术栈。 JS预执行很靠近指标了,最初js执行的耗时能不能打消呢?首先来看下440ms的耗时具体在哪里,通过剖析看到,框架初始化仅须要不到10ms的工夫,而真正的大头在业务代码的执行,其中代码编译耗时~80ms,其余的都是业务app初始化执行工夫,这个是业务自身复杂度造成的。 咱们首先思考了创立两个WebView的计划,一个负责加载preUrl预拉取数据,另一个负责loadUrl上屏,这样设计上比拟简洁强壮,不过实际下来发现成果不现实,如图展现了该计划的成果,渲染不稳固能够感知到白屏的存在。在曾经有了预拉取数据和离线资源的状况下,实践上用户点击后须要期待的就只有渲染这块的耗时,理论咱们发现在简单利用初始化时存在js执行耗时较大的问题。 ...

December 19, 2022 · 1 min · jiezi

关于h5页面:公众号项目报错xxxfail-the-permission-value-is-offline-verifying

获取地位信息时报错:公众号我的项目中应用微信JS-SDK,获取地位信息时,在微信开发者工具中调试时报以下谬误:getLocation:fail, the permission value is offline verifying 尽管在线上环境中没有问题,但开发环境还是受影像的。 解决办法在开发者工具地址栏拜访以下地址: https://www.weixinsxy.com/jssdk/ 拜访后果如图所示: 受权 点击须要的权限,点击受权,而后再拜访本地的开发地址进行测试,会提醒受权,点击确认解决问题。

August 9, 2022 · 1 min · jiezi

关于h5页面:利用canvas绘制时钟

window.onload = function () { var canvas = document.querySelector('canvas'); var context = canvas.getContext('2d'); // 绘制圆盘 function clock() { //绘制圆盘 context.beginPath(); context.arc(300, 300, 200, 0, Math.PI * 2); context.fillStyle = 'pink'; context.fill(); context.closePath(); //绘制时刻度 for (i = 0; i < 12; i++) { context.save(); context.lineWidth = 4; context.beginPath(); //将原点平移300,300 context.translate(300, 300); context.rotate(i * (Math.PI / 6)); context.moveTo(0, -180); context.lineTo(0, -200); context.stroke(); context.fillStyle = 'black'; context.rotate(Math.PI / 6); context.fillText(i + 1, -8, -220); context.closePath(); context.restore(); } //绘制分刻度 for (i = 0; i < 60; i++) { context.save(); context.lineWidth = 1; context.beginPath(); //将原点平移300,300 context.translate(300, 300); context.rotate(i * (Math.PI / 30)); context.moveTo(0, -190); context.lineTo(0, -200); context.stroke(); context.closePath(); context.restore(); } // 获取以后工夫 var today = new Date(); var hour = today.getHours(); var min = today.getMinutes(); var sec = today.getSeconds(); // hour = hour + min / 60; // 绘制时针 context.lineWidth = 3 context.save(); context.translate(300, 300); context.rotate(hour * Math.PI / 6); context.beginPath(); context.moveTo(0, 10) context.lineTo(0, -80); context.stroke() context.closePath(); context.restore(); // 绘制分针 context.lineWidth = 2; context.save(); context.translate(300, 300); context.rotate(min * (Math.PI / 30)); context.beginPath(); context.moveTo(0, 10); context.lineTo(0, -100); context.stroke() context.closePath(); context.restore(); // 绘制秒针 context.lineWidth = 1; context.save(); context.translate(300, 300); context.rotate(sec * Math.PI / 30); context.beginPath(); context.moveTo(0, 10); context.lineTo(0, -120); context.strokeStyle = 'red'; context.stroke() context.closePath(); context.restore(); // 绘制交叉处 // context.lineWidth=1 context.save(); context.translate(300, 300); context.beginPath(); context.arc(0, 0, 5, 0, Math.PI * 2); context.fill(); context.fillStyle = '#ccc' context.strokeStyle = 'red' context.stroke() context.closePath(); context.restore(); setInterval(clock, 1000)//超时模仿间歇 } clock(); }效果图如下: ...

September 15, 2021 · 2 min · jiezi

关于h5页面:移动端开发手册

挪动端设施适配挪动端适配计划 postcss px->vwremamfe-flexible rem挪动端罕用知识点横竖屏探讨判断横竖屏的最佳实现 ✳️ @media 媒体查问window.matchMedia / matcheswindow.innerHeight >= window.innerWidthwindow.orientation(旋转角度:0/90/-90/180)screen.width / screen.height挪动端兼容挪动端疑难杂症视频问题

August 26, 2021 · 1 min · jiezi

关于h5页面:移动端适配

计划介绍挪动端设计稿: 375*768 【基准】通常有两种计划,对立的思维就是 设计稿基准值*设施宽度比 375px=100% 宽度   也就是说1px = 100/375 %在375下1px,则在750px下 750/375 * 100/375 =  200/375 %; 计划一:px 转vwvw: 页面总宽度为100vw。能够配置转换时的设施宽度是375,会在不同设施宽度上进行适配。能够设置在横屏时持续应用设施宽坐基准值。 'postcss-px-to-viewport': { unitToConvert: 'px', //须要转换的单位,默认为"px" viewportWidth: 375, // 视窗的宽度,对应的是咱们设计稿的宽度 viewportHeight: 667,//视窗的高度,依据375设施的宽度来指定,个别指定667,也能够不配置 unitPrecision: 13, // 指定`px`转换为视窗单位值的小数位数(很多时候无奈整除) propList: ['*'], // 能转化为vw的属性列表 viewportUnit: 'vw', // 指定须要转换成的视窗单位,倡议应用vw fontViewportUnit: 'vw', //字体应用的视口单位 selectorBlackList: ['.ignore-', '.hairlines'], //指定不转换为视窗单位的类,能够自定义,能够有限增加,倡议定义一至两个通用的类名 minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也能够设置为你想要的值 mediaQuery: false, // 容许在媒体查问中转换`px` replace: true, //是否间接更换属性值,而不增加备用属性 exclude: [], //疏忽某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件 landscape: true, //是否增加依据 landscapeWidth 生成的媒体查问条件 @media (orientation: landscape) landscapeUnit: 'vh', //横屏时应用的单位 landscapeWidth: 375 //横屏时应用的视口宽度 }计划二: rem把基准值设置为rem, 在款式里都是依照rem来写 ...

August 26, 2021 · 1 min · jiezi

关于h5页面:H5唤醒app

url scheme形式 var downloader, scheme = ":lklk" //须要关上的app scheme地址 iosDownload = "jjjj",//如果关上scheme生效的app下载地址 anDownload = "http://xxx.com" var u = navigator.userAgent var isAndroid = u.indexOf("Android")>-1 || u.indexOf("Linux")>-1 //g var isIos = !!u.match(/\(i[^;]+;(u;)?CPU.+Mac OS X/);//ios终端 // 给id为openBtn的按钮增加点击事件处理函数 document.getElementById("openBtn").onclick = function(){ window.location.href = scheme //尝试关上scheme //设置3秒的定时下载工作 3秒之后下载app downloader = setTimeout(function(){ if(isAndroid){ window.location.href = anDownload } if(isIos){ windwo.location.href = iosDownload } },3000) }, document.addEventListener('visibilitychange webkitvisibilitychange',function(){ //如果页面暗藏 揣测关上scheme胜利 革除下载工作 if(docuemnt.hidden || docuemnt.webkitHidden){ clearInterval(downloader) } }) window.addEventListener('pagehide',function(){ clearInterval(downloader) })

March 14, 2021 · 1 min · jiezi

4图片的显示

现今的内容展示,简单的文字已经无法吸引读者的眼球。我们往往需要添加图片、音频、视频等元素吸引用户。下面我们来一起看看图片的显示实现。1、 创建舞台 var stage = new createjs.Stage("myStage");2、实例化图片对象 // 可以使用图片url、base64字符串 // (如果使用图片url注意要将代码放在web服务器环境下访问,此处有跨域资源限制问题将不能显示图片) var img = new createjs.Bitmap('https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=938848384,3548229994&fm=111&gp=0.jpg');3、 调整图片位置 img.x = 100;4、添加图片到舞台 stage.addChild(img);5、更新舞台stage.update(); 显示结果: done完成!

September 10, 2019 · 1 min · jiezi

微信小程序-webview-与-h5-通过-postMessage-实现实时通讯的实现

原文:https://pantao.parcmg.com/pre... 在做 React Native 应用时,如果需要在 App 里面内嵌 H5 页面,那么 H5 与 App 之间可以通过 Webview 的 PostMessage 功能实现实时的通讯,但是在小程序里面,虽然也提供了一个 webview 组件,但是,在进行 postMessage 通讯时,官方文档里面给出了一条很变态的说明: 网页向小程序 postMessage 时,会在特定时机(小程序后退、组件销毁、分享)触发并收到消息。e.detail = { data },data 是多次 postMessage 的参数组成的数组这里面已经说的很明白了,不管我们从 H5 页面里面 postMessage 多少次,小程序都是收不到的,除非: 用户做了回退到上一页的操作组件销毁用户点击了分享这里面其实我没有完全说对,官方其实说的是 小程序后退,并没有说是用户做回退操作,经过我的实测,确实人家表达得很清楚了,我们通过微信官方的SDK调起的回退也是完全可行的: wx.miniProgram.navigateBack()大体思路从上面的分析和实测中我们可以知道,要实现无需要用户操作即可完成的通讯,第三种情况我们是完全不需要考虑了的,那么来仔细考虑第 1 和第 2 种场景。 第 1 种方式:回退当我们想通过网页向小程序发送数据,同时还可以回退到上一个页面时,我们可以在 wx.miniProgram.postMessage 之后,立马调用一次 wx.miniProgram.navigateBack(),此时小程序的操作是: 处理 postMessage 信息回退到上一页我们在处理 postMessage 的时候做一些特殊操作,可以将这些数据保存下来 第 2 种方式:组件销毁这是我感觉最合适的一种方式,可以让小程序拿到数据,同时还保留在当前页面,只需要销毁一次 webview 即可,大概的流程就是: 小程序 postMessage小程序 navigateTo 将小程序页面导向一个特殊的页面小程序的那个特殊页面立马回退到 webview 所在的页面webview 所在的页面的 onShow 里面,做一次处理,将 webview 销毁,然后再次打开触发 onMessage 拿到数据H5 页面再次被打开这种方式虽然变态,但是至少可以做到实时拿到数据,同时还保留在当前 H5 页面,唯一需要解决的是,在做这整套操作前,H5 页面需要做好状态的缓存,要不然,再次打开之后,H5 的数据就清空了。 ...

August 20, 2019 · 4 min · jiezi

移动端H5-input输入完成后页面底部留白问题

说明最近在用vue写几个H5页面在微信上展示,遇到一个在弹窗上input输入完成之后点击键盘的完成,页面底部留出一片空白的问题 出现原因分析当键盘抬起时,window.scrollY会从0变到键盘的高度,所以解决办法就是当input失去焦点的时候,将window.scrollY重新设置为0解决给所有的input`textarea组件设置获取焦点和设置焦点事件,失去焦点的时候将`window.scrollY`设置为0因为的是vue所以结合vue来写代码<template> <input class="m-input" :value="value" @input="$emit('input', $event.target.value)" @focus="inputFocus()" @focusout="inputFocusOut"></template><script> export default { name: "MInput", props:['value'], data(){ return{ timer:null } }, methods:{ inputFocus(){ if(this.timer){ clearTimeout(this.timer) } }, inputFocusOut(){ this.timer = setTimeout(() => { window.scrollTo(0,0) },10) } }, destroyed(){ if(this.timer){ clearTimeout(this.timer) } } }</script>获取焦点事件,判断定时器是否存在如果存在的话清除掉(上一个input设置的定时器)失去焦点事件,将window.scrollY设置为0,并且给一个10的定时器,减少页面失去焦点的突兀感(为了顺滑一点点)destroyed vue组件中如果使用了定时器,一定要记得在组件销毁的生命周期里将清时期清除掉,防止全局定时器过多,容易爆栈补充:解决方案2在input上分别增加focus和blur的方法,基本可以解决键盘回落后留白问题;handleFocus(event) { let e = event.currentTarget; setTimeout(() => { e.scrollIntoView({ block: 'start', behavior: 'smooth' }); }, 300);}handleblur() { let e = event.currentTarget; setTimeout(() => { e.scrollIntoView({ block: 'end', behavior: 'smooth' }); }, 300); window.scrollTo(0, 0);}补充:解决方案3 //解决键盘弹出后挡表单的问题 window.addEventListener('resize', function() { if( document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA' ) { window.setTimeout(function() { if('scrollIntoView' in document.activeElement) { document.activeElement.scrollIntoView(); } else { document.activeElement.scrollIntoViewIfNeeded(); } }, 0); } });补充:页面来回弹跳问题:失焦时的scrollTop=0造成的页面弹跳。本来iOS是做了这方面的优化,在软键盘弹出和收起时页面会smooth的平滑,由于我加了scrollIntoView破坏了原生的优化导致弹跳了解决:handleFocus(event) { clearTimeout(this.timer);}handleblur() { this.timer = setTimeout(() => { document.body.scrollTop = 0; window.pageXOffset = 0; document.documentElement.scrollTop = 0; }, 100);}最后本文首发于:移动端H5 input输入完成后页面底部留白问题补充参考:一文彻底解决iOS中键盘回落后留白问题更新于2019/06/13

July 1, 2019 · 1 min · jiezi

H5活动页面2小时快速开发

前言这是一套我自己经常用的H5活动页面开发脚手架,针对目前一般的H5页面,基本上2小时就能完成相关的开发内容。俗话说:工欲善其事必先利其器,有了这么一套H5页面脚手架,我相信80%的H5页面,都能够在2小时当中开发完成。脚手架是基于React的,这里已经帮您做了如下几个基本事情 页面缩放,基于宽度为750px的视觉稿,当然您也可以自行修改页面微信分享,只需要配置获取分享相关的签名接口,就可以实现预加载loading,如果您需要,基于create.js 的 preload模块实现包含了Axios,你可以直接使用Axios请求相关的接口项目地址https://github.com/mmcai/single-page-react-h5目录结构说明|——build(代码编译后所在的文件目录)|——config(webpack相关的配置目录)|——node_modules|——public(html模板,favicon及其他静态资源存放目录)|——scripts(webpack各个环境脚本执行文件存放目录)|——src(项目源码存放路径)| |——components(组件存放目录,如果有?)| |——containers(具体页面存放目录)| |——...(具体看代码)| |——public(一些第三方库包含的相关资源存放的目录,比如swiper,animate.css)| |——utils(工具函数存放目录)| |——index.js(webpack入口执行文件)| |——registerServiceWorker.js(生产环境中处理文件的缓存,用来加快页面访问速度的)||——.gitingnore|——LICENSE|——package-lock.json|——package.json|——README.md如何使用确认您当前的系统是否具有以下相关环境(这里说的是window系统下)- git- node(npm)为了确保下载npm的体验更好,您可以选择以下两种方式之一1、安装cnpmnpm install -g cnpm --registry=https://registry.npm.taobao.org2、修改npm下载源npm config set registry https://registry.npm.taobao.org第一步npm install 或者 cnpm install 安装相关的依赖包 第二步npm run start 启动项目 第三步编写您的活动页面相关业务逻辑代码 第四步npm run build 打包(编译项目) 其他如果您的页面需要配置微信当中的分享,请保证与您联调的后台接口返回内容是如下格式的 { success: true, data: { "debug": true, "appId": "wxb17a5a75c9ad192b", "timestamp": "1533897246", "nonceStr": "b9aab9c2ii", "signature": "d1c126bbcaff2f48d415fd71e92684978c0e1a1c", "jsApiList": [ "onMenuShareTimeline", "onMenuShareAppMessage", "onMenuShareQQ", "onMenuShareWeibo", "onMenuShareQZone" ] }}或者您修改utils文件夹下面的Weixin.js文件 关于资源预加载 在config.js配置资源的根路径window.BaseUrl在webpack的入口文件index.js里面配置资源列表Manifest引入工具函数import PreLoad from './utils/PreLoad';执行资源预加载函数,然后再回调函数里面初始化页面关于日常的H5活动页面的一些开发建议如果您是一个H5活动页面的开发者,我相信,你一定经历过一周内好几个活动页面的同时开发,同时要求上线的需求。一开始在公司工作流程不怎么规范的时候,基本上运营人员,在即将做活动的前一天下午才会告诉你,我们有个活动页面,能不能明天上,最迟也要后天上线,我想您一定是崩溃的,但是我们的工作的一部分就是服务他们,所以抱怨几句,往往还是需要做这些临时的需求的。H5活动页面一般分为几种: 常规活动(促销类的,拉新类的)系列互动(一揽子促销)运营数据报告类的游戏类的...H5活动页面的特点往往是:生命周期短,上线时间紧张总的来说就是:快速上线,快速扔掉。这个时候如何保质保量,快速做好,快速上线,就是一门艺术了,根据公司的配置不同会有好多情况。我这边的原则就是,分析活动页面上那些是需要用户操作的,那些是展示的所有会让用户填写和操作的地方都用代码实现,其他一切展示的内容,统统使用图片。前端页面里面大量使用图片,可能会让自己不舒服,因为没啥技术含量,但我们做事情不是给自己看的,别人才不管你代码如何,只要你的项目能够按时保质保量的上线,后台能够有足够优秀的数据,就妥了。把有限的生命浪费在那些重复的,而且你已经会的,写过千八百遍的代码上不值得。如果你能开发一个工具或者制定一套工作流程能快速完成H5活动的任务,这个才是需要挑战的。技术是一种手段,是为了增加那些事情工作效率的,总的来说是为别人服务,脱离的服务,它的存在也就没有价值了不是吗。 ...

April 25, 2019 · 1 min · jiezi

iOS12 系统 BUG —— 微信 H5 输入法收起留有空白

BUG描述打开 iOS 12 系统的微信 H5 页面,当点击 input 输入弹出输入法的时候,页面如果上移了,那输入法收起的时候页面无法自动回到底部,会留有空白,导致下次点击弹起的失效。上面三张图中,第一张是未点击的状态,第二张是点击最后一个输入框弹出输入法的状态,第三张是收起输入法的状态,可以发现在第三张图中底部出现空白,页面没有下移返回底部。2. 解决方法可以通过重置元素滚动位置,触发回流(Reflow),从而消除底部空白。// 判断是否为 iOS 微信isIOSWeChat () { const ua = window.navigator.userAgent.toLowerCase() return ua.includes(‘micromessenger’) && ua.includes(’like mac os x’)}// input 失去焦点事件inputBlur (e) { if (isIOSWeChat()) { // window.scrollTo(0, document.documentElement.scrollTop || document.body.scrollTop) 亦可 document.body.scrollTop = document.body.scrollTop; }}本文首发于个人博客:https://www.aquatalking.com/b…(完)

March 7, 2019 · 1 min · jiezi

前端在h5页面调起微信支付接口和支付宝接口(日常笔记)

微信支付结合微信支付的api文档进行配置。参考JSAPI支付开发者文档——微信内H5调起支付微信文档中的例子如下。function onBridgeReady(){ WeixinJSBridge.invoke( ‘getBrandWCPayRequest’, { “appId”:“wx2421b1c4370ec43b”, //公众号名称,由商户传入 “timeStamp”:“1395712654”, //时间戳,自1970年以来的秒数 “nonceStr”:“e61463f8efa94090b1f366cccfbbb444”, //随机串 “package”:“prepay_id=u802345jgfjsdfgsdg888”, “signType”:“MD5”, //微信签名方式: “paySign”:“70EA570631E4BB79628FBCA90534C63FF7FADD89” //微信签名 }, function(res){ if(res.err_msg == “get_brand_wcpay_request:ok” ){ // 使用以上方式判断前端返回,微信团队郑重提示: //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。 } }); }// 下面是兼容不同浏览器绑定事件的方法if (typeof WeixinJSBridge == “undefined”){ if( document.addEventListener ){ document.addEventListener(‘WeixinJSBridgeReady’, onBridgeReady, false); }else if (document.attachEvent){ document.attachEvent(‘WeixinJSBridgeReady’, onBridgeReady); document.attachEvent(‘onWeixinJSBridgeReady’, onBridgeReady); }}else{ onBridgeReady();}我们主要是从后台中获取数据传入onBridgeReady这个方法中。所以第一步是获取数据,第二步是把获取到的数据传入到onBridgeReady方法第一步:发送请求获取后台数据1.在对应的api文件下封装请求(get)export function wechatPay(type, vid, token, point, discount) { let discount_type = discount || null return axios.get(${Host}/api/save_mobile,{ params: { pay_type: type, video_id: vid, token, point, discount_type } })}2.在对应的组件调用请求<p @click="_wechatPay(paytype, $route.query.video_id, info.token, info.points)" class=“submit”>发送支付请求</p>import { wechatPay } from ‘../../../api/pay.js’export default { name: ‘payfooter’, computed: { info() { return this.$store.state.user.info }, // 获取选择支付的方式 paytype() { return this.$store.state.pay.paytype } }, methods: { _wechatPay(type, vid, token, point) { wechatPay(type, vid, token, point).then(res => { console.log(res) // 这个res就是后台返回的数据 }) } }} 3.后台返回的json格式数据如下(这不是console出来,方便显示我就直接把json数据复制过来){ “code”: 0, “data”: { “appId”: “wx5beac7c40c”, “nonceStr”: “8491k3Rs5”, “package”: “prepay_id=wx07**************2653”, “paySign”: “CDE21B40C1A”, “signType”: “MD5”, “timeStamp”: “151” }, “msg”: null}第二步:把数据传给onBridgeReady函数所以真正需要获取的内容是 res.data.data,然后再把res.data.data的值传给onBridgeReady函数4.重新整理一下代码就是 methods: { _wechatPay(type, vid, token, point) { wechatPay(type, vid, token, point).then(res => { res = res.data if(res.code === 0) { this.onBridgeReady(res.data) // 这样就把res.data传给onBridgeReady函数 } }) }, // 微信支付api相关配置文档 onBridgeReady(data) { if (typeof WeixinJSBridge === ‘undefined’) { this.$toast({ message: ‘请使用微信内置浏览器进行支付’ }) } else { WeixinJSBridge.invoke( ‘getBrandWCPayRequest’, { appId: data.appId, // 公众号名称,由商户传入 timeStamp: data.timeStamp, // 时间戳,自1970年以来的秒数 nonceStr: data.nonceStr, // 随机串 package: data.package, signType: data.signType, // 微信签名方式: paySign: data.paySign // 微信签名 }, res => { if (res.err_msg === ‘get_brand_wcpay_request:ok’) { this.$toast({ message: ‘支付成功’ }) this.$router.push({path: ‘/videoplayer’, query: { video_id: this.$route.query.video_id }}) // 支付成功之后跳转的路由 } else { this.$toast({ message: ‘支付失败’ }) } } ) } }, }支付宝支付与微信支付不同的是,支付宝支付后台是返回form格式的数据,如下<form name=“punchout_form” method=“post” action=“https://openapi.alipay.com/gateway.do?charset=UTF-8&method=alipay.trade.wap.pay&sign=DEpMkIeWUs6EW3QKlt9OHYv%2FqkporO8Sr5%2Bay5VA9dpx3pAbIiPPajQ2gEcWHvz5bmkxH8ZvHUXahQL9S69p9wKNXpXOxYadlsxE8QKGUc4cO5rrgGq08%2BpiOq%2FOz4fLogEBWANXILUMWXNzJn8YryNifZ416Pd%2BxkKgXs%2Fo%2FQDcqEUgVXXPRq7IGRGQg%2FpZkOhxCH%2Fq%2B9hnWEncAfQLlAXfPqjdcQTNJ0TJdVr1X1ENOdAr5LQkydWw2EQ8g%3D%3D&return_url=+https%3A%2F%2**********&notify_url=+https%3A%2F%Fpub%2Fapi%2Fv1%2Fallback1&version=1.0&app_id=2057&sign_type=R&timestamp=2019-055&alipay_sdk=al*****.49.ALL&format=json”> <input type=“hidden” name=“biz_content” value="{&quot;body&quot;:&quot;&quot;,&quot;enable_pay_channels&quot;:&quot;balance,moneyFund,bankPay,debitCardExpress,creditCardExpress,creditCard,pcredit,pcreditpayInstallment,coupon,point,voucher,mdiscount,honeyPay&quot;,&quot;out_trade_no&quot;:&quot;132ecf937ad84487aa6cbaeb2ec157fe&quot;,&quot;product_code&quot;:&quot;13&quot;,&quot;subject&quot;:&quot;SpringBoot 2.x微信支付在线教育网站项目实战&quot;,&quot;timeout_express&quot;:&quot;20m&quot;,&quot;total_amount&quot;:&quot;98&quot;}"> <input type=“submit” value=“立即支付” style=“display:none” ></form><script>document.forms[0].submit();</script>那么在处理后台数据的时候用下面的方法(参考网络大神)_wechatPay(type, vid, token, point) { wechatPay(type, vid, token, point).then(res => { const form = res.data const div = document.createElement(‘div’) div.id = ‘alipay’ div.innerHTML = form document.body.appendChild(div) document.querySelector(’#alipay’).children[0].submit() // 执行后会唤起支付宝 })} ...

January 7, 2019 · 2 min · jiezi