wepy一些問題和解決方案

wepy一些問題和解決方案

小程序開發和傳統的web開發有相識的地方,可是也有不一樣的地方,要區分。html

computed屬性名和props屬性名重複

  • 若是那個組件的渲染值是重名的computed屬性,每次點擊都是以前的計算加上最新計算的值
  • 定義computed屬性名的時候避免和props屬性名重複

父子組件傳值和Vue中的區別

  • Vue中的prop傳值默認是隻要父組件的數據改變,子組件同時改變,可是這種模式在wepy中是靜態的 也即 :name="name"是靜態的,父組件改變name子組件仍是不會變,子組件仍是父組件第一次傳進來的值
  • wepy要作到父組件數據變的同時,子組件也跟着變,要加個修飾符.sync,也即:name.sync="name"
  • 還有一個是雙向綁定的問題,Vue中能夠經過$emit事件的方式實現,這裏wepy能夠在子組件中的props配置類型、默認值、以及是否雙向中的twoWaytrue,就實現了雙向數據流
  • 默認twoWay的值是false,若是不是特別須要,請按單向數據的方式傳遞數據最好,再配合$emit、$broadcast、$invoke,儘可能少用,除非是表單這種

如何給當前自定義組件或者頁面類添加靜態屬性

  • 能夠在constructor構造函數中添加靜態屬性,可是要添加super(),纔可使用this來添加靜態屬性
  • 因爲constructor執行時間比較早,全部在這裏面的變量,能夠直接用於wepy組件,也就是能夠和data的數據同樣用於數據綁定,可是原生組件只能放在data
  • 若是有些數據是一次性的,不會改變的(靜態),最好在constructor中定義,不要都放到data中,data中的數據都會被轉換成Observable數據的

組件與組件通訊$broadcast、$emit、$invoke

  • 這些方法不能夠在constructor調用,能夠在onLoad中調用
  • events用於定義事件,用於接收用的
  • 若是想傳數據給子組件,可使用$broadcast('eventName', ...args),可是全部的後代組件都會觸發該事件,若是後代組件的events.eventName有定義到,會調用其函數,並將args傳給其函數
  • 若是想傳數據給父組件可使用$emit,同理,父組件(到根組件)的events要事先定義好事件
  • $broadcast和$emit都會一次觸發多個事件,定義events的時候要注意
  • $invoke('./componentName', 'methodName', args)能夠直接調用指定組件的方法methods中定義的方法,若是是調用父組件能夠用../往上層走,若是要調用下層的./oneLevelComponentName/twoLevelComponentName
  • 若是有不少組件都公用一個方法methods或者events,還可使用mixins

區分Page、App、Component、Mixin這些實例

  • 有些生命週期鉤子是那個實例特有的,有些生命週期是全部都共享的

components不一樣於Vue或React的組件

  • 小程序的組件和Vue和React組件是有區別的
  • 在wepy中引入組件在components中,和Vue的同樣,可是使用的時候是不一樣的,一個組件對應一個id,若是在同一個模板中使用同一組件超過2次,它們會共享數據
  • 共享數據指的是props等,能夠測試一下,同一個組件傳入的props名同樣,值不同,最終全部組件那的那個props值是最後一個值
  • 由於它們共享同一個props,多個組件一塊兒使用,相似定義多個同名的函數同樣,最後使用的是最後一個函數
  • 爲了不這種狀況下能夠用同一個組件去定義多個組件名{ coma: Button, comb: Button },實際上就是new多一個Button
  • 也就是說小程序中的組件在使用的時候,不會自動地new一個新的組件,而是同一個組件,而像Vue和React這樣的組件,它們會new一個新的Button實例
  • 還有一種狀況是,在循環體<repeat>中,在小程序中就會去new一個新的組件實例,若是你的內容重複,又不想定義多個組件名(new 多個組件),可使用循環體<repeat>
  • 還有一種狀況是slot,若是那個組件和數據無關,只是單純的用於slot模板,它們最終生成的標籤是不一樣的,由於這些生成的模板和數據無關,若是生成的模板中包含數據,那生成那部分關聯數據的元素都是同樣的
  • 這裏說的數據是<view class='{{ className }}' >{{ data }}</view>這些花括號中的數據classNamedata,它們是共享的,因此它們最終生成的視圖是如出一轍的
  • 小程序的組件和目前流行的web組件有很大的區別,不能老用web組件傳值得思惟思考(不少莫名的bug),多從廣播(訂閱)的角度思考

repeat注意點

  • 分兩種狀況
//repeat包着元素view text等
<repeat for="{{mylist}}">
  <view>{{item.name}}</view>
</repeat>

//repeat包着自定義組件
<repeat for='{{myList}}'>
  <List :mylist.sync="mylist"></List>
  <Item :item='item'></Item>
</repeat>
  • 不支持在repeat的組件中使用propscomputedwatch等特性
  • 在使用repeat的時候,儘可能使用純文本渲染的組件,純組件
  • 原生組件的狀況下,可使用.或者[]的方式選擇想傳的數據,可是自定義組件不能夠,要整個數據傳入,或者傳入item([{}, {}]這種格式的數據),item就是wx:item
  • 數據源要在data中,纔有效果,靜態屬性不行
  • 儘可能只包含一個組件,出現多個組件,會出現莫名的bug,其它的功能再在這一個組件內部處理,而後組件間的通訊經過$broadcast、$emit、$invoke
  • 使用組件多使用$broadcast、$emit、$invoke的方式傳值,別老想着使用props,會有不少莫名的bug
  • 關於$broadcast、$emit、$invoke,能夠經過mixins拯救一下,惟一沒什麼莫名bug的

Object.create(null)

  • 上面返回的對象不帶原型鏈,也即不包含Object原生對象的信息
  • 小程序中一些數據,像data須要的對象要帶原型鏈,不能用這個,不然在綁定數據到模板的時候會報錯

字符串雙引號""和單引號''

  • 在模板中務必使用"",別用''(想殺人)
  • :age='2':age="2",前面的''是傳不了2age的,除非使用"2",哈哈哈哈哈哈哈哈
  • 在模板中最外層字符串最好用""不要使用'',好比定義事件函數的時候'handlerTap("123")',這裏是不成功的給handlerTap傳遞參數"123",可是"handlerTap('123')"就能夠???
  • 正確用法:@tap="handlerTap('love')",最外層用"",最內層''

mixins的computed順序問題

  • mixins中的computed執行順序和vue的相反,也即先執行component或者頁面的定義的,而後再執行mixins中的
  • 還有就是延遲的問題,mixins的慢於組件或者當前頁面定義的,若是想在當前頁面獲取mixins的一些值,會獲取不到

組件傳值和模板綁定問題

  • 一個是上面提到的字符串要用雙引號
  • 而後就是要區分原生組件和自定義組件

原生組件:就是小程序自帶的組件<view>、<text>、<image>等等,這些原生組件綁定數據,要求數據必須在data中,若是綁定的數據不在data中將不會渲染vue

<template>
  <view class="{{className}}">{{text}}</view>
</template>

<script>
import wepy from 'wepy'

// 注意:這個是組件實例
export default class Test extends wepy.component {
  data = {
    text: 123,
    className: 'hahah'
  }
  
  // 因爲computed最後返回值會成爲data中一部分,computed也能夠用於原生組件數據綁定
  // 可是在repeat的時候,不可使用這個,repeat的時候不可使用computed和watch
  computed = {
    text () {
      return this.text + 1
    }
  }
}
</script>

自定義組件:綁定數據能夠是data中,也能夠用自定義函數,或者靜態變量來綁定數據,且綁定數據的方式要和原生小程序的同樣,不能用vue的方式react

<template>
  <UserComponent :fn="fn()" :staticV="staticVar" :text="text"/>
</template>

<script>
import wepy from 'wepy'

// 注意:這個是頁面實例
export default class Index extends wepy.page {
  constructor () {
    super()
    this.staticVar = 123
  }

  data = {
    text: 123
  }
  
  // 自定義函數
  fn () {
    return '123'
  }
  
  // 因爲computed最後返回值會成爲data中一部分,computed也能夠用於原生組件數據綁定,若是和data中的屬性重名,優先使用computed的
  computed = {
    text () {
      return this.text + 1
    }
  }
}
</script>

原生組件的綁定只能是data中的數據,不能夠像vue中的那樣綁定數據,可是若是是自定義的組件就能夠像vue那樣綁定數據。還有methods自能用於定義事件處理程序,不能把自定義函數定義在裏面web

也就是碰到原生組件的時候,請用原生小程序的方式處理,碰到自定義組件的時候才考慮用你vue的方式處理,也就是區分原生組件和自定義組件很是重要canvas

圖片和導航的路徑問題

  • 不要在組件中使用相對定位,如../這種,由於當組件被引入到某個頁面時,會相對哪一個頁面,致使路徑沒法複用
  • 使用絕對定位,/,在小程序中,/是指的當前項目的文件夾,例如:/pages/index,這裏的首個字符/就至關於@/都是指向/src目錄
  • 若是是圖片,如@/assets/icons/logo.png能夠用/assets/icons/logo.png,由於第一個字符是/就至關於@/,表示/src目錄之下
  • 若是是導航wx.navigateTo,若是導航到/pages/user,不要使用/或者../,直接user,最終會自動拼成/pages/user,也就是說微信默認/pages/+user

canvas中的canvas-id不能動態賦值

  • 能夠經過slot來實現一個組件,不一樣canvas-id
<component-name sid="canvas">
    <canvas canvas-id="canvas"></canvas>
  </component-name>
  • component-name是一個組件,接收sid只要是爲了能夠wx.createCanvasContext(this.sid)
  • 其實咱們在組件的內部只須要知道canvas的id,而且調用wx.createCanvasContext(this.sid),因此咱們能夠把canvas獨立成slot

在一個組件中引入另外一個組件做爲子組件,子組件的樣式<style>不起做用

  • 是由於父組件沒有<style>標籤,致使子組件不編譯<style>標籤的內容
  • 最好仍是每一個組件都添加<style>標籤,即便裏面沒有內容
相關文章
相關標籤/搜索