mpvue開發小程序教程(五)

  • 2019 年 10 月 7 日
  • 筆記

作者:一斤代碼,原文地址:https://dwz.cn/u3dqw5wd

在上一章節中,我們了解了組件的三個基本特性以及組件的基本使用方法。在實際的小程序開發中,我們應該以組件的思維去設計每個小程序的功能頁面,對其進行合理的組件拆分,讓每個部分都保持功能簡潔、條理清楚、各司其職,這樣會讓代碼變得更易理解和維護,間接的也提升了代碼的健壯性,降低出現Bug的幾率,即使出現Bug,也會更容易進行定位和調試。

由於mpvue採用的是Vue框架的基礎設施,所以大部分的功能都是和Vue一致的。但是,mpvue的代碼畢竟最終還是要轉譯成小程序原生框架下的代碼的,由於小程序框架本身存在的一些功能限制,導致有些功能不能被翻譯過去,也就是說有些標準的Vue功能在mpvue下是不可以使用或有特殊限制的。

今天我們就來羅列一下,在使用mpvue的時候那些需要特別注意的點。

1. 在模板中,動態插入HTML的 v-html指令不可用

這條很好理解,小程序的界面並不是基於瀏覽器的BOM/DOM的,所以不能動態的在界面模板里直接插入HTML片段來顯示。

題外話,如果有在小程序里插入html片段的需求怎麼辦?可以用 <rich-text>組件或者 wxParse(https://github.com/icindy/wxParse)來實現。

2. 在模板中,用於數據綁定的雙括號語法 {{}}中的表達式功能存在諸多限制

在Vue本身的模板內雙括號語法中,我們可以對綁定變量進行比較豐富的處理,比如:

  • 可以調用 methods下的函數, 例如:
<template>    <div>{{ formatMessage(msg) }}</div>  </template>    <script>  export default {    data() {      return {        msg: "Hello,World"      }    },    methods: {      formatMessage(str) {        return str.trim().split(',').join('#')      }    }  }  </script>
  • 如果變量是對象的話,也可以調用對象的成員方法
<div>{{ msg.trim().split(',').join('#') }}</div>
  • 可以使用過濾器來處理變量,最有用的場景算是格式化數據了
<div>{{ msg | format }}</div>

以上這些好用的功能,在mpvue中,記得都是通通不能用的哦!!!

我們只能在雙括號中使用一些簡單的運算符運算( +-*%?:!=====><[].)。

但是也得找些可用的替代方案吶,大夥先考慮使用計算屬性(computed)來做吧。

3. 在模板中,除事件監聽外,其餘地方都不能調用 methods下的函數

在Vue中,模板里調用 methods部分定義的函數是非常常見的,比如下面這段代碼所示,在 v-if指令中調用函數 getErrorNum()

<div v-if="getErrorNum() > 0  && code == 10001" class="error">{{ errorMsg }}</div>

可是,在mpvue里就是不可以用!因為在小程序原生模板 wxml里就不支持這種函數調用,導致mpvue沒有很好的方式轉譯過去(雖然小程序有 wxs,但是感覺翻譯過去mpvue要做的工作會比較複雜)。

所以,可用的替代方案可能還是計算屬性了。

4. 在模板中,不支持直接綁定一個對象到 styleclass屬性上

在Vue中我們可以為HTML元素的 classstyle綁定一個對象,並按照對象內的屬性值來決定是否添加對應的屬性名到HTML元素的樣式名。示例如下:

<template>    <div :class="classObject"></div>  </template>    <script>  export default {    data() {      return {        classObject: {          active: true,          'text-danger': false        }      }    }  }  </script>

上面這段代碼的運行後生成的HTML將是:

<div class="active"></div>

但是在mpvue下面這個特性也不能用,按官方說法是由於涉及到一些性能相關的原因。那如果要動態改變組件的 class該怎麼寫呢?官方給出的方式是這樣的:

<div :class="{ active: classObject.active, 'text-danger': classObject['text-danger']}"></div>

其實改動不大,稍微多打了一些字而已,相當於在模板的 class里再定義一個對象罷了。但是據文檔中說這樣會提升性能。好吧,為了性能,這點麻煩還是能忍受的。但是它又說了:從性能考慮,建議不要過度依賴此……看來即使這樣,也還是有性能問題。

看來最好一點的方案,還是得使用計算屬性,直接生成一串樣式的字符串,綁定到 classstyle上:

<template>    <div :class="classStr"></div>  </template>    <script>  export default {    data() {      return {        classObject: {          active: true,          'text-danger': false        }      }    },    computed: {      classStr() {        let arr = []        for (let p in this.classObject) {          if (this.classObject[p]) {            arr.push(p)          }        }        return arr.join(' ')      }    }  }  </script>

5. 在模板中,嵌套使用 v-for時,必須指定索引 index

通常,我們在Vue模板中嵌套循環渲染數組的時候,一般是這個樣子的:

<template>    <ul v-for="category in categories">      <li v-for="product in category.products">{{product.name}}</li>    </ul>  </template>

但在mpvue中使用這種嵌套結構的 v-for時,則必須每層的 v-for上都給出索引,且索引需取不同名字:

<template>    <ul v-for="(category, index) in categories">      <li v-for="(product, productIndex) in category.products">{{product.name}}</li>    </ul>  </template>

6. 事件處理中的注意點

在mpvue中,一般可以使用Web的DOM事件名來綁定事件,mpvue會將Web事件名映射成對應的小程序事件名,對應列表如下:

// 左側為WEB事件 : 右側為對應的小程序事件  {      click: 'tap',      touchstart: 'touchstart',      touchmove: 'touchmove',      touchcancel: 'touchcancel',      touchend: 'touchend',      tap: 'tap',      longtap: 'longtap',      input: 'input',      change: 'change',      submit: 'submit',      blur: 'blur',      focus: 'focus',      reset: 'reset',      confirm: 'confirm',      columnchange: 'columnchange',      linechange: 'linechange',      error: 'error',      scrolltoupper: 'scrolltoupper',      scrolltolower: 'scrolltolower',      scroll: 'scroll'  }

除了上面的之外,Web表單組件 <input><textarea>的change事件會被轉為blur事件。

然後,像 keydownkeypress之類的鍵盤事件也沒有了,因為小程序沒有鍵盤,所以不需要這些事件。

還有,Vue裏面綁定事件的時候,可以指定事件修飾符,但是在mpvue里,官方給出了一些注意信息:

  • .stop 的使用會阻止冒泡,但是同時綁定了一個非冒泡事件,會導致該元素上的 catchEventName 失效!【這個親測了一下,感覺是最新版本里修復了還是怎麼的,沒有文檔里說的這個問題了】
  • .prevent 可以直接幹掉,因為小程序里沒有什麼默認事件,比如submit並不會跳轉頁面【也就是不需要支持】
  • .capture 支持 1.0.9 【也就是在 mpvue 1.0.9及以後版本支持】
  • .self 沒有可以判斷的標識 【也就是不支持】
  • .once 也不能做,因為小程序沒有 removeEventListener, 雖然可以直接在 handleProxy 中處理,但非常的不優雅,違背了原意,暫不考慮【也就是不支持】

所以呢,總之當你在遇到事件相關的問題,請回來查看一下文檔,看看自己是否已經掉在坑裡了。

7. 對於表單,請直接使用小程序原生的表單組件

一句話,表單組件又多又複雜,框架可能Hold不住。所以在實際開發中,推薦直接使用小程序的表單組件標籤來寫,而不是使用Web的表單組件標籤來寫。當然了,在mpvue中使用了小程序的組件標籤,數據綁定功能還是完全可以用的。給個示例:

<template>    <div>      <picker @change="handlePickerChange" :value="selectedIndex" :range="messages">        <view class="picker">當前消息:{{ messages[selectedIndex] }}</view>      </picker>    </div>  </template>    <script>  export default {    data () {      return {        selectedIndex: 0,        messages: ['Hello', 'World', 'Haha']      }    },    methods: {      handlePickerChange (e) {        console.log(e)      }    }  }  </script>

其他注意事項

另外,在Vue開發Web應用的時候,通常使用 vue-router來進行頁面路由。但是在mpvue小程序開發中,不能用這種方式,請使用 <a>標籤和小程序原生API wx.navigateTo等來做路由功能。

還有就是請求後端數據,我們通常在Web開發中使用 axios等ajax庫來實現,但是在小程序開發中也是不能用的,也請使用小程序的原生API wx.request等來進行。