小程序包含一個描述總體程序的 app
和多個描述各自頁面的 page
。javascript
描述頁面的四個文件必須具備相同的路徑與文件名css
網頁開發者須要面對的環境是各式各樣的瀏覽器,PC 端須要面對 IE、Chrome、QQ瀏覽器等,在移動端須要面對Safari、Chrome以及 iOS、Android 系統中的各式 WebView 。而小程序開發過程當中須要面對的是兩大操做系統 iOS 和 Android 的微信客戶端,以及用於輔助開發的小程序開發者工具,小程序中三大運行環境也是有所區別的,html
JSON 是一種數據格式,並非編程語言,在小程序中,JSON扮演的靜態配置的角色。java
咱們能夠看到在項目的根目錄有一個 app.json
和 project.config.json
,此外在 pages/logs
目錄下還有一個 logs.json
,咱們依次來講明一下它們的用途。git
app.json
是當前小程序的全局配置,包括了小程序的全部頁面路徑、界面表現、網絡超時時間、底部 tab 等。QuickStart 項目裏邊的 app.json
配置內容以下:編程
一般你們在使用一個工具的時候,都會針對各自喜愛作一些個性化配置,例如界面顏色、編譯配置等等,當你換了另一臺電腦從新安裝工具的時候,你還要從新配置。json
考慮到這點,小程序開發者工具在每一個項目的根目錄都會生成一個 project.config.json
,你在工具上作的任何配置都會寫入到這個文件,當你從新安裝工具或者換電腦工做時,你只要載入同一個項目的代碼包,開發者工具就自動會幫你恢復到當時你開發項目時的個性化配置,其中會包括編輯器的顏色、代碼上傳時自動壓縮等等一系列選項。小程序
所以咱們提供了 page.json
,讓開發者能夠獨立定義每一個頁面的一些屬性,例如剛剛說的頂部顏色、是否容許下拉刷新等等微信小程序
這裏說一下小程序裏JSON配置的一些注意事項。api
JSON文件都是被包裹在一個大括號中 {},經過key-value的方式來表達數據。JSON的Key必須包裹在一個雙引號中,在實踐中,編寫 JSON 的時候,忘了給 Key 值加雙引號或者是把雙引號寫成單引號是常見錯誤。
JSON的值只能是如下幾種數據格式,其餘任何格式都會觸發報錯,例如 JavaScript 中的 undefined。
還須要注意的是 JSON 文件中沒法使用註釋,試圖添加註釋將會引起報錯
要換一個思路了,在框架,其餘的開發中,在html中的標籤,如今都叫
組件了,要記得轉換過來。所謂封裝好的組件,在使用的時候就已經有了
一些js,css交互的功能了。而標籤更多的還只是語義化
標籤名字有點不同
每每寫 HTML 的時候,常常會用到的標籤是 div
, p
, span
,開發者在寫一個頁面的時候能夠根據這些基礎的標籤組合出不同的組件,例如日曆、彈窗等等。換個思路,既然你們都須要這些組件,爲何咱們不能把這些經常使用的組件包裝起來,大大提升咱們的開發效率。
從上邊的例子能夠看到,小程序的 WXML
用的標籤是 view
, button
, text
等等,這些標籤就是小程序給開發者包裝好的基本能力,咱們還提供了地圖、視頻、音頻等等組件能力。
多了一些 wx:if
這樣的屬性以及 這樣的表達式
在網頁的通常開發流程中,咱們一般會經過 JS
操做 DOM
(對應 HTML
的描述產生的樹),以引發界面的一些變化響應用戶的行爲。例如,用戶點擊某個按鈕的時候,JS
會記錄一些狀態到 JS
變量裏邊,同時經過 DOM
API 操控 DOM
的屬性或者行爲,進而引發界面一些變化。當項目愈來愈大的時候,你的代碼會充斥着很是多的界面交互邏輯和程序的各類狀態變量,顯然這不是一個很好的開發模式,所以就有了 MVVM 的開發模式(例如 React, Vue),提倡把渲染和邏輯分離。簡單來講就是不要再讓 JS
直接操控 DOM
,JS
只須要管理狀態便可,而後再經過一種模板語法來描述狀態和界面結構的關係便可。
小程序的框架也是用到了這個思路,若是你須要把一個 Hello World
的字符串顯示在界面上。
WXML 是這麼寫 :
JS 只須要管理狀態便可:<text>{{msg}}</text>
經過 {{ }} 的語法把一個變量綁定到界面上,咱們稱爲數據綁定。僅僅經過數據綁定還不夠完整的描述狀態和界面的關係,還須要 /, 等控制能力,
在小程序裏邊,這些控制能力都用 開頭的屬性來表達this.setData({ msg: "Hello World" })ifelseforwx:
WXSS
具備 CSS
大部分的特性,小程序在 WXSS
也作了一些擴充和修改。
新增了尺寸單位。在寫 CSS
樣式時,開發者須要考慮到手機設備的屏幕會有不一樣的寬度和設備像素比,採用一些技巧來換算一些像素單位。WXSS
在底層支持新的尺寸單位 rpx
,開發者能夠免去換算的煩惱,只要交給小程序底層來換算便可,因爲換算採用的浮點數運算,因此運算結果會和預期結果有一點點誤差。
提供了全局的樣式和局部樣式。和前邊 app.json
, page.json
的概念相同,你能夠寫一個 app.wxss
做爲全局樣式,會做用於當前小程序的全部頁面,局部頁面樣式 page.wxss
僅對當前頁面生效。
此外 WXSS
僅支持部分 CSS
選擇器
咱們改變數據必須用setData嗎? this.setDate({msg:hello world})
並且這個setData還必須在函數裏面
響應用戶的操做就是這麼簡單,更詳細的事件能夠參考文檔 WXML - 事件 。
此外你還能夠在 JS 中調用小程序提供的豐富的 API,利用這些 API 能夠很方便的調起微信提供的能力,例如獲取用戶信息、本地存儲、微信支付等。在前邊的 QuickStart 例子中,在 pages/index/index.js
就調用了 wx.getUserInfo 獲取微信用戶的頭像和暱稱,最後經過 setData
把獲取到的信息顯示到界面上。更多 API 能夠參考文檔 小程序的API 。
這些得本身看官方文檔的API內容
微信客戶端在打開小程序以前,會把整個小程序的代碼包下載到本地。
緊接着經過 app.json
的 pages
字段就能夠知道你當前小程序的全部頁面路徑:
因而微信客戶端就把首頁的代碼裝載進來,經過小程序底層的一些機制,就能夠渲染出這個首頁。
小程序啓動以後,在 app.js
定義的 App
實例的 onLaunch
回調會被執行:
整個小程序只有一個 App 實例,是所有頁面共享的,更多的事件回調參考文檔 註冊程序 App 。
Page({ data: { // 參與頁面渲染的數據 logs: [] }, onLoad: function () { // 頁面渲染後 執行 } })
Page
是一個頁面構造器,這個構造器就生成了一個頁面。在生成頁面的時候,小程序框架會把 data
數據和 index.wxml
一塊兒渲染出最終的結構,因而就獲得了你看到的小程序的樣子。
在渲染完界面以後,頁面實例就會收到一個 onLoad
的回調,你能夠在這個回調處理你的邏輯。
有關於 Page
構造器更多詳細的文檔參考 註冊頁面 Page
小程序提供了豐富的基礎組件給開發者,開發者能夠像搭積木同樣,組合各類組件拼合成本身的小程序。
<map bindmarkertap="markertap" longitude="廣州經度" latitude="廣州緯度"></map>
要獲取用戶的地理位置時,只須要:
調用微信掃一掃能力,只須要:wx.getLocation({ type: 'wgs84', success: (res) => { var latitude = res.latitude // 緯度 var longitude = res.longitude // 經度 } })
須要注意的是:多數 API 的回調都是異步,你須要處理好代碼邏輯的異步問題。
wx.scanCode({ success: (res) => { console.log(res) } })
相比於XML ,JSON格式最大的優勢是易於人的閱讀和編寫,一般不須要特殊的工具,就能讀懂和修改,是一種輕量級的數據交換格式。
JSON文件都是被包裹在一個大括號中 {},經過key-value的方式來表達數據。
看起來同 JavaScript 的對象表達方式十分類似,可是有所不一樣。
報錯信息的箭頭附近是有語法錯誤的
WXML 全稱是 WeiXin Markup Language,是小程序框架設計的一套標籤語言,結合小程序的基礎組件、事件系統,能夠構建出頁面的結構。
使用 wx:elif 和 wx:else 來添加一個 else 塊:
由於 wx:if 是一個控制屬性,須要將它添加到一個標籤上。若是要一次性判斷多個組件標籤,可使用一個 標籤將多個組件包裝起來,並在上邊使用 wx:if 控制屬性。
<view wx:if="{{length > 5}}"> 1 </view> <view wx:elif="{{length > 2}}"> 2 </view> <view wx:else> 3 </view><block/>
<block wx:if="{{true}}"> <view> view1 </view> <view> view2 </view> </block>
在組件上使用 wx:for 控制屬性綁定一個數組,便可使用數組中各項的數據重複渲染該組件。默認數組的當前項的下標變量名默認爲 index,數組當前項的變量名默認爲 item
使用 wx:for-item 指定數組當前元素的變量名,使用 wx:for-index 指定數組當前下標的變量名:
就是說指定他們的變量名,不是叫index和item了<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName"> {{idx}}: {{itemName.message}} </view>
相似block wx:if
,也能夠將wx:for
用在<block/>
標籤上,以渲染一個包含多節點的結構塊。例如:
block wx:ifwx:for<block/>
難道不放在block裏就不能渲染多個標籤了嗎<block wx:for="{{[1, 2, 3]}}"> <view> {{index}}: </view> <view> {{item}} </view> </block>
WXML提供模板(template),能夠在模板中定義代碼片斷,而後在不一樣的地方調用。使用 name 屬性,做爲模板的名字。而後在 <template/>
內定義代碼片斷,如:
這個東西我之前還百度過
看例子仍是有點看不懂
但好像也少用 知道他是模板就行了
就重複代碼段,到時候用到再百度
WXML 提供兩種文件引用方式import和include。
import 能夠在該文件中使用目標文件定義的 template,
須要注意的是 import 有做用域的概念,即只會 import 目標文件中定義的 template,而不會 import 目標文件中 import 的 template,簡言之就是 import 不具備遞歸的特性。
例如:C 引用 B,B 引用A,在C中可使用B定義的 template,在B中可使用A定義的 template ,可是C不能使用A定義的template ,
WXSS(WeiXin Style Sheets)是一套用於小程序的樣式語言,用於描述WXML的組件樣式,也就是視覺上的效果。
在小程序開發中,開發者不須要像Web開發那樣去優化樣式文件的請求數量,只須要考慮代碼的組織便可。樣式文件最終會被編譯優化,具體的編譯原理咱們留在後面章節再作介紹。
爲了減輕開發者樣式開發的工做量,咱們提供了WeUI.wxss基礎樣式庫。
WeUI是一套與微信原生視覺體驗一致的基礎樣式庫,由微信官方設計團隊爲微信內網頁和微信小程序量身設計,令用戶的使用感知更加統一。包含button、cell、dialog、progress、toast、article、actionsheet、icon等各式原生。
小程序的主要開發語言是 JavaScript ,開發者使用 JavaScript 來開發業務邏輯以及調用小程序的 API 來完成業務需求。
小程序中的 JavaScript 是由ECMAScript 以及小程序框架和小程序 API 來實現的。同瀏覽器中的JavaScript 相比沒有 BOM 以及 DOM 對象,因此相似 JQuery、Zepto這種瀏覽器類庫是沒法在小程序中運行起來的,一樣的缺乏 Native 模塊和NPM包管理的機制,小程序中沒法加載原生庫,也沒法直接使用大部分的 NPM 包。
小程序目前能夠運行在三大平臺:
小程序IDE提供語法轉碼工具幫助開發者,將 ECMAScript 6代碼轉爲 ECMAScript 5代碼,從而在全部的環境都能獲得很好的執行
開發者須要在項目設置中,勾選 ES6 轉 ES5 開啓此功能。
瀏覽器中,全部 JavaScript 是在運行在同一個做用域下的,定義的參數或者方法能夠被後續加載的腳本訪問或者改寫。同瀏覽器不一樣,小程序中能夠將任何一個JavaScript 文件做爲一個模塊,經過module.exports 或者 exports 對外暴露接口。(ES6提出的模塊化)
請看是一個簡單模塊示例,B.js 引用模塊A,並使用A暴露的multiplyBy2方法完成一個變量乘以 2 的操做。
// moduleA.js module.exports = function( value ){ return value * 2; }
// B.js // 在B.js中引用模塊A var multiplyBy2 = require('./moduleA') var result = multiplyBy2(4)
瀏覽器中,腳本嚴格按照加載的順序執行
而在小程序中的腳本執行順序有所不一樣。小程序的執行的入口文件是 app.js 。而且會根據其中 require 的模塊順序決定文件的運行順序,
當 app.js 執行結束後,小程序會按照開發者在 app.json 中定義的 pages 的順序,逐一執行。
就是說會先執行,App.js中的代碼
而後纔會執行頁面中的js代碼
當須要使用全局變量的時,經過使用全局函數 getApp() 獲取全局的實例,並設置相關屬性值,來達到設置全局變量的目的
從這個例子咱們能夠看到3個點:
1.渲染層和數據相關。
2.邏輯層負責產生、處理數據。
3.邏輯層經過 Page 實例的 setData 方法傳遞數據到渲染層。
宿主環境提供了 App() 構造器用來註冊一個程序App,須要留意的是App() 構造器必須寫在項目根目錄的app.js裏,App實例是單例對象,在其餘JS腳本中可使用宿主環境提供的 getApp() 來獲取程序實例。
var appInstance = getApp()
其中onLaunch / onShow / onHide 三個回調是App實例的生命週期函數,咱們會在後文展開;onError咱們暫時不在本章展開,
這是應用的生命週期:頁面有頁面的生命週期
代碼清單3-4 App構造器
App({ onLaunch: function(options) {}, onShow: function(options) {}, onHide: function() {}, onError: function(msg) {}, globalData: 'I am global data' })
初次進入小程序的時候,微信客戶端初始化好宿主環境,同時從網絡下載或者從本地緩存中拿到小程序的代碼包,把它注入到宿主環境,初始化完畢後,微信客戶端就會給App實例派發onLaunch事件,App構造器參數所定義的onLaunch方法會被調用。
進入小程序以後,用戶能夠點擊右上角的關閉,或者按手機設備的Home鍵離開小程序,此時小程序並無被直接銷燬,咱們把這種狀況稱爲「小程序進入後臺狀態」,App構造器參數所定義的onHide方法會被調用。
當再次回到微信或者再次打開小程序時,微信客戶端會把「後臺」的小程序喚醒,咱們把這種狀況稱爲「小程序進入前臺狀態」,App構造器參數所定義的onShow方法會被調用。
咱們能夠看到,App的生命週期是由微信客戶端根據用戶操做主動觸發的。爲了不程序上的混亂,咱們不該該從其餘代碼裏主動調用App實例的生命週期函數。
在微信客戶端中打開小程序有不少途徑:從羣聊會話裏打開,從小程序列表中打開,經過微信掃一掃二維碼打開,從另一個小程序打開當前小程序等,針對不一樣途徑的打開方式,小程序有時須要作不一樣的業務處理,因此微信客戶端會把打開方式帶給onLaunch和onShow的調用參數options,示例代碼以及詳細參數如代碼清單3-5和表3-2所示。須要留意小程序的宿主環境在迭代更新過程會增長很多打開場景,所以要獲取最新的場景值說明請查看官方文檔:https://mp.weixin.qq.com/debug/wxadoc/dev/framework/app-service/app.html。
getApp()獲得App.js裏面的實例
經過以上分析能夠看出,setTimeout與setInterval的主要區別是:
setTimeout()方法只運行一次,也就是說當達到設定的時間後就出發運行指定的代碼,運行完後就結束了,若是還想再次執行一樣的函數,能夠在函數體內再次調用setTimeout(),能夠達到循環調用的效果。
setInterval()是循環執行的,即每達到指定的時間間隔就執行相應的函數或者表達式,是真正的定時器。
與此同時,咱們要特別留意一點,全部頁面的腳本邏輯都跑在同一個JsCore線程,頁面使用setTimeout或者setInterval的定時器,而後跳轉到其餘頁面時,這些定時器並無被清除,須要開發者本身在頁面離開的時候進行清理。
宿主環境提供了 Page() 構造器用來註冊一個小程序頁面,Page()在頁面腳本page.js中調用,Page() 的調用方式如代碼清單3-8所示。Page構造器接受一個Object參數,參數說明如表3-4所示,其中data屬性是當前頁面WXML模板中能夠用來作數據綁定的初始數據,咱們會在後文展開討論;onLoad / onReady / onShow / onHide /onUnload 5個回調是Page實例的生命週期函數,咱們在後文展開;onPullDownRefresh / onReachBottom / onShareAppMessage / onPageScroll 4個回調是頁面的用戶行爲,咱們也會在後文展開。
代碼清單3-8 Page構造器
頁面初次加載的時候,微信客戶端就會給Page實例派發onLoad事件,Page構造器參數所定義的onLoad方法會被調用,onLoad在頁面沒被銷燬以前只會觸發1次,在onLoad的回調中,能夠獲取當前頁面所調用的打開參數option,關於打開參數咱們放在這一節的最後再展開闡述。
頁面顯示以後,Page構造器參數所定義的onShow方法會被調用,通常從別的頁面返回到當前頁面時,當前頁的onShow方法都會被調用。
在頁面初次渲染完成時,Page構造器參數所定義的onReady方法會被調用,onReady在頁面沒被銷燬前只會觸發1次,onReady觸發時,表示頁面已經準備穩當,在邏輯層就能夠和視圖層進行交互了。
以上三個事件觸發的時機是onLoad早於 onShow,onShow早於onReady。
頁面不可見時,Page構造器參數所定義的onHide方法會被調用,這種狀況會在使用wx.navigateTo切換到其餘頁面、底部tab切換時觸發。
當前頁面使用wx.redirectTo或wx.navigateBack返回到其餘頁時,當前頁面會被微信客戶端銷燬回收,此時Page構造器參數所定義的onUnload方法會被調用。
在列表頁打開商品詳情頁時把商品的id傳遞過來,詳情頁經過剛剛說的onLoad回調的參數option就能夠拿到商品id,從而繪製出對應的商品,
宿主環境所提供的Page實例的原型中有setData函數,咱們能夠在Page實例下的方法調用this.setData把數據傳遞給渲染層,從而達到更新界面的目的。
因爲小程序的渲染層和邏輯層分別在兩個線程中運行,因此setData傳遞數據實際是一個異步的過程,
因此setData的第二個參數是一個callback回調,在此次setData對界面渲染完畢後觸發。
setData其通常調用格式是 setData(data, callback),其中data是由多個key: value構成的Object對象。
代碼清單3-11 使用setData更新渲染層數據// pages/list/list.js // 列表頁使用navigateTo跳轉到詳情頁 wx.navigateTo({ url: 'pages/detail/detail?id=1&other=abc' }) // pages/detail/detail.js Page({ onLoad: function(option) { console.log(option.id) console.log(option.other) } })
// page.js Page({ onLoad: function(){ this.setData({ text: 'change data' }, function(){ // 在此次setData對界面渲染完畢後觸發 }) } })
此外須要注意如下3點:
小程序宿主環境提供了四個和頁面相關的用戶行爲回調:
用戶轉發 onShareAppMessage
只有定義了此事件處理函數,右上角菜單纔會顯示「轉發」按鈕,在用戶點擊轉發按鈕的時候會調用,此事件須要return一個Object,包含title和path兩個字段,用於自定義轉發內容,如代碼清單3-13所示。
須要注意,全部組件名和屬性都是小寫,多個單詞會以英文橫槓 "-" 進行鏈接。
對於一些容器組件,其內容能夠聲明在其開始標籤和結束標籤之間。
這個mode屬性只要image組件有嗎
mode(中文名模式)
咱們介紹一下API通常調用的約定:
wx.set* 開頭的API是寫入數據到宿主環境的接口。
事件是經過bindtap這個屬性綁定在組件上的,同時在當前頁面的Page構造器中定義對應的事件處理函數tapName,當用戶點擊該view區域時,達到觸發條件生成事件tap,該事件處理函數tapName會被執行,同時還會收到一個事件對象event。