## WeX5 & BeX5 頁面框架核心之數據綁定
### 視頻地址:[http://pan.baidu.com/s/1hqlBoC8](http://pan.baidu.com/s/1hqlBoC8)
# 目錄
* [1、引言:《外賣》案例的代碼不完整嗎???](http://wex5.com/cn/?p=4253#1)
* [2、概述](http://wex5.com/cn/?p=4253#2)
* [2.1、WeX5頁面組成](http://wex5.com/cn/?p=4253#2.1)
* [2.2、數據綁定](http://wex5.com/cn/?p=4253#2.2)
* [3、規則表達式](http://wex5.com/cn/?p=4253#3)
* [3.1、數據規則](http://wex5.com/cn/?p=4253#3.1)
* [3.2、環境變量](http://wex5.com/cn/?p=4253#3.2)
* [3.3、上下文對象](http://wex5.com/cn/?p=4253#3.3)
* [3.4、ref、val和label的區別](http://wex5.com/cn/?p=4253#3.4)
* [4、綁定表達式](http://wex5.com/cn/?p=4253#4)
* [4.1、概述](http://wex5.com/cn/?p=4253#4.1)
* [4.2、綁定表達式的環境變量和上下文對象](http://wex5.com/cn/?p=4253#4.2)
* [4.3、特殊的ref綁定(bind-ref、bind-labelRef、bind-extRef)](http://wex5.com/cn/?p=4253#4.3)
* [4.4、數據相關的綁定表達式(bind-value、bind-checked、bind-text)](http://wex5.com/cn/?p=4253#4.4)
* [4.5、狀態相關的綁定表達式(bind-visible、bind-enabled、bind-disabled、bind-hasFocus)](http://wex5.com/cn/?p=4253#4.5)
* [4.6、樣式相關的綁定表達式(bind-style、bind-css)](http://wex5.com/cn/?p=4253#4.6)
* [4.7、其他HTML屬性的綁定表達式(bind-attr-src、bind-attr-href、bind-attr-title、bind-attr-xxx)](http://wex5.com/cn/?p=4253#4.7)
* [4.8、HTML片段相關的綁定表達式(bind-if、binf-ifnot、bind-with、bind-foreach)](http://wex5.com/cn/?p=4253#4.8)
* [4.9、其他綁定表達式(bind-html、bind-uniqueName)](http://wex5.com/cn/?p=4253#4.9)
* [5、List組件的過濾表達式](http://wex5.com/cn/?p=4253#5)
* [6、表達式中使用JS對象和函數](http://wex5.com/cn/?p=4253#6)
* [附錄、表達式環境變量及上下文對象一覽表](http://wex5.com/cn/?p=4253#appendix)
# 1、引言:《外賣》案例的代碼不完整嗎???
WeX5自帶了一個經典的《外賣》案例,實現了常見的購物車需求。但是初學者在第一次去看它的源碼時,會發現它的JS代碼是“不完整的”。JS代碼中只有一些核心的與數據操作相關的代碼片段,很多頁面上的動態計算和顯示都找不到相應的代碼實現。
那么這些動態計算和顯示是如何實現的呢?不需要寫代碼嗎?仔細觀察相關組件的屬性定義,會發現它們原來都是通過一些支持表達式定義的屬性來實現的。這就是現在要給大家介紹的WeX5的數據綁定了。數據綁定讓很多原本需要大量的事件監控和代碼編程才能完成的數據運算、規則校驗和動態顯示等頁面邏輯,現在通過簡單的表達式定義就可以輕松實現了。
* 購物車中菜品增加后,下面的購物車按鈕會自動變成黃色,并顯示項目數
[](http://wex5.com/cn/wp-content/uploads/2015/04/bind-1-01.png)[](https://box.kancloud.cn/2015-09-23_560187dd98506.png)
* 購物車中菜品數量改變時,合計金額會自動計算
[](http://wex5.com/cn/wp-content/uploads/2015/04/bind-1-03.png)
[](https://box.kancloud.cn/2015-09-23_560187e863e32.png)
* 購物車中所有菜品數量為零時,下單按鈕會自動禁用
[](http://wex5.com/cn/wp-content/uploads/2015/04/bind-1-05.png)
[](https://box.kancloud.cn/2015-09-23_560187ee75397.png)
# 2、概述
## 2.1、WeX5頁面組成
[](https://box.kancloud.cn/2015-09-23_560187eed0cd1.png)
首先,我們來看一下WeX5的頁面組成。WeX5的頁面主要由數據(Data)、視圖(View)和代碼(Code)三個部分組成,體現了**數據與視圖分離、頁面描述與代碼邏輯分離**的核心設計思想。
* 數據部分包含若干個數據組件,是整個頁面的數據核心;
* 視圖部分包含布局組件、顯示組件和編輯組件等各種視圖組件,構成用戶交互界面;
* 代碼部分包含當前頁面的JS代碼,WeX5頁面采用基于組件對象的事件驅動程模式,數據和視圖部分的每個組件對象都提供了大量的方法和事件,讓開發者可以編程實現任意復雜的個性化邏輯。
## 2.2、數據綁定
WeX5在數據和視圖兩個層面的組件上,都提供了大量可通過表達式來定義的動態屬性。當表達式依賴的數據項改變時,表達式會自動重新計算,并通過屬性動態影響組件的顯示和行為。我們把頁面上的這種由數據驅動界面動態交互的能力統稱為“**數據綁定**”。
由于在數據和視圖兩個層面,表達式屬性的作用有所不同,我們把表達式屬性分為兩類:
* **規則表達式**:用于定義數據組件上的只讀、必填、計算和約束等數據規則;
* **綁定表達式**:用于定義視圖組件上的數據、狀態、樣式等各種動態交互屬性。
“**規則表達式**”和 “**綁定表達式**”都采用JS表達式語法,但不同的表達式屬性有不同的作用和描述規則。下面我們會對WeX5中提供的各種表達式屬性,逐個展開進行講解。
**本文所用到案例參見WeX5模型資源中的“數據綁定”(/UI2/demo/misc/bind/index.w)。啟動WeX5自帶的Tomcat服務后,在瀏覽器中訪問([http://localhost:8080/x5/UI2/demo/misc/bind/index.w](http://localhost:8080/x5/UI2/demo/misc/bind/index.w))即可運行。**
# 3、規則表達式
## 3.1、數據規則
在數據組件上支持表達式定義的數據規則有:
* 對整個數據集生效的只讀規則;
* 對數據列生效的只讀、計算、必填和約束規則。
[](https://box.kancloud.cn/2015-09-23_560187f295c03.png)
上圖來自案例中foodData的數據規則(在foodData組件的右鍵菜單中選擇編輯規則),我們現在就從圖中的規則表達式開始講起。
* **foodData只讀:$model.tempData.val(‘foodDataReadonly’)**
規則含義:當tempData的foodDataReadonly列值為true時,foodData全部只讀。
運行演示:點擊“只讀”按鈕觸發事件JS代碼,將tempData的foodDataReadonly列取非并賦值,從而導致所依賴的foodData只讀規則表達式重新計算,并最終影響界面相關組件的只讀狀態改變。
[](https://box.kancloud.cn/2015-09-23_560187f305045.png)
[](https://box.kancloud.cn/2015-09-23_560187f367e3d.png)
* **fDate只讀:$row.val(“fPrice”)>30**
規則含義:當前行的價格大于30時,日期字段只讀。
運行演示:選擇價格大于30的數據,右邊的日期字段自動只讀。
[](https://box.kancloud.cn/2015-09-23_560187f3c830f.png)
* **fDate約束:!$val || $val < ‘2020-01-01′**
規則含義:當前列的值不為空時必須小于’2020-01-01’。
運行演示:選擇大于’2020-01-01’的日期,會看到約束警告。
[](https://box.kancloud.cn/2015-09-23_560187fe372c4.png)
從上面的幾個示例中我們看到,數據規則表達式能力強大,但是使用簡單。當數據規則表達式中依賴的“**數據項**”改變后,表達式會自動重新計算,并且最終通過數據規則影響所關聯視圖組件的顯示和狀態,反映給最終用戶。
* **并不是任何一個組件都能感知數據規則**:在前面的foodData只讀規則示例中,我們可以觀察到當foodData只讀時,并不是所有關聯的視圖組件都只讀了。這是因為只有通過ref屬性綁定到數據的視圖組件才能感知數據規則,有關ref屬性綁定的知識在后面的綁定表達式部分進行講解。
[](https://box.kancloud.cn/2015-09-23_560187fe958e7.png)
* **并不是任何一個數據變量的改變都會自動觸發表達式的運算**:這里的數據特指“可觀察(observable)”數據。“可觀察”數據不是一個簡單變量,而是一個特殊的數據對象,當它的數據域改變時會自動刺激所有依賴它的表達式重新計算。Data組件中的數據項都是“可觀察”數據,所以前面的示例中所有的表達式都可以自動計算。WeX5的數據綁定體系基于knockoutJS(這是一個開源的數據感知框架),更多相關知識,大家可以參見[http://knockoutjs.com](http://knockoutjs.com/)。
## 3.2、環境變量
我們在前面的幾個表達式例子中,已經看到$model、$row、$val等以$開頭的特殊變量,這些就是在數據規則表達式中可以使用的環境變量。
* **$model**:當前頁面的模型對象(也就是當前頁面.js文件中Model對象的運行時實例)
* **$data**:當前數據對象
* **$row**:當前計算行對象
* **$col**:當前列名
* **$val**:當前數據值 = $row.val($col)
* **$rowID**:當前行的ID值 = $row.getID()
注意:$model.tempData是一種特殊寫法,頁面上只有數據組件可以這樣寫,獲取其他頁面組件都必須通過$model.comp(xid)方法。
注意:下面兩個表達式的不同,如果有疑問的話建議自己寫個例子實際觀察一下:
$data.val(‘fName’) — 當前選中行的fName列的值
$row.val(‘fName’) — 當前計算行的fName列的值
## 3.3、上下文對象
在數據規則表達式中,除了有上面所列的環境變量以外,還有一個默認的上下文對象,在表達式里是可以忽略的。例如:fDate的只讀規則$row.val(“fPrice”)>30,可以簡寫為val(“fPrice”)>30。
* 對于定義在數據集上的數據規則,默認上下文對象是$data
* 對于定義在數據列上的數據規則,默認上下文對象是$row
## 3.4、ref、val和label的區別
[](https://box.kancloud.cn/2015-09-23_560187ff08abe.png)
我們在表達式對話框里,每次都會看到每個列都有ref、val和label三個函數,它們有什么區別呢?
* **val**:返回列的數據值,用于表達式計算(由于這些數據本身是“可觀察”數據,所以當數據值改變時,會自動觸發所依賴的表達式規則重新計算)。
* **ref**:返回列的“可觀察”數據對象,用于視圖組件的ref綁定。
* **label**:返回列的名稱,一般用于頁面顯示列名標簽。
# 4、綁定表達式
## 4.1、概述
前面我們講解了可以在數據上定義的數據規則表達式,接下來我們要講解的是在視圖組件上定義的動態表達式—“綁定表達式”。
雖然我們從設計器上來看,綁定表達式是視圖組件的屬性,但其實綁定表達式可以作用于任何一個HTML標簽。當然,我們也可以認為每個HTML標簽本身就是最簡單的組件,而其他復雜組件都可以看做是基本HTML標簽的組合。
綁定表達式的能力極其強大,可以動態定義HTML標簽的所有屬性,甚至可以通過表達式定義動態創建HTML片段,可以實現各種復雜的界面動態交互。**沒有做不到,只有想不到!**
我們下面首先通過一個簡單的示例,來看一下綁定表達式是如何作用于HTML的。參照案例中的bind-visible(>30),input組件的bind-visible屬性值為foodData.val(‘fPrice’) > 30。我們首先通過選擇不同的數據行,可以觀察到如下現象:
[](https://box.kancloud.cn/2015-09-23_560187ff75b2a.png)
這時我們用F12打開“開發者工具”,監控這個input標簽的屬性,會發現:
[](https://box.kancloud.cn/2015-09-23_560187ffda7ad.png)
[](https://box.kancloud.cn/2015-09-23_560188005344c.png)
通過上面的示例觀察我們可以知道,當綁定表達式依賴的數據項改變時會重新計算,并動態更新對應HTML標簽的DOM結構,從而影響頁面的顯示,而這一切僅需要定義一個表達式就搞定!
## 4.2、綁定表達式的環境變量和上下文對象
**環境變量:**
* **$model**:當前頁面模型對象。
* **$element**:當前HTML標簽的JS對象。
* **$index**:當前行索引,僅當表達式處于bind-foreach所作用的內容片段時有效,見后“HTML片段相關的綁定表達式”。
* **$object**:當前HTML標簽所處環境的上下文對象,一般情況下就是$model;但是如果表達式處于bind-with和bind-foreach所作用的內容片段時,$object的值由bind-with和bind-foreach賦予,見后“HTML片段相關的綁定表達式”。
**上下文對象:**
* **$object**:見上,上下文對象在表達式中是可以忽略的,所以在案例的綁定表達式中經常可以看到foodData.val(‘fPrice’)這樣的寫法,這里其實相當于$object.foodData.val(‘fPrice’)和$model.foodData.val(‘fPrice’)。
## 4.3、特殊的ref綁定(bind-ref、bind-labelRef、bind-extRef)
在前面的數據規則表達式中我們提到過,視圖組件必須通過ref綁定到數據才能感知數據規則。ref綁定是一種高級的復合數據綁定,它可以為組件同時帶來多種數據感知能力:
* **雙向數據感知**:數據改變會自動更新組件顯示,組件編輯后也會自動更新數據。從界面交互效果上來看,就是多個關聯到同一個數據的組件,一個數據編輯后其它組件都會自動更新。
[](https://box.kancloud.cn/2015-09-23_56018800b4dd3.png)
* **數據規則感知**:組件可以通過HTML狀態和樣式的改變將只讀、必填、約束等規則提示給用戶。
[](https://box.kancloud.cn/2015-09-23_5601880122844.png)
* **數據類型感知**:這里特指input組件通過ref綁定數據列后,可以感知列的數據類型。例如:當列是日期類型時,input自動變成日期編輯模式;當列是整型數值時,input只能輸入數值。
[](https://box.kancloud.cn/2015-09-23_560188042115c.png)
注意:并不是所有的組件都支持ref綁定,只有屬性中包含bind-ref(bind-labelRef、bind-extRef)的組件才能支持ref綁定。目前支持ref綁定的組件有:input、output、textArea、select、gridSelect、radio、checkbox、radioGroup、checkboxGroup、toggle、attachment、blobImage等,基本上常用的表單編輯組件都是支持ref綁定的。
最后要注意,ref綁定的屬性值只能是數據列的ref對象,不支持表達式。
## 4.4、數據相關的綁定表達式(bind-value、bind-checked、bind-text)
* **bind-value**:適用于input、password、select、textarea
* **bind-checked**:適用于checkbox、radio
* **bind-text**:適用于span、label、em……
這三個表達式理解上很簡單,就是通過表達式來動態定義HTML標簽對應的數據屬性。
[](https://box.kancloud.cn/2015-09-23_5601880482338.png)
bind-value="foodData.ref('fPrice')"
bind-value="foodData.val('fPrice')"
bind-text="foodData.ref('fPrice')"
bind-checked="foodData.ref('fStatus')"
bind-value和bind-checked也可以支持雙向數據感知,但是要求表達式的值只能是“可觀察”數據對象(即列的ref值)。
[](https://box.kancloud.cn/2015-09-23_56018804dc2c7.png)
## 4.5、狀態相關的綁定表達式(bind-visible、bind-enabled、bind-disabled、bind-hasFocus)
* **bind-visible**:組件是否顯示
* **bind-enabled**:組件是否可用
* **bind-disabled**:組件是否禁用(優先級高于bind-enabled)
* **bind-hasFocus**:組件是否獲得輸入焦點
與狀態相關的四個表達式都要求必須是**布爾表達式**。
[](https://box.kancloud.cn/2015-09-23_5601880542e75.png)
bind-visible="foodData.val('fPrice') > 30"
bind-hasFocus="foodData.val('fPrice') > 50"
bind-enable="foodData.val('fStatus') == 1"
bind-disable="foodData.val('fStatus') != 1"
## 4.6、樣式相關的綁定表達式(bind-style、bind-css)
* **bind-style**:用表達式定義style中的屬性值
* **bind-css**:動態為html標簽增加或刪除class
這兩個綁定表達式都是用于動態定義HTML標簽的樣式,由于HTML樣式的能力包羅萬象、無所不能,所以對于這兩個表達式的使用場景,大家可以盡情發揮想象力。
這兩個表達式在寫法上與前面的簡單屬性表達式有所不同,采用JSON數據格式:
* bind-style:{“style屬性”: 表達式動態定義此style屬性的值}
* bind-css:{“class名稱”: 布爾表達式動態定義增加或刪除class}
[](https://box.kancloud.cn/2015-09-23_560188059fe7a.png)
bind-style(>30)的表達式:
bind-style=”{
'backgroundColor': foodData.val('fPrice') > 30 ? 'red' : null,
'color' : foodData.val('fPrice') > 30 ? 'yellow' : null
}”
含義:背景色當價格大于30時為紅色,前景色當價格大于30時為黃色
* bind-css(>30)的表達式:
bind-css=”{
'text-danger': foodData.val('fPrice') > 30
}”
含義:當價格大于30時,為class屬性動態增加text-danger
由于WeX5的頁面組件大多基于bootstrap框架,為了今后能統一的換膚,在大家定義bind-css表達式時,推薦大家盡量使用bootstrap已有的樣式。下面列出一些bootstrap常用樣式:
* 字體:.h1 .h2 .h3 .h4 .h5 .h6
* 顏色:.text-muted .text-primary .text-success .text-info .text-warning .text-danger
* 背景:.bg-primary .bg-success .bg-info .bg-warning .bg-danger
Bootstrap相關的資料請參見:[http://v3.bootcss.com/](http://v3.bootcss.com/)、[http://getbootstrap.com/](http://getbootstrap.com/)
## 4.7、其他HTML屬性的綁定表達式(bind-attr-src、bind-attr-href、bind-attr-title、bind-attr-xxx)
* **bind-attr-src**: 標簽的src屬性
* **bind-attr-href**:標簽的href屬性
* **bind-attr-title**:HTML標簽的title屬性
* **bind-attr-xxx**:xxx可以是HTML標簽的任意屬性,甚至是自定義屬性
bind-attr-src、bind-attr-href、bind-attr-title這三個表達式比較簡單,分別用于動態定義幾個特定的HTML屬性。
除了前面講的這些HTML屬性對應的特定綁定表達式,還可用bind-attr-xxx的動態定義任何其他HTML屬性。
[](https://box.kancloud.cn/2015-09-23_560188060582a.png)
## 4.8、HTML片段相關的綁定表達式(bind-if、binf-ifnot、bind-with、bind-foreach)
前面介紹的綁定表達式都是與HTML屬性相關的,下面介紹幾個與HTML片段相關的綁定表達式:
* **bind-if**:用布爾表達式定義HTML標簽的內容片段(innerHTML)是否創建
* **bind-ifnot**:同上但邏輯相反
注意:上面兩個表達式只是定義HTML標簽的內容片段是否**創建**,并不是隱藏和顯示,而且當前HTML標簽是不變的。
[](https://box.kancloud.cn/2015-09-23_560188066dbfc.png)
<div class="x-col" xid="col82" bind-if="foodData.val('fPrice') > 30">
<input type="text" value="" xid="input25" bind-value="foodData.val('fPrice')" style="width:100%;"/>
</div>
* **bind-with**:為HTML標簽的內容片段指定表達式的上下文對象$object
[](https://box.kancloud.cn/2015-09-23_56018806caa35.png)
<div class="x-col" xid="col16" bind-with="foodData">
<input type="text" value="" xid="input2" bind-value="xid+ '的數量:' + getCount()" style="width:100%;"/>
</div>
* **bind-foreach**:按照表達式定義的數組項,動態創建多份內容片段(innerHTML),并且每份內容片段的上下文對象$object分別等于數組中的每一項。
[](https://box.kancloud.cn/2015-09-23_560188072fcc4.png)
<div class="x-col" xid="col17" bind-foreach="foodData.datas">
<input type="text" value="" xid="input4" style="width:100%;" bind-value="$index() + val('fName')"/>
</div>
## 4.9、其他綁定表達式(bind-html、bind-uniqueName)
* **bind-html**:動態創建HTML標簽的innerHTML,要求表達式返回html片段。這個能力很強大吧,呵呵,這個算是留個課后作業,就不給例子了,自己DIY看看吧。
* **bind-uniqueName**:為HTML標簽動態創建唯一name,這個很少用。
# 5、List組件的過濾表達式
List組件的filter屬性可以用表達式過濾可顯示的數據項,List組件的filter表達式支持的環境變量有:
* **$model**:當前頁面模型對象。
* **$row**:當前計算行對象。
* **$object**:當前HTML標簽所處環境的上下文對象,同視圖組件。
修改案例左邊的List組件,filter=”$row.val(‘fStatus’) == 1”,頁面刷新后只顯示啟用的數據。
[](https://box.kancloud.cn/2015-09-23_560188078ed3b.png)
# 6、表達式中使用JS對象和函數
在數據表達式中除了我們前面提到的那些環境變量,其實我們可以使用任何“可以訪問的JS對象和函數”:
* Javasrcipt的全局函數和對象,例如:parseInt、parseFloat等。
* window對象,這個不用講了吧。
* jQuery,$可以直接用,例如:$.each、$(‘div’)等。
* justep工具類,例如:justep.Date.fromString。
* $model、$data、$row……等環境變量。
獲取頁面組件:
* 獲取當前頁面上的X5組件對象: $model.comp(xid)
* 獲取當前頁面上的HTML原生對象:$model.getElementByXid(xid)
基于$model自定義函數和函數庫:
* 自定義函數:在頁面的JS文件中為Model增加自定義函數,表達式中通過$model調用。
* 自定義函數庫:在頁面的JS文件中引入JS函數庫,將函數庫對象設置為Model的變量,表達式中通過$model訪問函數庫對象。
# 附錄、表達式環境變量及上下文對象一覽表
| **表達式** | **上下文對象** | **環境變量** |
| Data規則表達式 | 數據集表達式 | $data | $model、$data |
| 字段表達式 | $row | $model、$data、$row、$col、$rowID |
| View綁定表達式 | 一般場景 | $object=$model | $model、$element、$object |
| 在bind-with環境內 | $object=with的對象 | $model、$element、$object |
| 在list組件內 | $object=當前行對象row | $model、$element、$object、$index |
| 在bind-foreach環境內 | $object=當前行數據項 | $model、$element、$object、$index |
| 過濾表達式 | list的filter屬性 | $object(同上) | $model、$object、$row(當前計算行) |
- 快速入門
- 第一個應用
- WeX5產品能力和技術
- wex5技術理念
- WeX5可以怎么玩?
- WeX5和BeX5比較
- UI2開發
- UI2前端框架基礎01:應用和頁面
- UI2框架基礎02:框架結構圖和目錄
- 組建基礎
- 編程基礎
- js引用
- css、text引用
- 設置資源依賴
- 代碼調試
- 數據組件
- Data組件基礎01:列、初始化加載狀態、行對象和游標
- Data組件基礎02:規則、數據遍歷查找
- Data組件基礎03:CRUD
- Data組件基礎04:Tree、主從數據、更新模式
- Data組件基礎05:再談Data組件新增,查詢,保存
- Data組件的JSON數據格式
- WeX5 & BeX5 頁面框架核心之數據綁定
- 數據綁定屬性系列
- 初識綁定
- visible綁定
- text綁定
- html綁定
- css綁定
- 頁面布局
- 頁面樣式
- 樣式基礎
- 添加自定義圖標(iconfont)
- 常用組件
- bar組件
- contents組件
- 前端路由和頁面跳轉
- 路由模塊
- 頁面跳轉
- 部署和發布
- 三種部署方式
- Web app部署
- UIServer的緩存機制
- 自定義組件開發
- 組件運行時開發案例
- 組件設計時開發案例
- 組件設計時開發參考
- 屬性編輯器配置和開發
- 自定義向導開發(waiting)
- 第三方庫集成
- 集成Echarts
- 集成百度和高德地圖
- App開發
- 打包
- App打包基礎和常見問題
- App打包原理和目錄結構
- App打包過程詳解
- App打包服務器環境搭建
- 蘋果證書申請 使用
- Android和IOS的本地應用圖標規范
- Android和IOS的本地App如何安裝(apk&ipa)
- 蘋果App部署HTTPS進行在線下載安裝
- 調試
- Android和IOS真機調試
- 插件
- 如何使用和擴展cordova插件
- cordova插件開發
- 常用cordovar插件
- SQLite插件
- 極光推送(JPush)插件
- 微信支付入門教程
- 微信、支付寶支付開發
- 服務端開發
- App與服務端交互原理
- 輕量級Baas(視頻)(文字) (.net版)
- Data組件的JSON數據格式11
- 微信服務號集成(視頻)
- 擴展學習資料
- bootstrap
- Knockoutjs
- JQuery
- requirejs
- phonegap/cordova