99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

Debug 指南

2020-05-12 17:47 更新

Debug 指南

和所有框架一樣,Taro 也可能存在 bug。當(dāng)你認(rèn)為你的代碼沒有問題,問題出在 Taro 時(shí),可以按照本章內(nèi)容進(jìn)行調(diào)試。

當(dāng)你在 Taro 進(jìn)行 debug 時(shí),請先確認(rèn)一下流程均已完成:

  1. ESLint 已經(jīng)開啟并且沒有報(bào)錯(cuò);
  2. 大致過了一遍包括最佳實(shí)踐在內(nèi)的文檔,文檔里沒有對應(yīng)問題的描述;
  3. 搜索過相關(guān)的 issue,issue 沒有提到相關(guān)解決方案;
  4. 按項(xiàng)目使用的 Taro 版本往上查看 changelog,changelog 中沒有意見修復(fù)相關(guān)問題的提交;

很多時(shí)候只要你把以上四個(gè)流程都走一遍,遇到的問題就會迎刃而解。而作為一個(gè)多端框架,Taro 有非常多的模塊,當(dāng)出現(xiàn)問題時(shí) Taro 也需要分模塊進(jìn)行調(diào)試,接下來我們會舉一些已經(jīng)解決了的 bug 樣例,闡述我們調(diào)試 bug 的思路:

安裝

使用 yarn 安裝完 CLI 報(bào)錯(cuò)

由于 commander.js 的緣故,在 Mac 下使用 yarn 安裝 CLI,偶爾會出現(xiàn)執(zhí)行命令報(bào)錯(cuò)的情況

taro-init(1) does not exist, try --help

這時(shí)候,你可以選擇使用 npm 或者 cnpm 重新安裝 CLI,或者將 CLI 添加到環(huán)境變量中來解決。

項(xiàng)目依賴一直安裝不下來

由于 Taro 的 @tarojs/webpack-runner 包默認(rèn)依賴了 node-sass,倒是有些時(shí)候依賴一直安裝不了,在此,建議直接使用淘寶的 cnpm 進(jìn)行安裝依賴,或者嘗試一下這個(gè)包

小程序

沒有任何報(bào)錯(cuò),但顯示的結(jié)果不如預(yù)期

被 diff 邏輯過濾

此問題發(fā)生在頁面或組件更新時(shí)。

在調(diào)用小程序的 setData 方法前,Taro 會把 state 與 data 做一次 diff。

如果 state 與 data 的某個(gè)屬性值沒有變化,很有可能就不會重新 setData 該屬性,導(dǎo)致頁面或組件沒有正確更新。

這種問題多出現(xiàn)在小程序的表單組件中,例如以下兩個(gè) issue:#1981、#2257。因?yàn)樾〕绦蛞恍┍韱谓M件為非受控組件,表單更新時(shí),對應(yīng) value 值的 data 并不會更新,導(dǎo)致 data 值還是初始值。如果再 setState 此屬性為初始值,由于 diff 邏輯判斷屬性值沒有變化,不會 setData 此屬性,導(dǎo)致視圖沒有更新。正確做法是在表單組件的 update 事件中 setData value 為當(dāng)前值,保證 data 與表單顯示值保持一致。

debug diff

開發(fā)者可以在開發(fā)者工具中找到 taro 運(yùn)行時(shí)庫,在 diff 方法前后打斷點(diǎn)或 log,觀察 state、小程序 data 和 diff 后將要被 setData 的數(shù)據(jù),這種排查有助定位很多視圖更新問題。

qq20190305-151951

微信小程序,增加數(shù)組元素?zé)o法正確更新數(shù)組 length

增加數(shù)組元素時(shí),經(jīng) diff 后會按路徑更新。但由于微信小程序自身 bug,按路徑更新數(shù)組時(shí),數(shù)組 length 不會正確更新。詳見 #882

此問題只出現(xiàn)于微信小程序,微信官方說法是暫不修復(fù)。

推薦做法是新開一個(gè) state 值來同步 length 變化。

編譯模板出錯(cuò)

這時(shí)候很可能是編譯模板出現(xiàn)了錯(cuò)誤。例如中 #2285 中,題主寫了兩個(gè)嵌套循環(huán),在第二個(gè)循環(huán)中無法正確地訪問到第一個(gè)循環(huán)聲明的 index 變量:

// 假設(shè)源碼在 src/pages/index/index.js 中
rooms.map((room, index) => (
  <View key={room.id}>
    <View>房間</View>
    <View className="men">
      {room.checkInMen.map(man => (
        <View onClick={this.handleRemoveMan.bind(this, man.id, index)}>
          {man.name}
        </View>
      ))}
    </View>
  </View>
);

而編譯出來的 wxml 將會是:

<!-- 編譯后代碼代碼至少會生成三個(gè)文件,分別是: -->
<!-- dist/pages/index/index.js,dist/pages/index/index.wxml,dist/pages/index/index.json -->
<view wx:for="{{loopArray0}}" wx:for-item="room" wx:for-index="index">
  <view>房間</view>
    <view class="men">
      <view  data-e-tap-a-b="{{index}}" bindtap="handleRemoveMan" wx:for="{{room.$anonymousCallee__0}}" wx:for-item="man" data-e-tap-so="this" data-e-tap-a-a="{{man.$original.id}}">{{man.$original.name}}
      </view>
    </view>
  </view>
</view>

觀察編譯前后文件,我們可以發(fā)現(xiàn):由于第二個(gè)循環(huán)沒有指定 index 變量名,Taro 編譯的循環(huán)也沒有指定 index 變量名。但問題在于微信小程序當(dāng)不指定 index 時(shí),會隱式地注入一個(gè)名為 index 的變量名作為 index。因此這段代碼在第二個(gè)循環(huán)中訪問 index,實(shí)際上是當(dāng)前循環(huán)的 index,而不是上級循環(huán)的 index。

當(dāng)我們了解到問題所在之后,解決問題也很容易,只要在第二個(gè)循環(huán)顯式地暴露循環(huán)的第二個(gè)變量即可,源代碼可以修改為:

rooms.map((room, index) => (
  <View key={room.id}>
    <View>房間</View>
    <View className="men">
      {room.checkInMen.map((man, _) => (
        <View onClick={this.handleRemoveMan.bind(this, man.id, index)}>
          {man.name}
        </View>
      ))}
    </View>
  </View>
);

運(yùn)行時(shí)在小程序開發(fā)者工具報(bào)錯(cuò)

有時(shí)候我們會在運(yùn)行時(shí)遇到這樣錯(cuò)誤:

debug.png

調(diào)試這樣的問題也很簡單,只需要點(diǎn)擊調(diào)用棧從調(diào)用棧最上層的鏈接,點(diǎn)進(jìn)去我們可以發(fā)現(xiàn)是這樣的代碼:

debug2.png

這時(shí)我們可以發(fā)現(xiàn)這個(gè)錯(cuò)誤的原因在于變量 url 在調(diào)用 Object.assign() 函數(shù)時(shí)找不到變量,我們可以再看一下源碼:

// 如果運(yùn)行時(shí)報(bào)錯(cuò)文件路徑是:dist/pages/test/test.js
// 那么就可以推算出源碼在:src/pages/test/test.js
// 編譯后的 js 文件已經(jīng)經(jīng)過 Babel 編譯過,但函數(shù)基本上還是能一一對應(yīng)的
// 除了 `render()` 函數(shù)會對應(yīng)到 `_createData()` 函數(shù),形如 `renderTest` 函數(shù)會對應(yīng)到 `createTestData` 函數(shù)
render () {
  let dom = null
  if (this.props.visable) {
      const url = 'https://...'
      dom = <Image src={url} />
  }
  
  return <Container>
    {dom}
  </Container>
}

通過觀察編譯前后代碼,我們可以發(fā)現(xiàn)源碼沒有任何問題,但 Taro 在此問題出現(xiàn)的版本沒有處理好 if 表達(dá)式作用域內(nèi)的變量,調(diào)用 Object.assign() 函數(shù)時(shí) url 變量并不存在于 render 函數(shù)的作用域中。為了解決這個(gè)問題,我們可以修改源碼,手動(dòng)把 url 變量也放在 render 函數(shù)作用域中:

render () {
  let dom = null
  let url = ''
  if (this.props.visable) {
      url = 'https://...'
      dom = <Image src={url} />
  }
  
  return <Container>
    {dom}
  </Container>
}

大部分運(yùn)行時(shí)錯(cuò)誤都可以通過小程序內(nèi)置的 Chrome DevTools 找到報(bào)錯(cuò)的緣由,如果當(dāng)前調(diào)用棧沒有找到問題所在,可以往上逐層地去調(diào)試各個(gè)調(diào)用棧。Chrome DevTools 相關(guān)文檔請查看:Chrome 開發(fā)者工具

生命周期/路由/setState 出錯(cuò)

在 #1814 中提到了 this.$router.path (當(dāng)前頁面路由的路徑) 有時(shí)無法訪問。經(jīng)過調(diào)研發(fā)現(xiàn)原因在于 Taro 把獲取路徑的函數(shù)放在了小程序的 onLoad 函數(shù)上,而不是每個(gè)組件都能調(diào)用到這個(gè)函數(shù)。而解決這個(gè)問題的方法也很簡單,如果當(dāng)前頁面是組件可以直接通過 this.$scope.route 訪問,更普適的方法則是通過 getCurrentPages 函數(shù)訪問到當(dāng)前頁面的示例,然后訪問實(shí)例的 route 或 __route__ 訪問到當(dāng)前頁面路由的路徑。

通過這個(gè)例子,我們不難發(fā)現(xiàn) Taro 的生命周期/路由 和 setState 在小程序端其實(shí)是包裝成 React API 的一層語法糖,我們把這層包裝稱之為 Taro 運(yùn)行時(shí)框架。幾乎所有 Taro 提供的 API 和語法糖最終都是通過小程序本身提供的 API 實(shí)現(xiàn)的,也就是說當(dāng) Taro 運(yùn)行時(shí)框架出現(xiàn)問題時(shí),你基本都能使用小程序本身提供的 API 達(dá)到同等的需求,其中就包括但不限于:

  1. 使用 this.$scope.triggerEvent 調(diào)用通過 props 傳遞的函數(shù);
  2. 通過 this.$scope.selectComponent 和 wx.createSelectorQuery 實(shí)現(xiàn) ref;
  3. 通過 getCurrentPages 等相關(guān)方法訪問路由;
  4. 修改編譯后文件 createComponent 函數(shù)創(chuàng)建的對象

雖然使用小程序原生方法也能做很多同樣的事,但當(dāng) Taro 運(yùn)行時(shí)框架出現(xiàn)問題時(shí),我們還是強(qiáng)烈建議開發(fā)者向 Taro 官方 提交 issue,有能力的開發(fā)者朋友也可以 提交 PR。一方面使用 Taro API 實(shí)現(xiàn)可以幫助你抹平多端差異,另一方面尋找甚至是修復(fù) bug 也有助于加強(qiáng)你對 Taro 和小程序底層的理解。

微信小程序表單組件問題

微信小程序表單組件不是受控組件,當(dāng)用戶操作表單時(shí)視圖會立即改變,但表單的 value 值還是沒有變化。

如果在表單 onChange、onInput 此類值改變回調(diào)中 setState value 為用戶操作改變表單之前的值時(shí),Taro 的 diff 邏輯會判斷 setState 的 value 值和當(dāng)前 data.value 一致,則放棄 setData,導(dǎo)致視圖沒有正確更新。

解決辦法:

Input 組件可以通過在回調(diào)中 return 需要改變的值來更新視圖。詳見 #2642

小程序 Input 組件文檔截圖:

inputdoc

其它組件需要立即 setState({ value: e.detail.value }) 以立即更新同步 data.value 值,然后再 setState 真正需要表單改變的值。詳見 #1981#2257

API 問題

API 調(diào)用結(jié)果不符合預(yù)期

Taro 小程序端的 API 只是對小程序原生 API 簡單地進(jìn)行了 promise 化,并沒有做什么額外操作。因此開發(fā)者在遇到這種情況時(shí)可以試試直接使用小程序 API,如微信小程序中直接使用 wx.xxx。如果有同樣的報(bào)錯(cuò),證明是小程序方面的問題。否則則可能是 Taro 的問題,可以給我們提相關(guān) issue。

API 調(diào)用報(bào)錯(cuò)

假設(shè)開發(fā)者在調(diào)用某個(gè) API Taro.xxx,出現(xiàn)類似以下報(bào)錯(cuò):

image

證明 Taro 還沒兼容此 API,比如一些小程序平臺最新更新的 API。這時(shí)可以給我們提 issue 要求添加,或者修改此文件 native-apis.js 后,給我們提 PR。

H5

運(yùn)行時(shí)報(bào) DOM 相關(guān)錯(cuò)誤

在 #1804 中提到,只要使用了 Block 組件并且有一個(gè)變量控制它的顯式時(shí),就必定會報(bào)錯(cuò):

export default class Index extends Component {
  config = {
    navigationBarTitleText: '首頁'
  };

  state = {
    num: 1
  };

  componentDidMount() {
    console.log('did');
    setTimeout(() => {
      this.setState({
        num: 0
      });
    }, 2000);
  }

  render() {
    const { num } = this.state;
    return (
      <View className="container">
        {num === 0 && <View>已賣完</View>}
        {num > 0 && (
          <Block>
            <View>正在銷售</View>
            <View>立即購買</View>
          </Block>
        )}
        {/* {num > 0 && <View>正在銷售</View>} */}
      </View>
    );
  }
}

這個(gè)時(shí)候我們可以把問題定位到 Block 組件中,我們可以查看 @tarojs/components 的 Block 組件源碼:

const Block = (props) =>  props.children
export default Block

也就是說當(dāng)變量 num > 0 時(shí),Block 組件的 children 會顯示,而當(dāng) Block 組件的 children 是一個(gè)數(shù)組時(shí),View.container 的 children 就變成 [一個(gè) View 組件, [一個(gè)數(shù)組]],渲染這樣的數(shù)據(jù)結(jié)構(gòu)需要 React.Fragment 的包裹才能渲染。而 Taro 目前還沒有支持 React.Fragment 語法,所以這樣的寫法就報(bào)錯(cuò)了。解決這個(gè)問題也很簡單,只需要修改 Block 組件,用一個(gè)元素包裹住 children 即可:

const Block = (props) => <div>{props.children}</div>

當(dāng)你遇到了相關(guān)問題時(shí),我們準(zhǔn)備了一個(gè)快速起步的沙盒工具,你可以直接在這個(gè)工具里編輯、調(diào)試、復(fù)現(xiàn)問題:

Edit Taro sandbox

組件

jsEnginScriptError

Component is not found in path "xxx/xxx/xxx" 解決辦法:

1、檢查有沒有編譯報(bào)錯(cuò)

2、檢查編譯后的文件是否正確

3、步驟 1 和 步驟 2 如果檢查沒有問題,重啟開發(fā)者工具,否則跳到步驟 4

4、提供具體編譯報(bào)錯(cuò)信息與編譯后文件信息的截圖


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號