《微信小程序七日談》- 第一天:人生若只如初見

《微信小程序七日談》系列文章:javascript

  1. 第一天:人生若只如初見
  2. 次日:你可能要拋棄原來的響應式開發思惟
  3. 第三天:玩轉Page組件的生命週期
  4. 第四天:頁面路徑最多五層?導航能夠這麼玩
  5. 第五天:你可能要在登陸功能上花費大力氣
  6. 第六天:小程序devtool隱藏的祕密;
  7. 第七天:不要撿了芝麻丟了西瓜

本系列的文章並不是初學教程,而是筆者在具體開發過程當中遇到的問題以及部分解決方案。css

微信小程序自公佈以來就被捧上了天,新聞一波接一波。一部分聲音來自前端界,把小程序當成前端歷史地位提高的一次革新;一部分聲音來自app開發界,把小程序當成失業的助推器(攤手)。本文的目的不是討論小程序的是或非,只是記錄一下筆者在開發小程序過程當中一些收穫和感想。html

有消息稱第一批微信小程序在12月中下旬發佈,在那以前,須要將已完成的小程序向騰訊提交審覈。58到家看準了此次推廣的機會,制定了小程序開發計劃。筆者是主要開發者之一。前端

閒話少說,進入正題。vue

小程序號稱使用前端技術開發接近native體驗的webapp,微信提供了許多js和native交互的bridge API,同時將html/css進行改造,分別對應wxml和wxss。初見之時,看上去就是換個名字而已嘛,都是熟悉的技術,項目分分鐘開發完成哈哈。而後就興致勃勃的開始折騰,而後就...java

小程序官方文檔至關「簡潔」,以示例代碼的形式很形象地說明了各模塊的開發模式。可是示例代碼以及文字描述並未將其中的細節徹底暴露出來,上手開發後才發現不少坑。web

wxss

wxss乍看上去就是css,名字類似,語法類似。但寫起代碼來真是痛苦的很,下面一一列出目前筆者遇到的問題。json

1> 不支持級聯選擇器
css選擇器能夠支持自上而下一層層的級聯選擇,好比:小程序

.parent .child{
    color: #000;
}

前端開發者對此很是熟悉。可是wxss並不支持上述語法,若是使用class做爲匹配選擇器,只能寫一層,以下:微信小程序

.parent{}
.child{
    color: #000;
}

這種模式令開發者在爲class命名上必須不能重複,限制了自由度。

注意:目前最新版的小程序已經支持級聯選擇器。

2> 選擇器支持很是有限
目前官方給出的wxss支持選擇器只有如下幾種:

其中的element是wxml支持的標籤元素,並不是全部html標籤。

3> 不支持引用本地圖片資源
好比咱們須要使用本地的sprites圖片:

.dj__icon {
    background-image; url("./assets/icons.sprites.png");
}

若是在wxss中編寫以上代碼並不會報錯,可是也不會有任何理想的效果。官方給出的答覆是:

因此若是咱們須要使用自定義的圖標UI的話,目前只能先將sprites圖片上傳到本身的服務器或者base64編譯後再寫入wxss中。

wxml

wxml的語法與vue.js有點類似,支持數據綁定以及部分模板邏輯。筆者目前在wxml開發中總結如下幾點注意事項:

1> 使用wxml模板語法時只能使用部分js邏輯判斷
或者也能夠理解爲只能使用如下幾種邏輯:

  • 引用變量;
  • 二元操做符;
  • 三元操做符。

因爲wxml使用雙花括號{{}}做爲數據綁定標識,因此被{{}}包裹的邏輯語句不能出現花括號{},不然會報語法錯誤。好比:

<view>{{ Object.assign({},data,{isTrue: false})}}</view>

2> event handler的參數event不支持訪問DOM
小程序中不支持任何訪問DOM的語法,由於它並非在瀏覽器環境下運行,因此documentwindow等瀏覽器暴露的API均不能訪問。事件響應函數接受的event參數的完整結構以下:

{
    "type":"tap",
    "timeStamp":895,
    "target": {
      "id": "tapTest",
      "dataset":  {
        "hi":"WeChat"
      }
    },
    "currentTarget":  {
      "id": "tapTest",
      "dataset": {
        "hi":"WeChat"
      }
    },
    "detail": {
      "x":53,
      "y":14
    },
    "touches":[{
      "identifier":0,
      "pageX":53,
      "pageY":14,
      "clientX":53,
      "clientY":14
    }],
    "changedTouches":[{
      "identifier":0,
      "pageX":53,
      "pageY":14,
      "clientX":53,
      "clientY":14
    }]
}

因此若是想使用常規瀏覽器環境下,經過event.target獲取DOM是不可行的。只能經過操做數據來修改UI。

3> 使用剩餘參數語法向模板傳遞對象格式的data

wxml支持模板引用以便開發通用組件,好比項目中存在item.wxml

<!-- item.wxml -->
<template name="item">
  <text>{{text}}</text>
</template>

index.wxml 中引用了 item.wxml,就可使用item模板:

<import src="item.wxml"/>
<template is="item" data="{{text: 'forbar'}}"/>

其中的data是向item.wxml傳遞的參數。若是要循環一個列表數據,列表中每一個元素都是key-value格式且對應一個item的話,須要使用如下格式:

<import src="item.wxml"/>
<template is="item" wx:for="{{list}}" wx:for-item="item" data="{{..item}}"/>

上述代碼將列表的每一個元素總體傳遞給item.wxml,使用data="{{..item}}"語法。固然,你也能夠在data中添加其餘數據,好比data="{{..item, text:'forbar'}}"

3> 可將事件響應函數名稱經過data傳遞給組件模板
組件對引用它的模板來講就是一個黑盒,外部不該該干涉組件的內部邏輯。若是想要組件響應某些操做並反饋外部定義的響應函數,能夠將外部已定義的響應函數名稱傳給組件。

咱們將上文的代碼改造一下演示這個問題。好比item.wxml暴露了tap響應API:

<!-- item.wxml -->
<template name="item">
  <text bindtap="{{tapHandler}}">{{text}}</text>
</template>

index.wxml中引入item組件並傳遞了tapHandler:

<import src="item.wxml"/>
<template is="item" data="{{text: 'forbar', tapHandler: 'indexTapHandler'}}"/>

其中indexTapHandlerindex.wxml對應的js中聲明的響應函數:

Page({
    indexTapHandler(e){
        alert('trigger index tap event');
    }
});

這樣就完成了組件事件響應的定製。

3> 可變數組數據渲染務必使用wx:key

渲染列表數據時,若是列表中的數據是動態的(好比點擊以後修改列表中某個元素的值),那麼在渲染UI時務必將渲染的模板加上wx:key。請看如下代碼:

<import src="item.wxml"/>
<template is="item" wx:for="{{list}}" wx:for-item="item" wx:for-index="idx" wx:key="item-{{idx}}" data="{{..item}}"/>

上述代碼使用列表的index做爲wx:key的值,保證每一個元素對應template的惟一性。

wx:key的取值還能夠是保留字*this,官方給出的定義以下:

保留關鍵字 *this 表明在 for 循環中的 item 自己,這種表示須要 item 自己是一個惟一的字符串或者數字。

根據以上的解釋,若是item自己是動態不惟一的,是不能使用*this做爲wx:key取值的,不然會出現很是詭異的狀況。

總結

第一天的開發感想就是:小程序並不像第一眼看上去那麼美好,不能把小程序簡單地理解爲html+css+js。本文暫時不討論小程序背後的運行原理,單純出開發層面看,wxss至關於極度縮減版的css;wxml是mustache的簡化版。至於js,後續筆者會將遇到的問題和經驗寫出來,以供參考。

相關文章
相關標籤/搜索