微信小程序開發技巧

開發小程序這麼久了,整理了一些技巧清單,分享出來。css

一、backgroundColor 配置無效

頁面配置中 backgroundColor 能夠設置窗口顏色:html

{
  "backgroundColor": "#f2f2f2"
}
複製代碼

這麼設置完以後發現一點效果都沒有,仔細研究一番,原來窗口顏色指的是最底層。(真想說句:臥槽~)vue

解決這個問題很簡單,使用 page 選擇器便可:react

page {
  background: #f2f2f2;
}
複製代碼

page 是頁面的根節點,也就是h5裏的 html,因此能夠用來設置一些樣式。web

二、改變自定義組件根節點樣式

header組件代碼以下:npm

<view class="header">
  header
</view>
複製代碼

能夠看到渲染出來後發現多出 header 節點。編程

在大部分開發中跟組件節點並無什麼用, 可是 某些狀況下是會影響樣式的, 好比說彈性佈局,這裏不貼demo了,反之此技巧一定用到,回頭瞧瞧就行。json

咱們能夠在自定義組件樣式文件使用 :host 選擇器修改跟組件節點:小程序

:host {
  padding: 50px;
}
複製代碼

能夠對比上圖盒子模型微信小程序

三、block標籤是什麼

block 標籤其實就相似於 react 中的 Fragment, Vue中的 template

若是沒接觸過 react/vue 不要緊,看下面例子:

<block>
  <view>say</view>
  <view>hello</view>
</block>
複製代碼

渲染後結果, block 節點消失

<view>say</view>
<view>hello</view>
複製代碼

若是沒有block節點,須要這麼作:

<!-- 多渲染了跟節點標籤 -->
<view>
  <view>say</view>
  <view>hello</view>
</view>
複製代碼

比較經常使用的用來配合 wx:if

<block wx:if="{{ show }}">
  <view wx:for="{{ arr }}" wx:key="index">{{ item }}</view>
</block>
複製代碼

四、如何設置背景圖片

搞個背景圖片都費勁 [發火]

日常在h5中設置背景圖片直接引入地址就行

background: url("/example.png");
複製代碼

可是在小程序中居然不能夠。。。

爲啥???

小程序: 你只能乖乖引入網絡圖片
xx: mmp, 設置個圖片都搞那麼多花樣? 我以爲...
小程序:我不要你以爲, 我要我以爲。
複製代碼

xx了。 只能走後門了。

一、能夠將圖片轉成 base64 便可:

background-image: url("data:image/svg+xml;base64,PHN2ZyBjbGFzcz0ibGRzLXNwaW5uZXIiIHdpZHRoPSIxMDlweCIgIGhlaWdodD0iMTA5cHgiICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQiIHN0eWxlPSJiYWNrZ3JvdW5kOiBub25lOyI+PGcgdHJhbnNmb3JtPSJyb3RhdGUoMCA1MCA1MCkiPgogIDxyZWN0IHg9IjQ3IiB5PSIyNCIgcng9IjkuNCIgcnk9IjQuOCIgd2lkdGg9IjYiIGhlaWdodD0iMTIiIGZpbGw9IiMwMDAiPgogICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0ib3BhY2l0eSIgdmFsdWVzPSIxOzAiIHRpbWVzPSIwOzEiIGR1cj0iMXMiIGJlZ2luPSItMC45MTY2NjY2NjY2NjY2NjY2cyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiPjwvYW5pbWF0ZT4KICA8L3JlY3Q+CjwvZz48ZyB0cmFuc2Zvcm09InJvdGF0ZSgzMCA1MCA1MCkiPgogIDxyZWN0IHg9IjQ3IiB5PSIyNCIgcng9IjkuNCIgcnk9IjQuOCIgd2lkdGg9IjYiIGhlaWdodD0iMTIiIGZpbGw9IiMwMDAiPgogICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0ib3BhY2l0eSIgdmFsdWVzPSIxOzAiIHRpbWVzPSIwOzEiIGR1cj0iMXMiIGJlZ2luPSItMC44MzMzMzMzMzMzMzMzMzM0cyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiPjwvYW5pbWF0ZT4KICA8L3JlY3Q+CjwvZz48ZyB0cmFuc2Zvcm09InJvdGF0ZSg2MCA1MCA1MCkiPgogIDxyZWN0IHg9IjQ3IiB5PSIyNCIgcng9IjkuNCIgcnk9IjQuOCIgd2lkdGg9IjYiIGhlaWdodD0iMTIiIGZpbGw9IiMwMDAiPgogICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0ib3BhY2l0eSIgdmFsdWVzPSIxOzAiIHRpbWVzPSIwOzEiIGR1cj0iMXMiIGJlZ2luPSItMC43NXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIj48L2FuaW1hdGU+CiAgPC9yZWN0Pgo8L2c+PGcgdHJhbnNmb3JtPSJyb3RhdGUoOTAgNTAgNTApIj4KICA8cmVjdCB4PSI0NyIgeT0iMjQiIHJ4PSI5LjQiIHJ5PSI0LjgiIHdpZHRoPSI2IiBoZWlnaHQ9IjEyIiBmaWxsPSIjMDAwIj4KICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIHZhbHVlcz0iMTswIiB0aW1lcz0iMDsxIiBkdXI9IjFzIiBiZWdpbj0iLTAuNjY2NjY2NjY2NjY2NjY2NnMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIj48L2FuaW1hdGU+CiAgPC9yZWN0Pgo8L2c+PGcgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDUwIDUwKSI+CiAgPHJlY3QgeD0iNDciIHk9IjI0IiByeD0iOS40IiByeT0iNC44IiB3aWR0aD0iNiIgaGVpZ2h0PSIxMiIgZmlsbD0iIzAwMCI+CiAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJvcGFjaXR5IiB2YWx1ZXM9IjE7MCIgdGltZXM9IjA7MSIgZHVyPSIxcyIgYmVnaW49Ii0wLjU4MzMzMzMzMzMzMzMzMzRzIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSI+PC9hbmltYXRlPgogIDwvcmVjdD4KPC9nPjxnIHRyYW5zZm9ybT0icm90YXRlKDE1MCA1MCA1MCkiPgogIDxyZWN0IHg9IjQ3IiB5PSIyNCIgcng9IjkuNCIgcnk9IjQuOCIgd2lkdGg9IjYiIGhlaWdodD0iMTIiIGZpbGw9IiMwMDAiPgogICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0ib3BhY2l0eSIgdmFsdWVzPSIxOzAiIHRpbWVzPSIwOzEiIGR1cj0iMXMiIGJlZ2luPSItMC41cyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiPjwvYW5pbWF0ZT4KICA8L3JlY3Q+CjwvZz48ZyB0cmFuc2Zvcm09InJvdGF0ZSgxODAgNTAgNTApIj4KICA8cmVjdCB4PSI0NyIgeT0iMjQiIHJ4PSI5LjQiIHJ5PSI0LjgiIHdpZHRoPSI2IiBoZWlnaHQ9IjEyIiBmaWxsPSIjMDAwIj4KICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIHZhbHVlcz0iMTswIiB0aW1lcz0iMDsxIiBkdXI9IjFzIiBiZWdpbj0iLTAuNDE2NjY2NjY2NjY2NjY2N3MiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIj48L2FuaW1hdGU+CiAgPC9yZWN0Pgo8L2c+PGcgdHJhbnNmb3JtPSJyb3RhdGUoMjEwIDUwIDUwKSI+CiAgPHJlY3QgeD0iNDciIHk9IjI0IiByeD0iOS40IiByeT0iNC44IiB3aWR0aD0iNiIgaGVpZ2h0PSIxMiIgZmlsbD0iIzAwMCI+CiAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJvcGFjaXR5IiB2YWx1ZXM9IjE7MCIgdGltZXM9IjA7MSIgZHVyPSIxcyIgYmVnaW49Ii0wLjMzMzMzMzMzMzMzMzMzMzNzIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSI+PC9hbmltYXRlPgogIDwvcmVjdD4KPC9nPjxnIHRyYW5zZm9ybT0icm90YXRlKDI0MCA1MCA1MCkiPgogIDxyZWN0IHg9IjQ3IiB5PSIyNCIgcng9IjkuNCIgcnk9IjQuOCIgd2lkdGg9IjYiIGhlaWdodD0iMTIiIGZpbGw9IiMwMDAiPgogICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0ib3BhY2l0eSIgdmFsdWVzPSIxOzAiIHRpbWVzPSIwOzEiIGR1cj0iMXMiIGJlZ2luPSItMC4yNXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIj48L2FuaW1hdGU+CiAgPC9yZWN0Pgo8L2c+PGcgdHJhbnNmb3JtPSJyb3RhdGUoMjcwIDUwIDUwKSI+CiAgPHJlY3QgeD0iNDciIHk9IjI0IiByeD0iOS40IiByeT0iNC44IiB3aWR0aD0iNiIgaGVpZ2h0PSIxMiIgZmlsbD0iIzAwMCI+CiAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJvcGFjaXR5IiB2YWx1ZXM9IjE7MCIgdGltZXM9IjA7MSIgZHVyPSIxcyIgYmVnaW49Ii0wLjE2NjY2NjY2NjY2NjY2NjY2cyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiPjwvYW5pbWF0ZT4KICA8L3JlY3Q+CjwvZz48ZyB0cmFuc2Zvcm09InJvdGF0ZSgzMDAgNTAgNTApIj4KICA8cmVjdCB4PSI0NyIgeT0iMjQiIHJ4PSI5LjQiIHJ5PSI0LjgiIHdpZHRoPSI2IiBoZWlnaHQ9IjEyIiBmaWxsPSIjMDAwIj4KICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9Im9wYWNpdHkiIHZhbHVlcz0iMTswIiB0aW1lcz0iMDsxIiBkdXI9IjFzIiBiZWdpbj0iLTAuMDgzMzMzMzMzMzMzMzMzMzNzIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSI+PC9hbmltYXRlPgogIDwvcmVjdD4KPC9nPjxnIHRyYW5zZm9ybT0icm90YXRlKDMzMCA1MCA1MCkiPgogIDxyZWN0IHg9IjQ3IiB5PSIyNCIgcng9IjkuNCIgcnk9IjQuOCIgd2lkdGg9IjYiIGhlaWdodD0iMTIiIGZpbGw9IiMwMDAiPgogICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0ib3BhY2l0eSIgdmFsdWVzPSIxOzAiIHRpbWVzPSIwOzEiIGR1cj0iMXMiIGJlZ2luPSIwcyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiPjwvYW5pbWF0ZT4KICA8L3JlY3Q+CjwvZz48L3N2Zz4=");
複製代碼

二、內聯節點中使用 backgorund-image

<view style="background-image: url(example.png)">
</view>
複製代碼

這個方法我就不應說出來~ 由於在真機是無效的。。。(欲哭無淚)

三、使用 image 這個方法我也懶得詳細貼demo了, 總之就是使用 image 改改樣式設置到底部便可。

<view>
  <image src="example.png" />
</view>
複製代碼

最後:如今的項目本地圖片使用是很是少的,反正我見過的項目最多也就幾張。 因此設置背景圖片最簡單的方法就是使用base64

五、object-fit無效

在h5中使用 object-fit 特性是很是多的,它能夠對圖片保持必定的比例,而不會發生變形, 若是想了解其具體內容到 MDN

在小程序中對圖片使用此特性是沒有效果的

.image {
  object-fit: cover;
}
複製代碼

解決這個問題也很簡單,使用小程序自帶的屬性便可

<image src="example.png" mode="aspectFill"></image>
複製代碼

具體屬性可到官方查看 mode屬性一覽

六、小程序mock數據

在WEB開發中咱們會使用 mockjs 進行攔截請求從而模擬數據。

在小程序中也可使用嗎? 那固然了, 只不過要對小程序 wx.request 處理。

一、安裝 mockjs

npm i mockjs
複製代碼

二、新建 wxMock.js

// 有點水平的應該能看得懂
// 微信底層API都是不能重寫的,因此用到 defineProperty 將其設置可寫
// 以後重寫了底層 wx.request 方法,而後作些處理便可

const __request = wx.request;
const Mock = require('mockjs');

Object.defineProperty(wx, 'request', { writable: true });

wx.request = function (config) {
  if (typeof Mock._mocked[config.url] === 'undefined') {
    __request(config);
    return;
  }

  const resTemplate = Mock._mocked[config.url].template;
  const response = Mock.mock(resTemplate);

  if (typeof config.success === 'function') {
    config.success(response)
  }
  
  if (typeof config.complete === 'function') {
    config.complete(response)
  }
};

module.exports = Mock;
複製代碼

三、使用 wxMock.js

const Mock = require('wxMock.js')

// 日常怎麼用的就怎麼用
Mock.mock('/api/example', {
  data: { ... }
})
複製代碼

四、在app.js入口文件中引入mock

import "./mock/index.js";
複製代碼

七、圖片寬度100%,高度沒法自適應

在WEB開發中當把圖片設置 100% 時,高度會自適應。

小程序就是不行,不行你看:

由於小程序底層已經對 image 添加了寬高了,因此默認就是 240px

解決方法是給 image 元素添加 mode 屬性

<image src="example.png" mode="widthFix"></image>
複製代碼

當添加此模式並給圖片設置 100% 寬度後,小程序自動計算其高度,就可讓圖片自適應了。

八、properties 能定義多個類型嗎?

我只能先說能夠

此特性是小程序基礎庫2.6.5新增的,可能有些小夥伴不知道。

optionalTypes 字段是個數組,指定屬性類型,能夠多個。

Component({
  properties: {
    lastLeaf: {
      // 這個屬性能夠是 Number 、 String 、 Object 三種類型中的一種
      type: Number,
      optionalTypes: [String, Object],
      value: 0
    }
  }
})
複製代碼

九、跳轉到tabbar沒法返回上一層

這個問題我估計每個開發者都經歷過。

常規頁面跳轉到 tabbar 頁面只能使用 wx.switchTab ,此API有個問題是:跳轉到 tabBar 頁面,並關閉其餘全部非 tabBar 頁面

因此當跳轉到 tabbar 頁面左上角返回鍵天然就沒了,因此是沒法返回上一層的。

用得比較多的場景就是購物車了, 某個頁面跳轉到購物車不能夠返回上一層那體驗不是不好麼。

這個問題我就不貼demo了,說下其方案。

  • 自定義導航頭部,新增一個返回鍵
  • 自定義 tabbar 組件, 這個時候就不存在什麼 switchTab 跳轉了
  • 將購物車頁面封裝成一個組件,而後新建2個頁面,一個做爲tabbar,一個做爲常規頁面,目前jd使用這種方案。

十、頁面使用 behaviors

behaviors 是用於組件間代碼共享的特性,相似於一些編程語言中的「mixins」「traits」

遺憾的是 behaviors 只能用於組件,想在頁面中使用怎麼辦?

雖然頁面中不可使用 behaviors 可是咱們能夠模擬 mixins 混入

一、首先咋們可使用 lodash 工具類 merge

或者本身實現:

export function merge(source, other) {
  if (!isObject(source) || !isObject(other)) {
    return other === undefined ? source : other
  }
  // 合併兩個對象的 key,另外要區分數組的初始值爲 []
  return Object.keys({
    ...source,
    ...other
  }).reduce((acc, key) => {
    // 遞歸合併 value
    acc[key] = merge(source[key], other[key])
    return acc
  }, Array.isArray(source) ? [] : {})
}
複製代碼

二、say.js 使用 mixins, 把它當成一個普通對象導出便可

export default {
  data: {
    say: 'hello'
  },
  $setData() {
    this.setData({ say: 'world' })
  }
}
複製代碼

三、在頁面中引入 mixins

import merge from './merge.js'
import say from 'say.js'

Page(merge(say, {
  data: {
    foo: 'foo'
  },
  onLoad() {
    // 調用 mixins 中的方法
    this.$setData()
  }
}))
複製代碼

這還算是比較完美的mixins方案了, 不過它有個缺點: 後面函數會覆蓋前面函數,在生命週期咋們能夠這麼解決:

// say.js mixins
export default {
  onLoad(options) {
    this.onLoadCallback && this.onLoadCallback(options)
  }
}
複製代碼

在有使用mixins的頁面能夠稍微改動

// ...

Page(merge(say, {
  onLoadCallback(options) {
    // ... do something
  }
}))
複製代碼

十一、避免 thirdScriptError 異常

一旦拋出 thirdScriptError 會致使整個應用程序崩潰白屏。

  • 一、不要在小程序項目中包含 dom/bom 相關API,即時不使用也會拋出異常,由於小程序會編譯整個項目。
  • 二、properties 必定要聲明類型
  • 三、不要提早引用,如 App 未註冊調用 getApp

總結

微信小程序開發和 web 仍是有一些區別的, 小程序的開發靈活度雖然如今沒有那麼高,但隨着不斷的迭代更新,會慢慢獲得改善,並受到衆多開發者的喜好。

這篇文章不會斷更,只要有些好的技巧會總結下來並分享。

相關文章
相關標籤/搜索