偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

12個(gè)前端必會(huì) H5 問(wèn)題及解決方法

新聞 前端
作為一個(gè)開(kāi)發(fā)了多個(gè) H5 項(xiàng)目的前端工程師,在開(kāi)發(fā)過(guò)程中難免會(huì)遇到一些兼容性等 爬過(guò)坑 的問(wèn)題。

前言

作為一個(gè)開(kāi)發(fā)了多個(gè) H5 項(xiàng)目的前端工程師,在開(kāi)發(fā)過(guò)程中難免會(huì)遇到一些兼容性等 爬過(guò)坑 的問(wèn)題?,F(xiàn)在我將這些問(wèn)題一一匯總一下,并在后面給出 坑產(chǎn)生的原理 ,和 現(xiàn)階段常規(guī)的填坑方案 。由此來(lái)做一個(gè)階段性的總結(jié)。

問(wèn)題

下面列舉了我遇到的一些常規(guī)問(wèn)題,如有遇到其他問(wèn)題請(qǐng)?jiān)谠u(píng)論區(qū)補(bǔ)充,之后我也會(huì)實(shí)踐后加以補(bǔ)充,感謝?。ń?jīng)常更新該文)

移動(dòng)端 H5 相關(guān)問(wèn)題匯總:

  • 1px 問(wèn)題
  • 響應(yīng)式布局
  • iOS 滑動(dòng)不流暢
  • iOS 上拉邊界下拉出現(xiàn)白色空白
  • 頁(yè)面件放大或縮小不確定性行為
  • click 點(diǎn)擊穿透與延遲
  • 軟鍵盤(pán)彈出將頁(yè)面頂起來(lái)、收起未回落問(wèn)題
  • iPhone X 底部欄適配問(wèn)題
  • 保存頁(yè)面為圖片和二維碼問(wèn)題和解決方案
  • 微信公眾號(hào) H5 分享問(wèn)題
  • H5 調(diào)用 SDK 相關(guān)問(wèn)題及解決方案
  • H5 調(diào)試相關(guān)方案與策略

移動(dòng)端 H5 相關(guān)基礎(chǔ)技術(shù)概覽

 

 

原理與實(shí)踐

之前兩篇文章已經(jīng)詳細(xì)的論述了 1px 問(wèn)題與 響應(yīng)式布局 問(wèn)題,并給出了原理和解決方案。

防止丟失, 點(diǎn)贊收藏 后跳轉(zhuǎn)至快捷通道: 1px 通道與響應(yīng)式布局通道

接下來(lái)呢,我們看看其他問(wèn)題的原理和解決方案吧。

以下解決方案,均經(jīng)過(guò)我測(cè)試成功,健康安全,請(qǐng)放下食用。由于篇幅原因,某些非核心解決方案的實(shí)現(xiàn)細(xì)節(jié)暫未談?wù)?,需要自行研究?/p>

iOS 滑動(dòng)不流暢

表現(xiàn)

上下滑動(dòng)頁(yè)面會(huì)產(chǎn)生卡頓,手指離開(kāi)頁(yè)面,頁(yè)面立即停止運(yùn)動(dòng)。整體表現(xiàn)就是滑動(dòng)不流暢,沒(méi)有滑動(dòng)慣性。

產(chǎn)生原因

為什么 iOS 的 webview 中 滑動(dòng)不流暢,它是如何定義的?

最終我在 safari 文檔里面尋找到了答案(文檔鏈接在參考資料項(xiàng))。

 

 

原來(lái)在 iOS 5.0 以及之后的版本,滑動(dòng)有定義有兩個(gè)值 auto 和 touch ,默認(rèn)值為 auto 。

  1. -webkit-overflow-scrolling: touch; /* 當(dāng)手指從觸摸屏上移開(kāi),會(huì)保持一段時(shí)間的滾動(dòng) */ 
  2.  
  3. -webkit-overflow-scrolling: auto; /* 當(dāng)手指從觸摸屏上移開(kāi),滾動(dòng)會(huì)立即停止 */ 

解決方案

1.在滾動(dòng)容器上增加滾動(dòng) touch 方法

將 -webkit-overflow-scrolling 值設(shè)置為 touch

  1. .wrapper { 
  2.     -webkit-overflow-scrolling: touch; 

設(shè)置滾動(dòng)條隱藏: .container ::-webkit-scrollbar {display: none;}

可能會(huì)導(dǎo)致使用 position:fixed; 固定定位的元素,隨著頁(yè)面一起滾動(dòng)

2.設(shè)置 overflow

設(shè)置外部 overflow 為 hidden ,設(shè)置內(nèi)容元素 overflow 為 auto 。內(nèi)部元素超出 body 即產(chǎn)生滾動(dòng),超出的部分 body 隱藏。

  1. body { 
  2.     overflow-y: hidden; 
  3. .wrapper { 
  4.     overflow-y: auto; 

兩者結(jié)合使用更佳!

iOS 上拉邊界下拉出現(xiàn)白色空白

表現(xiàn)

手指按住屏幕下拉,屏幕頂部會(huì)多出一塊白色區(qū)域。手指按住屏幕上拉,底部多出一塊白色區(qū)域。

產(chǎn)生原因

在 iOS 中,手指按住屏幕上下拖動(dòng),會(huì)觸發(fā) touchmove 事件。這個(gè)事件觸發(fā)的對(duì)象是整個(gè) webview 容器,容器自然會(huì)被拖動(dòng),剩下的部分會(huì)成空白。

解決方案

1. 監(jiān)聽(tīng)事件禁止滑動(dòng)

移動(dòng)端觸摸事件有三個(gè),分別定義為

  1. 1. touchstart :手指放在一個(gè)DOM元素上。 
  2. 2. touchmove :手指拖曳一個(gè)DOM元素。 
  3. 3. touchend :手指從一個(gè)DOM元素上移開(kāi)。 

顯然我們需要控制的是 touchmove 事件,由此我在 W3C 文檔中找到了這樣一段話(huà)

Note that the rate at which the user agent sends touchmove events is implementation-defined, and may depend on hardware capabilities and other implementation details.

touchmove 事件的速度是可以實(shí)現(xiàn)定義的,取決于硬件性能和其他實(shí)現(xiàn)細(xì)節(jié)

preventDefault 方法,阻止同一觸點(diǎn)上所有默認(rèn)行為,比如滾動(dòng)。

由此我們找到解決方案,通過(guò)監(jiān)聽(tīng) touchmove ,讓需要滑動(dòng)的地方滑動(dòng),不需要滑動(dòng)的地方禁止滑動(dòng)。

值得注意的是我們要過(guò)濾掉具有滾動(dòng)容器的元素。

實(shí)現(xiàn)如下:

  1. document.body.addEventListener('touchmove', function(e) { 
  2.     if(e._isScroller) return
  3.     // 阻止默認(rèn)事件 
  4.     e.preventDefault(); 
  5. }, { 
  6.     passive: false 
  7. }); 

2. 滾動(dòng)妥協(xié)填充空白,裝飾成其他功能

在很多時(shí)候,我們可以不去解決這個(gè)問(wèn)題,換一直思路。根據(jù)場(chǎng)景, 我們可以將下拉作為一個(gè)功能性的操作 。

比如:下拉后刷新頁(yè)面

 

 

頁(yè)面放大或縮小不確定性行為

表現(xiàn)

雙擊或者雙指張開(kāi)手指頁(yè)面元素,頁(yè)面會(huì)放大或縮小。

產(chǎn)生原因

HTML 本身會(huì)產(chǎn)生放大或縮小的行為,比如在 PC 瀏覽器上,可以自由控制頁(yè)面的放大縮小。但是在移動(dòng)端,我們是不需要這個(gè)行為的。所以,我們需要禁止該不確定性行為,來(lái)提升用戶(hù)體驗(yàn)。

原理與解決方案

HTML meta 元標(biāo)簽標(biāo)準(zhǔn)中有個(gè) 中 viewport 屬性,用來(lái)控制頁(yè)面的縮放,一般用于移動(dòng)端。如下圖 MDN 中介紹

 

 

移動(dòng)端常規(guī)寫(xiě)法

  1. <meta name="viewport" content="width=device-width, initial-scale=1.0"

因此我們可以設(shè)置 maximum-scale 、 minimum-scale 與 user-scalable=no 用來(lái)避免這個(gè)問(wèn)題

  1. <meta name=viewport 
  2.   content="width=device-width, initial-scale=1.0, minimum-scale=1.0 maximum-scale=1.0, user-scalable=no"

click 點(diǎn)擊事件延時(shí)與穿透

表現(xiàn)

監(jiān)聽(tīng)元素 click 事件,點(diǎn)擊元素觸發(fā)時(shí)間延遲約 300ms 。

點(diǎn)擊蒙層,蒙層消失后,下層元素點(diǎn)擊觸發(fā)。

產(chǎn)生原因

為什么會(huì)產(chǎn)生 click 延時(shí)?

iOS 中的 safari,為了實(shí)現(xiàn)雙擊縮放操作,在單擊 300ms 之后,如果未進(jìn)行第二次點(diǎn)擊,則執(zhí)行 click 單擊操作。也就是說(shuō)來(lái)判斷用戶(hù)行為是否為雙擊產(chǎn)生的。但是,在 App 中,無(wú)論是否需要雙擊縮放這種行為, click 單擊都會(huì)產(chǎn)生 300ms 延遲。

為什么會(huì)產(chǎn)生 click 點(diǎn)擊穿透?

雙層元素疊加時(shí),在上層元素上綁定 touch 事件,下層元素綁定 click 事件。由于 click 發(fā)生在 touch 之后,點(diǎn)擊上層元素,元素消失,下層元素會(huì)觸發(fā) click 事件,由此產(chǎn)生了點(diǎn)擊穿透的效果。

原理與解決方案

解決方案一:使用 touchstart 替換 click

前面已經(jīng)介紹了,移動(dòng)設(shè)備不僅支持點(diǎn)擊,還支持幾個(gè)觸摸事件。那么我們現(xiàn)在基本思路就是用 touch 事件代替 click 事件。

將 click 替換成 touchstart 不僅解決了 click 事件都延時(shí)問(wèn)題,還解決了穿透問(wèn)題。因?yàn)榇┩竼?wèn)題是在 touch 和 click 混用時(shí)產(chǎn)生。

在原生中使用

  1. el.addEventListener("touchstart", () => { console.log("ok"); }, false); 

在 vue 中使用

  1. <button @touchstart="handleTouchstart()">點(diǎn)擊</button> 

開(kāi)源解決方案中,也是既提供了 click 事件,又提供了 touchstart 事件。如 vant 中的 button 組件

 

 

那么,是否可以將 click 事件全部替換成 touchstart 呢?為什么開(kāi)源框架還會(huì)給出 click事件呢?

我們想象一種情景,同時(shí)需要點(diǎn)擊和滑動(dòng)的場(chǎng)景下。如果將 click 替換成 touchstart 會(huì)怎樣?

事件觸發(fā)順序: touchstart , touchmove , touchend , click 。

很容易想象,在我需要 touchmove 滑動(dòng)時(shí)候,優(yōu)先觸發(fā)了 touchstart 的點(diǎn)擊事件,是不是已經(jīng)產(chǎn)生了沖突呢?

所以呢,在具有滾動(dòng)的情況下,還是建議使用 click 處理。

在接下來(lái)的 fastclick 開(kāi)源庫(kù)中也做了如下處理。針對(duì) touchstart 和 touchend ,截取了部分源碼。

  1. // If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and: 
  2. // 1) the user does a fling scroll on the scrollable layer 
  3. // 2) the user stops the fling scroll with another tap 
  4. // then the event.target of the last 'touchend' event will be the element that was under the user's finger 
  5. // when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check 
  6. // is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42). 
  7. this.updateScrollParent(targetElement); 
  8.  
  9. // Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled 
  10. // and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42). 
  11. scrollParent = targetElement.fastClickScrollParent; 
  12. if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) { 
  13. return true

主要目的就是,在使用 touchstart 合成 click 事件時(shí),保證其不在滾動(dòng)的父元素之下。

解決方案二:使用 fastclick 庫(kù)

使用 npm/yarn 安裝后使用

  1. import FastClick from 'fastclick'
  2.  
  3. FastClick.attach(document.body, options); 

同樣,使用 fastclick 庫(kù)后, click 延時(shí)和穿透問(wèn)題都沒(méi)了

按照我的慣例,只要涉及開(kāi)源庫(kù),那么我們一定要去了解它實(shí)現(xiàn)的原理。主要是將現(xiàn)有的原生事件集合封裝合成一個(gè)兼容性較強(qiáng)的事件集合。

fastclick源碼 核心代碼不長(zhǎng), 1000 行不到。有興趣可以了解一下!

軟鍵盤(pán)將頁(yè)面頂起來(lái)、收起未回落問(wèn)題

表現(xiàn)

Android 手機(jī)中,點(diǎn)擊 input 框時(shí),鍵盤(pán)彈出,將頁(yè)面頂起來(lái),導(dǎo)致頁(yè)面樣式錯(cuò)亂。

移開(kāi)焦點(diǎn)時(shí),鍵盤(pán)收起,鍵盤(pán)區(qū)域空白,未回落。

產(chǎn)生原因

我們?cè)赼pp 布局中會(huì)有個(gè)固定的底部。安卓一些版本中,輸入彈窗出來(lái),會(huì)將解壓 absolute和 fixed 定位的元素。導(dǎo)致可視區(qū)域變小,布局錯(cuò)亂。

原理與解決方案

軟鍵盤(pán)將頁(yè)面頂起來(lái)的解決方案,主要是通過(guò)監(jiān)聽(tīng)頁(yè)面高度變化,強(qiáng)制恢復(fù)成彈出前的高度。

  1. // 記錄原有的視口高度 
  2. const originalHeight = document.body.clientHeight || document.documentElement.clientHeight; 
  3.  
  4. window.onresize = function(){ 
  5.   var resizeHeight = document.documentElement.clientHeight || document.body.clientHeight; 
  6.   if(resizeHeight < originalHeight ){ 
  7.     // 恢復(fù)內(nèi)容區(qū)域高度 
  8.     // const container = document.getElementById("container") 
  9.     // 例如 container.style.height = originalHeight; 
  10.   } 

鍵盤(pán)不能回落問(wèn)題出現(xiàn)在 iOS 12+ 和 wechat 6.7.4+ 中,而在微信 H5 開(kāi)發(fā)中是比較常見(jiàn)的 Bug。

兼容原理,1.判斷版本類(lèi)型 2.更改滾動(dòng)的可視區(qū)域

  1. const isWechat = window.navigator.userAgent.match(/MicroMessenger\/([\d\.]+)/i); 
  2. if (!isWechat) return
  3. const wechatVersion = wechatInfo[1]; 
  4. const version = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/); 
  5.   
  6.  // 如果設(shè)備類(lèi)型為iOS 12+ 和wechat 6.7.4+,恢復(fù)成原來(lái)的視口 
  7. if (+wechatVersion.replace(/\./g, '') >= 674 && +version[1] >= 12) { 
  8.   window.scrollTo(0, Math.max(document.body.clientHeight, document.documentElement.clientHeight)); 

window.scrollTo(x-coord, y-coord) ,其中 window.scrollTo(0, clientHeight) 恢復(fù)成原來(lái)的視口

iPhone X系列安全區(qū)域適配問(wèn)題

表現(xiàn)

頭部劉海兩側(cè)區(qū)域或者底部區(qū)域,出現(xiàn)劉海遮擋文字,或者呈現(xiàn)黑底或白底空白區(qū)域。

產(chǎn)生原因

iPhone X 以及它以上的系列,都采用 劉海屏設(shè)計(jì) 和 全面屏手勢(shì) 。頭部、底部、側(cè)邊都需要做特殊處理。才能適配 iPhone X 的特殊情況。

解決方案

設(shè)置安全區(qū)域,填充危險(xiǎn)區(qū)域,危險(xiǎn)區(qū)域不做操作和內(nèi)容展示。

危險(xiǎn)區(qū)域指頭部不規(guī)則區(qū)域,底部橫條區(qū)域,左右觸發(fā)區(qū)域。

 

 

具體操作為: viewport-fit meta 標(biāo)簽設(shè)置為 cover ,獲取所有區(qū)域填充。判斷設(shè)備是否屬于 iPhone X,給頭部底部增加 適配層

viewport-fit 有 3 個(gè)值分別為:

  • auto :此值不影響初始布局視圖端口,并且整個(gè)web頁(yè)面都是可查看的。
  • contain :視圖端口按比例縮放,以適合顯示內(nèi)嵌的最大矩形。
  • cover :視圖端口被縮放以填充設(shè)備顯示。強(qiáng)烈建議使用 safe area inset 變量,以確保重要內(nèi)容不會(huì)出現(xiàn)在顯示之外。

設(shè)置 viewport-fit 為 cover

  1. <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes, viewport-fit=cover"

增加適配層

使用 safe area inset 變量

  1. /* 適配 iPhone X 頂部填充*/ 
  2. @supports (top: env(safe-area-inset-top)){ 
  3.   body, 
  4.   .header{ 
  5.       padding-top: constant(safe-area-inset-top, 40px); 
  6.       padding-top: env(safe-area-inset-top, 40px); 
  7.       padding-top: var(safe-area-inset-top, 40px); 
  8.   } 
  9. /* 判斷iPhoneX 將 footer 的 padding-bottom 填充到最底部 */ 
  10. @supports (bottom: env(safe-area-inset-bottom)){ 
  11.     body, 
  12.     .footer{ 
  13.         padding-bottom: constant(safe-area-inset-bottom, 20px); 
  14.         padding-bottom: env(safe-area-inset-bottom, 20px); 
  15.         padding-top: var(safe-area-inset-bottom, 20px); 
  16.     } 

safe-area-inset-top , safe-area-inset-right , safe-area-inset-bottom , safe-area-inset-left safe-area-inset-* 由四個(gè)定義了視口邊緣內(nèi)矩形的 top , right , bottom 和 left 的環(huán)境變量組成,這樣可以安全地放入內(nèi)容,而不會(huì)有被非矩形的顯示切斷的風(fēng)險(xiǎn)。對(duì)于矩形視口,例如普通的筆記本電腦顯示器,其值等于零。對(duì)于非矩形顯示器(如圓形表盤(pán), iPhoneX 屏幕),在用戶(hù)代理設(shè)置的四個(gè)值形成的矩形內(nèi),所有內(nèi)容均可見(jiàn)。

其中 env() 用法為 env( <custom-ident> , <declaration-value>? ) ,第一個(gè)參數(shù)為自定義的區(qū)域,第二個(gè)為備用值。

其中 var() 用法為 var( <custom-property-name> , <declaration-value>? ) ,作用是在 env() 不生效的情況下,給出一個(gè)備用值。

constant() 被 css 2017-2018 年為草稿階段,是否已被標(biāo)準(zhǔn)化未知。而其他iOS 瀏覽器版本中是否有此函數(shù)未知,作為兼容處理而添加進(jìn)去。

詳情請(qǐng)查看文章末尾的參考資料。

兼容性

 

 

頁(yè)面生成為圖片和二維碼問(wèn)題

表現(xiàn)

在工作中有需要將頁(yè)面生成圖片或者二維碼的需求??赡芪覀兊谝幌氲降模唤o后端來(lái)生成更簡(jiǎn)單。但是這樣我們需要把頁(yè)面代碼全部傳給后端,網(wǎng)絡(luò)性能消耗太大。

解決方案

生成二維碼

使用 QRCode 生成二維碼

  1. import QRCode from 'qrcode'
  2. // 使用 async 生成圖片 
  3. const options = {}; 
  4. const url = window.location.href; 
  5. async url => { 
  6.   try { 
  7.     console.log(await QRCode.toDataURL(url, options)) 
  8.   } catch (err) { 
  9.     console.error(err); 
  10.   } 

將 await QRCode.toDataURL(url, options) 賦值給 圖片 url 即可

生成圖片

主要是使用 htmlToCanvas 生成 canvas 畫(huà)布

  1. import html2canvas from 'html2canvas'
  2.  
  3. html2canvas(document.body).then(function(canvas) { 
  4.     document.body.appendChild(canvas); 
  5. }); 

但是不單單在此處就完了,由于是 canvas 的原因。移動(dòng)端生成出來(lái)的圖片比較模糊。

我們使用一個(gè)新的 canvas 方法多倍生成,放入一倍容器里面,達(dá)到更加清晰的效果,通過(guò)超鏈接下載圖片 下載文件簡(jiǎn)單實(shí)現(xiàn),更完整的實(shí)現(xiàn)方式之后更新

  1. const scaleSize = 2
  2. const newCanvas = document.createElement("canvas"); 
  3. const target = document.querySelector('div'); 
  4. const width = parseInt(window.getComputedStyle(target).width); 
  5. const height = parseInt(window.getComputedStyle(target).height); 
  6. newCanvas.width = width * scaleSize; 
  7. newCanvas.height = widthh * scaleSize; 
  8. newCanvas.style.width = width + "px"
  9. newCanvas.style.height =width + "px"
  10. const context = newCanvas.getContext("2d"); 
  11. context.scale(scaleSize, scaleSize); 
  12. html2canvas(document.querySelector('.demo'), { canvas: newCanvas }).then(function(canvas) { 
  13.   // 簡(jiǎn)單的通過(guò)超鏈接設(shè)置下載功能 
  14.   document.querySelector(".btn").setAttribute('href', canvas.toDataURL()); 

根據(jù)需要設(shè)置 scaleSize 大小

微信公眾號(hào)分享問(wèn)題

表現(xiàn)

在微信公眾號(hào) H5 開(kāi)發(fā)中,頁(yè)面內(nèi)部點(diǎn)擊分享按鈕調(diào)用 SDK,方法不生效。

解決方案

解決方法:添加一層蒙層,做分享引導(dǎo)。

因?yàn)轫?yè)面內(nèi)部點(diǎn)擊分享按鈕無(wú)法直接調(diào)用,而分享功能需要點(diǎn)擊右上角更多來(lái)操作。

然后用戶(hù)可能不知道通過(guò)右上角小標(biāo)里面的功能分享。又想引導(dǎo)用戶(hù)分享,這時(shí)應(yīng)該怎么做呢?

技術(shù)無(wú)法實(shí)現(xiàn)的,從產(chǎn)品出發(fā)。

 

 

如果技術(shù)上實(shí)現(xiàn)復(fù)雜,或者直接不能實(shí)現(xiàn)。不要強(qiáng)行鉆牛角尖哦,學(xué)會(huì)懟產(chǎn)品,也是程序員必備的能力之一。

H5 調(diào)用 SDK 相關(guān)解決方案

產(chǎn)生原因

在 Hybrid App 中使用 H5 是最常見(jiàn)的不過(guò)了,剛接觸的,肯定會(huì)很生疏模糊。不知道 H5 和 Hybrid 是怎么交互的。怎樣同時(shí)支持 iOS 和 Android 呢?現(xiàn)在來(lái)談?wù)?Hybrid 技術(shù)要點(diǎn), 原生與 H5 的通信 。

解決方案

 

[[337511]]

 

使用 DSBridge 同時(shí)支持 iOS 與 Android

文檔見(jiàn)參考資料

SDK小組 提供方法

1. 注冊(cè)方法 bridge.register

  1. bridge.register('enterApp', function() { 
  2.   broadcast.emit('ENTER_APP'
  3. }) 

2. 回調(diào)方法 bridge.call

  1. export const getSDKVersion = () => bridge.call('BLT.getSDKVersion'

事件監(jiān)聽(tīng)與觸發(fā)法

  1. const broadcast = { 
  2.   on: function(name, fn, pluralable) { 
  3.     this._on(name, fn, pluralable, false
  4.   }, 
  5.   once: function(name, fn, pluralable) { 
  6.     this._on(name, fn, pluralable, true
  7.   }, 
  8.   _on: function(name, fn, pluralable, once) { 
  9.     let eventData = broadcast.data 
  10.     let fnObj = { fn: fn, once: once } 
  11.     if (pluralable && Object.prototype.hasOwnProperty.call(eventData, 'name')) { 
  12.       eventData[name].push(fnObj) 
  13.     } else { 
  14.       eventData[name] = [fnObj] 
  15.     } 
  16.     return this 
  17.   }, 
  18.   emit: function(name, data, thisArg) { 
  19.     let fn, fnList, i, len 
  20.     thisArg = thisArg || null 
  21.     fnList = broadcast.data[name] || [] 
  22.     for (i = 0, len = fnList.length; i < len; i++) { 
  23.       fn = fnList[i].fn 
  24.       fn.apply(thisArg, [data, name]) 
  25.       if (fnList[i].once) { 
  26.         fnList.splice(i, 1
  27.         i-- 
  28.         len-- 
  29.       } 
  30.     } 
  31.     return this 
  32.   }, 
  33.   data: {} 
  34. export default broadcast 

踩坑注意

方法調(diào)用前,一定要判斷 SDK 是否提供該方法 如果 Android 提供該方法,iOS 上調(diào)用就會(huì)出現(xiàn)一個(gè)方法 調(diào)用失敗等彈窗 。怎么解決呢?

提供一個(gè)判斷是否 Android、iOS。根據(jù)設(shè)備進(jìn)行判斷

  1. export const hasNativeMethod = (name) => 
  2.   return bridge.hasNativeMethod('BYJ.' + name) 
  3.  
  4. export const getSDKVersion = function() { 
  5.   if (hasNativeMethod('getSDKVersion')) { 
  6.     bridge.call('BYJ.getSDKVersion'
  7.   } 

同一功能需要iOS,Android方法名相同,這樣更好處理哦

H5 調(diào)試相關(guān)方案策略

表現(xiàn)

調(diào)試代碼一般就是為了 查看數(shù)據(jù) 和 定位 bug 。分為兩種場(chǎng)景,一種是開(kāi)發(fā)和測(cè)試時(shí)調(diào)試,一種是生產(chǎn)環(huán)境上調(diào)試。

為什么有生產(chǎn)環(huán)境上調(diào)試呢?有些時(shí)候測(cè)試環(huán)境上沒(méi)法復(fù)現(xiàn)這個(gè) bug,測(cè)試環(huán)境和生產(chǎn)環(huán)境不一致,此時(shí)就需要緊急生產(chǎn)調(diào)試。

在 PC 端開(kāi)發(fā)時(shí),我們可以直接掉出控制臺(tái),使用瀏覽器提供的工具操作devtools或者查看日志。但是在 App 內(nèi)部我們?cè)趺醋瞿兀?/p>

原理與解決方案

1. vconsole 控制臺(tái)插件

使用方法也很簡(jiǎn)單

  1. import Vconsole from 'vconsole' 
  2.  
  3. new Vconsole() 

 

 

有興趣看看它實(shí)現(xiàn)的基本原理,我們關(guān)注的點(diǎn)應(yīng)該在 vsconsole 如何打印出我們所有 log 的騰訊開(kāi)源vconsole

上述方法僅用于開(kāi)發(fā)和測(cè)試。 生產(chǎn)環(huán)境中不允許出現(xiàn),所以,使用時(shí)需要對(duì)環(huán)境進(jìn)行判斷。

  1. import Vconsole from 'vconsole' 
  2. if (process.env.NODE_ENV !== 'production') { 
  3.     new Vconsole() 

2. 代理 + spy-debugger

操作稍微有點(diǎn)麻煩,不過(guò)我會(huì)詳細(xì)寫(xiě)出,大致分為 4 個(gè)步驟

1. 安裝插件(全局安裝)

  1. sudo npm install spy-debugger -g 

2. 手機(jī)與電腦置于同一 wifi 下,手機(jī)設(shè)置代理

設(shè)置手機(jī)的 HTTP 代理,代理 IP 地址設(shè)置為 PC 的 IP 地址,端口為 spy-debugger 的啟動(dòng)端口

spy-debugger 默認(rèn)端口:9888

Android :設(shè)置 - WLAN - 長(zhǎng)按選中網(wǎng)絡(luò) - 修改網(wǎng)絡(luò) - 高級(jí) - 代理設(shè)置 - 手動(dòng)

IOS :設(shè)置 - Wi-Fi - 選中網(wǎng)絡(luò), 點(diǎn)擊感嘆號(hào), HTTP 代理手動(dòng)

3. 手機(jī)打開(kāi)瀏覽器或者 app 中 H5 頁(yè)面

4. 打開(kāi)桌面日志網(wǎng)站進(jìn)行調(diào)試,點(diǎn)擊 npm 控制臺(tái)監(jiān)聽(tīng)地址。查看抓包和 H5 頁(yè)面結(jié)構(gòu)

這種方式可以調(diào)試生成環(huán)境的頁(yè)面,不需要修改代碼,可以應(yīng)付大多數(shù)調(diào)試需求

總結(jié)

本篇文章耗費(fèi)作者一個(gè)多星期的業(yè)余時(shí)間,存手工敲打 4500 +字,同時(shí)收集,整理之前很多坑點(diǎn)和邊寫(xiě)作邊 思考 和 總結(jié) 。如果能對(duì)你有幫助,便是它最大的價(jià)值。都看到這里還不 點(diǎn)贊 ,太過(guò)不去啦!

由于技術(shù)水平有限,文章中如有錯(cuò)誤地方,請(qǐng)?jiān)谠u(píng)論區(qū)指出,感謝!

 

責(zé)任編輯:張燕妮 來(lái)源: 知乎
相關(guān)推薦

2018-11-01 15:26:38

開(kāi)源軟件安全

2022-04-06 10:09:17

云服務(wù)云計(jì)算

2009-08-24 10:37:11

Silverlight

2009-07-01 18:14:36

JSP亂碼

2022-04-02 20:27:30

ETS操作系統(tǒng)鴻蒙

2021-04-20 11:03:26

人工智能AI機(jī)器學(xué)習(xí)

2011-08-24 17:41:16

MySQL死鎖

2011-05-06 17:25:58

硒鼓

2021-06-17 08:07:35

Linux 內(nèi)存站崗

2018-08-29 13:57:40

前端性能測(cè)試Html5

2013-07-22 14:47:56

iOS開(kāi)發(fā)iOS5中ASIHtt

2016-11-14 10:06:04

大數(shù)據(jù)max位圖

2009-03-04 10:38:36

Troubleshoo桌面虛擬化Xendesktop

2010-08-31 13:49:12

CSS

2019-10-11 19:45:28

SparkSQLHiveHadoop

2025-04-07 07:20:35

SQL慢查詢(xún)性能

2017-06-14 22:11:57

數(shù)據(jù)庫(kù)MySQL死鎖

2010-12-27 10:48:10

VirtualboxFreedos

2021-01-12 11:40:12

SonarQube平臺(tái)數(shù)據(jù)項(xiàng)目授權(quán)

2010-07-22 14:05:33

krb5-telnet
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)