小程序是一種不須要下載安裝便可使用的應用,它實現了應用「觸手可及」的夢想,用戶掃一掃或搜一下便可打開應用。也體現了「用完即走」的理念,用戶不用關心是否安裝太多應用的問題。應用將無處不在,隨時可用,但又無需安裝卸載。 ——張小龍javascript
微信小程序分爲視圖層和邏輯層,視圖層包含WXML(相似HTML)、WXSS(相似css),邏輯層包含javascript文件。視圖層經過事件通知邏輯層,而邏輯層經過控制data來更新視圖。此外,微信還提供了API、組件、配置文件,使微信小程序的開發更加簡單。css
在開發微信小程序時,咱們經過網絡請求請求數據,對數據進行必定的處理綁定到視圖便可,因爲組件的存在,簡單的展現變得更加簡單。涉及網絡請求、媒體、文件、緩存、位置、設備、支付、二維碼等功能時,均可以去調用相應的API。因此,微信小程序的開發足夠簡單,能夠快速開發並實現。html
固然,利弊是共存的,微信小程序開發起來雖然簡單,可是限制也較多、靈活性卻不足。在微信小程序中,要更新視圖就只能修改data,而視圖層也只能經過事件向邏輯層傳遞交互信息。前端傳統的Dom操做在微信小程序中是不可用的,由於window、document在微信小程序中都不存在,因此,只要涉及操做Dom的代碼均不可複用。微信小程序WXML提供的標籤也比HTML要少不少,可是常見的標籤都是有的,WXSS支持的樣式也比CSS要少一些。若是要將H5頁面移植到微信小程序,要修改的地方還比較多:前端
WXML標籤與HTML標籤並不一致,要重寫;java
微信小程序無DOM交互能力,涉及DOM操做的代碼須要在小程序中單獨設計;git
網絡請求、媒體、文件、緩存、界面等相關內容須要使用小程序提供的API來實現,API的使用比較簡單;程序員
與上述內容無關的JS邏輯代碼是能夠複用的;github
css代碼可複用率高,除了一些複雜的CSS3樣式外,基本移植可用。小程序額外提供了flex、rpx的實現,作響應式頁面變得更加容易。json
綜上,微信小程序開發簡單,碼農們能夠快速上手,開發出一個可用的小程序。可是,微信小程序限制也很多,不能操做DOM,支持的HTML標籤和CSS樣式少一些,作一些炫酷的動畫或者複雜的功能就比較困難。H5頁面移植到微信小程序要修改的地方也還比較多,主要是WXML標籤、JS和HTML的交互及小程序提供的API功能部分。小程序
若是你要開始開發一款微信小程序了,那麼正確的步驟是什麼呢?我也不知道啊。。。如下個人我的推薦步驟:
先了解微信小程序爲什麼而生,從產品的角度去思考微信小程序的利與弊(對於程序員思考爲何小程序要如此設計、爲何裏面有各類限制是很是有幫助的),推薦《一篇文章讀懂微信小程序(應用號)是什麼?》、《你的產品適不適合作微信小程序?》;
總體認識小程序的框架、設計理念、開發的利弊;
通讀微信小程序官網;
仔細閱讀小程序官網的開發部分(https://mp.weixin.qq.com/debu...,下載微信小程序開發者工具,體驗官網提供的Demo;
開始開發微信小程序。
微信小程序中,JS文件中聲明的變量和函數只在該文件中有效;不一樣的文件能夠聲明相同名字的變量和函數,不會相互影響。若是須要獲取全局的應用實例,能夠在App()中設置。
// app.js App({ globalData: 1 }) // a.js // The localValue can only be used in file a.js. var localValue = 'a' // Get the app instance. var app = getApp() // Get the global data and change it. app.globalData++
此外,能夠經過require()引入其餘JS文件,在文件中能夠經過module.exports來暴露模塊接口。
// common.js function sayHello(name) { console.log(`Hello ${name} !`) } module.exports.sayHello = sayHello
// index.js var common = require('common.js') Page({ helloMINA: function() { common.sayHello('MINA') } })
WXML能夠經過模板(template)來組織標籤,使WXML拆分合理、清晰易讀。使用template標籤來定義模版,使用name屬性指定模版名稱;經過import標籤來引入模版,並使用is屬性來指定使用的模版名稱,data傳入屬性。
// template/msgItem.wxml <template name="msgItem"> <view> <text> {{index}}: {{msg}} </text> <text> Time: {{time}} </text> </view> </template>
// index.wxml <import src="./template/msgItem.wxml" /> <template is="msgItem" data="{{...item}}"/>
使用@import語句能夠導入外聯樣式表,@import後跟須要導入的外聯樣式表的相對路徑,用;表示語句結束。
/** common.wxss **/ .small-p { padding:5px; }
/** app.wxss **/ @import "common.wxss"; .middle-p { padding:15px; }
視圖層包含相似HTML的WXML、基本等同於CSS的WXSS,邏輯層則包含ES,去除了window、document等對象及方法,提供了一些API。視圖層經過事件來通知邏輯層交互,邏輯層經過修改data來更新視圖。
<view id="tapTest" data-name="Payton" bindtap="tapName"> {{userName}}, Click me! </view>
Page({ data: { userName: 'xxx' }, tapName: function(e){ wx.showToast({ title: 'hi,' + this.data.userName + 'I`m ' + e.currentTarget.dataset.name, icon: 'success', duration: 2000 }) } })
WXML中的動態數據均來自對應 Page 的 data。數據綁定使用雙大括號將變量包起來,數據改變(this.setData())時就會更新視圖,更新方式相似於虛擬dom。而事件的定義須要在標籤屬性中指定事件處理函數名稱,事件處理函數在Page({})中定義,若是事件處理函數須要傳遞參數,則要在標籤的data-中定義,可是通常狀況下,咱們是不須要傳遞參數的,由於大部分的數據咱們能夠在事件處理函數中只是使用this.data.的方式取得。
在小程序中,要使用this.setData()的方式來修改data,進而更新視圖。可是,當要修改data中的二級數據時,將不會進行合併修改。如:
Page({ data: { userInfo: { name: 'payton', sex: 1 }, tip: 'hello, world' }, onLoad: function(){ this.setData({tip: 'hello, world!'}) // 進行合併修改,userInfo不變 this.setData({userInfo: {name: 'peyton'}}) // 二級數據,總體修改。userInfo中sex消失,userInfo爲{name: 'peyton'} } })
不少時候,咱們在修改data時,是但願只修改咱們傳入的參數,而原有的參數不進行變動的,如上面咱們只但願修改name,而sex保持和原來一致。因此,咱們能夠採起一下方式:
this.setData({ userInfo: { name: 'peyton', sex: this.data.userInfo.sex } })
可是這種方式很麻煩,並且很容易形成忘記一些內容,或者修改屬性名時很容易漏掉。因此,咱們設計了一個函數,來實現這種深層次數據的合併修改。使用下面的方式,即可以進行合併了。
// util.js function mergeObject(to, source) { var from; var symbols; for(var s = 1; s < arguments.length; s++) { from = Object(arguments[s]); for(var key in from) { if(hasOwnProperty.call(from, key)) { to[key] = from[key]; } } } return to; }; module.exports.mergeObject = mergeObject;
var util = require('../util.js'); Page({ ... onLoad: function(){ this.setData({tip: 'hello, world!'}) //進行合併修改,userInfo不變 this.setData({ userInfo: util.mergeObject(this.data.userInfo, { name: 'peyton' }) }) // 合併修改,sex不會消失。userInfo爲{name:'peyton',sex:1} } })
在開發H5頁面時,咱們一般要使用innerHTML來修改一個標籤內的HTML,在小程序中,咱們沒法手動修改DOM。好比:後臺傳遞過來一短內容,這段內容要展示在頁面中,可是其中包含圖片,且圖片數目不定。咱們就沒有辦法經過js來構造HTML片斷,並插入到視圖中。在開發花樣直播時,有時候一個用戶發送的內容中包含表情,也就是圖片,此時,使用小程序的data是沒法解析標籤的,這個功能實現起來就很麻煩。個人實現方式以下:
// msg.wxml <block wx:for="{{contents}}" wx:for-item="content"> <text wx:if="{{content.type == 'text'}}" class="content">{{content.text}}</text> <image wx:if="{{content.type == 'image'}}" class="emoji" src="{{content.src}}"></image> </block>
// 後臺傳遞的content: 主播好漂亮/:149/ (注:/:149/表示微笑表情) if (...) { return { type: 'text', text: text } } else if (..){ return { type: 'image', src: src } }
也就是要將後臺傳遞的內容轉成數組,而且須要標明類型,再根據條件渲染,分別渲染成文字和圖片。因爲我這裏的需求只須要關注展現文字和表情,因此這種方式處理起來就OK。可是,若是後臺傳遞的是文章類型的內容(包含圖片、標題等等),須要轉換成多種格式,再本身寫就會很麻煩了。這個時候推薦使用wxParse(https://github.com/icindy/wxP...,支持HTML及markdown解析,其實現思路其實和上面方式相似。使用wxParse的話,能夠將H5版本構造的html片斷直接傳入wxParse,wxParse會進行解析,最終轉換成小程序版本。不過,有同事用過,不過反饋說頁面中圖片多的話,用wxParse會比較卡,我本身沒有嘗試過,此處就再也不多說。
小程序自己提供了不少組件和API,使用這些組件和API能夠很方便的進行開發,極大的加快開發進程。目前來講,有些組件和API還有些小坑,目前仍在動態完善中。關注此部分,官網上全面不少,此處只作簡述。
在小程序中,能夠經過app.json對小程序進行全局的配置,在每一個頁面中能夠進行有關配置(只能配置頁面內的配置項,比全局配置要少)。在全局配置中,能夠配置的內容爲:
pages,設置頁面路徑,第一個路徑即爲默認初始頁,全部的頁面路徑均須要配置;
window,設置默認頁面的窗口表現,如狀態欄、導航條、標題、窗口背景色等(能夠在頁面中配置,覆蓋全局配置);
tabBar,設置tab的表現,能夠設置圖片、文字等;
networkTimeout,網絡超時時間;
debug,設置是否開啓 debug 模式。
與H5相比,WXML提供的組件種類並不算多,可是經常使用的都有,開發個小程序不成問題。其組件中提供了一些便捷的屬性,仍是很方便的,可是屬性與H5相比仍然不全面。
視圖容器:view(相似div)、scroll-view(相似帶滾動條的div)、swiper(滑塊視圖容器);
表單組件:button、checkbox、form、input、label等;
基礎內容:icon(小程序提供的圖標)、text(行內文本)、progress(進度條);
媒體組件:audio、image(background-image的形式有不少坑,最好用image)、video;
地圖、畫布、導航、客服會話等。
微信小程序提供的API仍是挺多,用起來也還不錯。
網絡:請求(http請求,使用手感不錯)、上傳、下載、WebSocket(服務器能支持就很爽了);
媒體:圖片、錄音、音頻控制、視頻控制(目前感受這部分提供的API仍然不足);
界面:提示框、彈框、導航條設置、跳轉、下拉刷新、繪圖等;
數據緩存、設備(羅盤、掃碼、撥打電話、重力感應等)、文件等;
開放接口:登陸、微信支付、用戶信息、模板消息、分享等。