React Native小菜雞的踩坑排雷記錄(4)

一、Text增加點擊態效果

在RN裏,我們經常會遇到點擊文字或者按鈕有響應的。其中,我們的一些按鈕是Text+style 去實現一個按鈕樣式的。當我們點擊文字的時候,會出現只有文字被選中的陰影,而不是覆蓋到整個按鈕上的。
第一個反應就是Text沒覆蓋,或者我們需要在上面蒙上一層全覆蓋的蒙層。由於View標籤在onPress響應無效且不好寫點擊態樣式,我們可以採取Touch系列的組件,這裏可以說下幾個值得注意的點:

  • TouchableOpacity 裏的activeOpacity 這個屬性很好用,當activeOpacity = 1時可以實現失效按鈕的效果,不帶透明度。
  • 在React Native 官方文檔中,有提到過關於Touchable 系列組件不能很好的響應,具體表現就是:有些時候,如果我們有一項操作與點擊事件所帶來的透明度改變或者高亮效果發生在同一幀中,那麼有可能在onPress函數結束之前我們都看不到這些效果。特別是真機上的時候,時好時壞。當然,官方也給出了相關解決方案。對此的一個解決方案是將onPress處理函數中的操作封裝到requestAnimationFrame中,
 handleOnPress() {
  // 謹記在使用requestAnimationFrame、setTimeout以及setInterval時
  // 要使用TimerMixin(其作用是在組件unmount時,清除所有定時器)
  this.requestAnimationFrame(() => {
    this.doExpensiveAction();
  });
}

這裏所要解決的就是一個掉幀的問題,這裏也不再細述,有興趣想了解的可以移步官網性能篇

二、定時器

看到第一個問題的時候,就看到了官網的解決方案裏有一句,在組件unmount時,清除所有定時器!!!這裏提示了我,我在項目裏,也有些setTimeout和setInterval是沒有在unmount時,去清除的。因爲我們發現很多 React Native 應用發生致命錯誤(閃退)是與計時器有關,這很難受,且致命。這裏就列一個清除的小栗子🌰吧~~

import React, { Component } from "react";

export default class Hello extends Component {
  componentDidMount() {
    this.timer = setTimeout(() => {
      console.log("把一個定時器的引用掛在this上");
    }, 500);
  }
  componentWillUnmount() {
    // 請注意Un"m"ount的m是小寫

    // 如果存在this.timer,則使用clearTimeout清空。
    // 如果你使用多個timer,那麼用多個變量,或者用個數組來保存引用,然後逐個clear
    this.timer && clearTimeout(this.timer);
  }
}

三、console問題

“快來看,快來看,卡死了卡死了,根本就不能動啊~~”,測試小夥伴跑過來跟我講,並遞過來一個彷彿時間停滯50倍的ios。我特麼就是一臉問號,“不是吧,我提交的時候,還是好好地啊,我就是修改了一下要修改的字段啊,怎麼這麼卡??”
“不慌不慌,我瞅瞅”,實則內心慌得一比!!就在我的模擬器上實操了一下,“哎~~沒問題啊,很流暢。” 這就納了悶兒了。我就比較了一下提交,發現除了改個字段以外,我還打印了一句console.log(“props”,this.props),心裏還想,難道是這個console搞得鬼,我立馬就弄起註釋來了,提交後發現哎喲,還真是console的原因。打發走測試後,我就來找原因,後來發現,這裏的this.props對象內容過多,拖累了js進程,導致的卡頓。所以,我就全局修改了所有的console。
但是問題來了,沒了console,調試起來真的是很麻煩,每次改東西的時候,會去打開,然後提交的時候,都註釋掉,這樣就很“人工”,很不安全。畢竟誰都不好保證每次都記得。
其實這些東西,很多大佬們早就想好了,我們只要去找輪子就好,更何況,寫在了官網上,在運行打好了離線包的應用時,控制檯大量打印語句可能會拖累 JavaScript 線程。注意有些第三方調試庫也可能包含控制檯打印語句,比如redux-logger,所以在發佈應用前請務必仔細檢查,確保全部移除。

有個babel 插件可以幫你移除所有的console.*調用。首先需要使用yarn add --dev babel-plugin-transform-remove-console來安裝,然後在項目根目錄下編輯(或者是新建)一個名爲·.babelrc`的文件,在其中加入:

{
  "env": {
    "production": {
      "plugins": ["transform-remove-console"]
    }
  }
}

這樣在打包發佈時,所有的控制檯語句就會被自動移除,而在調試時它們仍然會被正常調用。

四、app引導頁

在app每次下載的第一次打開,都會有個引導頁,來引導用戶去第一時間瞭解app或者去諮詢用戶所需要的相關硬件權限授權。開始想得比較簡單,就是用一個storage的值來存一個值,判斷是否是第一次打開。然後navigation裏把引導頁設置爲初始頁。然後判斷storage的值再進行跳轉到首頁。但是,這個在首頁沒有禁止滑動的情況下,右滑是可以返回到上一頁(引導頁的,且多爲空白屏)。
於是,我熟練地打開了github,搜了個引導頁的組件,就裝了進來。哈哈~~萬能的github。也不說什麼廢話了,有需要的可以自取:新手引導頁組件

五、webview 插入js

產品中,遇到過這麼個問題,就是運營那邊上傳的一些用戶協議,合同條款這些文件的時候,字體太小。且在後端只是簡單的做一個文件存儲的情況下,這種變大字體的活兒只能落到我們前端肩上了。
RN是打開了一個Webview,source鏈到對應的資源上的。前期我們有個類似的需求,就是文章滑到地步看完後,webview外面的按鈕才能高亮點擊。
Webview裏的這個injectedJavaScript屬性,就是會去寫入的js。但是,我在寫入後發現,injectedJavaScript不生效了。哪怕是一個簡單的console,都沒有執行。我這就很無語。以爲是執行順序的問題。以下是我的injectedJavaScript的值:

`window.οnlοad=function(){
	document.getElementsByTagName('body'[0].style.webkitTextSizeAdjust= '300%';
};true;`

對的,injectedJavaScript這裏的屬性值就是一個字符串,但是,這樣就是沒有生效。然後我又加了個window.onload() 再去觸發下:

`window.οnlοad=function(){
	document.getElementsByTagName('body'[0].style.webkitTextSizeAdjust= '300%';
};
 window.onload();
true;`

發現依然無效,我就擔心是不是url裏的文件有問題,我換了個鏈接,去網站上隨便找了個在線新聞的鏈接,放進去。哎喲,放大了。
這就是一個很好的信號,告訴我,injectedJavaScript這個方法,且我寫的js是可以執行的。那我們接着找原因。難道真的是後端返回鏈接問題。仔細一看才發現,後端返回的協議是以.htm結尾的。不是一個鏈接,而是一個靜態資源,需要我們去下載的,所以應該就是這裏的問題了。
那問題就好說了,我們在點擊彈出Webview框展示內容的時候,先把資源下載下來,然後再對他進行js插入。
ok~~搞定。

後續:後面一些插入關於用戶信息的數據時,也是用這個思路和方法解決的。
只是有一個小地方,需要注意下,那就是injectedJavaScript裏都是字符串,如果傳變量的話,不能簡單的這樣傳入的,這樣他會把傳入的值變爲字符串。

// name 是傳入的變量值
`window.οnlοad=function(){
	document.getElementsByTagName('body'[0].style.webkitTextSizeAdjust= '300%';
	//let a = ${name}  
	let a = '${name}'
};
 window.onload();
true;`

要在外面再包一層,這樣才能解析好name這個變量了。😄

以上,爲我現階段整理的部分,只是想記錄以下自己遇到的RN裏的一些坑點,分享給大家,也希望和大家多交流~~還有許多東西要去了解和學習,以後也會持續更新,道阻且長!

紀念下,ios版本的App終於上線啦!!希望越來越好~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章