數據綁定
Weex使用 mustache 的語法 ({{...}}) 來對 <template> 中的模板和 <script> 里的數據進行綁定. 一旦數據額模板綁定了, 數據上的修改會實時的在模板內容中生效。
樣式: style 或 class
組件的樣式能夠通過style特性進行綁定:
<template>
<div>
<text style="font-size: {{size}}; color: {{color}};">Hello World</text>
</div>
</template>
<script>
module.exports = {
data: {
size: 32,
color: '#ff0000'
}
}
</script>
樣式也能夠通過class特性實現樣式綁定,多個 class 名通過空格分隔:
<template>
<div>
<text class="{{size}}">Hello</text>
<text class="title {{status}}">World</text>
</div>
</template>
<style>
.large { font-size: 64; }
.small { font-size: 32; }
.title { font-weight: bold; }
.success { color: #00ff00; }
.error { color: #ff0000; }
</style>
<script>
module.exports = {
data: {
size: 'large',
status: 'success'
}
}
</script>
按下Ctrl+Shift+P調出命令面板輸入install 調出 Install Package 選項並回車,然后在列表中選中要安裝的插件。按下Ctrl+Shift+P調出命令面板輸入install 調出 Install Package 選項並回車,然后在列表中選中要安裝的插件。
weex hello.we
weex hello.we --qr
weex debug hello.we
在 Weex 中,您可以通過在特定的子組件上設置 id 特性,以此在該 <template> 內唯一標識這個組件。
Weex 代碼由三部分構成:template、style、script,這三個概念之於 Weex 就如 HTML,CSS,JavaScript 之於 Web。
Weex 代碼由 <template>、<style>、<script> 三個部分構成。
- <template>:必須的,使用 HTML 語法描述頁面結構,內容由多個標簽組成,不同的標簽代表不同的組件。
- <style>:可選的,使用 CSS 語法描述頁面的具體展現形式。
- <script>:可選的,使用 JavaScript 描述頁面中的數據和頁面的行為,Weex 中的數據定義也在 <script> 中進行。
每個 Weex 頁面最頂層的節點,我們稱為根節點。下面是目前我們支持的三種根節點:
- <div>:普通根節點,有確定的尺寸,不可滾動。
- <scroller>:可滾動根節點,適用於需要全頁滾動的場景。
- <list>:列表根節點,適用於其中包含重復的子元素的列表場景。
目前 Weex 僅支持以上三種根節點。
<script> 描述頁面中的數據和頁面的行為,代碼遵循 JavaScript (ES5) 語法 (目前 iOS 端和瀏覽器端取決於內置 JavaScript 引擎對 ES 版本的支持情況
上面 <script> 標簽中定義了被賦值給 module.exports 的對象,這個對象其實就是一個 ViewModel 選項,
定義組件是通過一組選項來描述一個組件。這組選項總是被賦值給 <script> 標簽中的 module.exports 。
module.exports = {
// a set of options here
}
data 選項是一個函數,它返回這個視圖模型可監聽的數據對象。而 methods 是一個映射,其中包含所有視圖模型的方法。
每個 data 或 method 屬性將被代理到視圖模型實例中。所以,你能通過 this.x 讀寫數據,或者通過 this.doThis() 調用方法。
events 選項允許你在視圖模型被創建時注冊自定義事件。然后,它會監聽這些類型的事件,並通過函數類型的值處理它們。
Weex 會把一個事件對象作為第一個參數傳遞給其綁定的事件,這個事件對象在 e.detail 中包含事件數據。
組件定義
定義組件是通過一組選項來描述一個組件。這組選項總是被賦值給 <script> 標簽中的 module.exports
data 選項是一個函數,它返回這個視圖模型可監聽的數據對象。而 methods 是一個映射,其中包含所有視圖模型的方法。
events 選項允許你在視圖模型被創建時注冊自定義事件。然后,它會監聽這些類型的事件,並通過函數類型的值處理它們。
生命周期
module.exports = {
data: ...,
methods: ...,
init: function () {
console.log('ViewModel constructor begins')
console.log('在初始化內部變量,並且添加了事件功能后被觸發');
},
created: function () {
console.log('Data observation finished')
console.log('完成數據綁定之后,模板編譯之前被觸發');
},
ready: function () {
console.log('Virtual DOM finished')
console.log('模板已經編譯並且生成了 Virtual DOM 之后被觸發');
},
destroyed: function () { console.log('在頁面被銷毀時調用'); },
...
}
Weex 視圖模型現在支持生命周期內的鈎子函數,這些鈎子函數能被寫為組件選項:
- init: 在視圖模型的構造函數開始調用時激活;
- created: 當視圖模型監聽默認數據,但還未編譯模板時激活;
- ready: 當視圖模型監聽默認數據並且編譯模板生成虛擬DOM后被激活。
init內一般用於初始化一些內部變量,綁定一些自定義事件,這時還沒有數據綁定,沒有創建vdom,所以不能通過this獲取到data和methods,也不能獲取vdom的節點
created 完成了數據綁定 ,但還未開始編譯模板,可以通過this獲取data和methods,但不能獲取vdom的節點
ready表示渲染完成 ,從子組件往上觸發
destroyed 組件銷毀,比如頁面跳轉,從子組件開始往上觸發

注意:當 methods、events 或生命周期方法作為參數傳遞給別的函數時,務必確認函數執行時的上下文符合您的預期,例如:
module.exports = {
data: function () {
return {x: 1, y: 2}
},
ready: function () {
// `undefined`
// 因為上下文發生了變化
this.foo(this.bar)
// `1`
// 正確綁定上下文之后可以得到預期的值
this.foo(this.bar.bind(this))
},
methods: {
foo: function (fn) {
return fn()
},
bar: function () {
return this.x
}
}
}
Weex使用 mustache 的語法 ({{...}}) 來對 <template> 中的模板和 <script> 里的數據進行綁定. 一旦數據額模板綁定了, 數據上的修改會實時的在模板內容中生效。
注意事項:data、methods、computed 中的字段是不能相互重復的,因為它們都會通過組件實例的this 訪問到。
事件綁定:on...
以 on... 開頭的就是用於綁定事件的特性,特性名中 on 之后的部分就是事件的類型,特性的值就是處理該事件的函數名。函數名外不需要添加 mustache 語法中的大括號。
在 Weex 頁面上樣式有兩種形式:
- <template> 中的 style 特性
- <style> 樣式表
append
append 特性定義了當前組件的子組件:
- 以一整棵樹的方式一次性添加到視圖中 (append="tree"),還是
- 每個子組件都產生一次單獨的添加到視圖的指令 (append="node")
自定義組件
經常我們會發現 Weex 的 <template> 中有很多可復用的部分,這時候我們可以將其封裝成上層的自定義組件並重用。例如我們可以直接創建一個名為 foo.we 的文件,<foo> 就是自定義組件的組件名稱:
組件嵌套
自定義組件也支持嵌套,如下:
<!-- somepath/foo.we -->
<template>
<div style="flex-direction: row;">
<image src="{{image}}"></image>
<text>{{title}}</text>
</div>
</template>
<script>
module.exports = {
data: {
// These keys must be declared explicitly here
// or data-binding will not work from its parent.
title: null,
image: null
}
}
</script>
<!-- samepath/foo.list.we -->
<template>
<div>
<text>{{description}}</text>
<foo repeat="item in list" title="{{item.text}}" image="{{item.img}}"></foo>
</div>
</template>
<script>
module.exports = {
data: {
description: '',
// This key must be declared explicitly here
// or data-binding will not work from its parent.
list: []
}
}
</script>
<!-- samepath/main.we -->
<template>
<foo-list list="{{list}}"></foo-list>
</template>
<script>
module.exports = {
data: {
list: [
{text: '...', img: '...'},
{text: '...', img: '...'},
{text: '...', img: '...'},
...
]
}
}
</script>
這里的main.we嵌套了<foo-list>,<foo-list>嵌套了<foo>,同時組件可以正常的配合數據綁定、repeat特性等使用。
更多子組件的定義和書寫方式
除了在主文件同目錄下創建和被封裝組件同名的 we 文件之外,Weex 還支持另外幾種子組件的書寫方式:
- 在 <script> 中通過 require 其它目錄的 we 文件定義同名組件
- 在主文件下新增 <element name="xxx"> 標簽,name 特性的值為新創建的組件名,其 <element> 內部的內容是定義該組件的代碼
比如:
<!-- path-a/main.we -->
<element name="foo">
<text>Foo</text>
</element>
<template>
<div>
<foo></foo>
<bar></bar>
</div>
</template>
<script>
require('path-b/bar.we')
</script>
<!-- path-b/bar.we -->
<template>
<text>Bar</text>
</template>
這樣的話,path-a/main.we 最終展示的結果是“Foo”和“Bar”兩段文本。
注意事項
- 組件各自的 <style> 是相互獨立的,不會擔心不同組件中相同的 class name 相互干擾。
- 如果自定義組件在父組件中有 id 特性,則可以在父組件上下文中通過 this.$vm(id) 接口來訪問該自定義組件的上下文,也可以通過 this.$el(id) 來找到其背后真實的原生組件。更多詳見獲取子組件信息
- 自定義組件之間通信的問題可以參考組件間通信
- 不論通過父組件把數據傳遞進來還是在當前組件內部對數據發起修改,只有在組件的 data 選項中明確寫明的字段才會被正常的監聽。
獲取自定義子組件的上下文
另外,我們還可以通過this.$vm(id) 方法可以訪問自定義子組件的上下文:
另外,我們還可以通過this.$vm(id)方法可以訪問自定義子組件的上下文:
<element name="foo">
<template>
<div style="flex-direction: row;">
<text>{{title}}</text>
</div>
</template>
<script>
module.exports = {
data: {
title: null
},
methods: {
setTitle: function (text) {
this.title = text
}
}
}
</script>
</element>
<template>
<div>
<foo id="sub" title="Hello"></foo>
<text onclick="update">Click Me to Update</text>
</div>
</template>
<script>
module.exports = {
methods: {
update: function (e) {
this.$vm('sub').setTitle('Updated')
}
}
}
</script>
獲取子組件信息
在 Weex 中,您可以通過在特定的子組件上設置id特性,以此在該<template>內唯一標識這個組件。
獲取子組件
您可以在父組件上下文中使用this.$el(id)來找到該組件,以運用scrollToElement()為例:
<template>
<div>
<text id="goto-top">Top</text>
<div style="height: 10000; "></div>
<text onclick="back2Top">Back to Top</text>
</div>
</template>
<script>
var dom = require('@weex-module/dom')
module.exports = {
methods: {
back2Top: function () {
var el = this.$el('goto-top')
dom.scrollToElement(el, { offset: 10 })
}
}
}
</script>
組件間通信
自定義事件
Weex 支持自定義事件,這里有兩個相關的設計:1,監聽自定義事件;2,創建自定義事件。
監聽自定義事件
每個 Weex 的 ViewModel 都支持 this.$on(type, handler) 和 this.$off(type[, handler]) 的 API。type 是監聽的自定義事件類型,handler 是事件處理函數。
當 handler 被觸發時,會有一個事件對象 event 作為第一個參數被傳入,事件對象的數據格式基於事件機制中提到的事件描述對象。
創建自定義事件
每個 Weex 的 ViewModel 都支持 this.$emit(type, detail) 的 API,可以在當前 ViewModel 中產生一個自定義事件。type 是自定義事件的類型,detail 則是一個對該事件細節補充描述的 JSON 對象,會以 event.detail 的形式出現在處理此事件的函數中。
從子組件向父組件通信
首先父組件要監聽特定類型的自定義事件,而子組件可以使用 this._parent 找到父組件,然后再調用 this._parent.$emit(type, detail) 方法,即可實現自下而上的通信。例如:
從父組件向子組件通信
同理,首先子組件要監聽特定類型的自定義事件,而父組件可以使用 this.$vm(id) “訪問自定義子組件的上下文”,然后再調用 this.$vm(id).$emit(type, detail) 方法,即可實現自上而下的通信。例如:
頁面整體配置
在 Weex 中,你可以通過一些特殊的 <script> 進行頁面整體配置。
注意事項:這些配置會代表頁面整體,所以寫在自定義子組件中是無效的,只有寫在頂級 ViewModel 的 <sctipt> 中才會生效。
先舉個例子:
<!-- definition of sub components -->
<element name="sub-component-a">...</element>
<element name="sub-component-b">...</element>
<element name="sub-component-c">...</element>
<!-- definition of top-level component -->
<template>...</template>
<style></style>
<script>
module.exports = {
data: { x: 1, y: 2 }
}
</script>
<!-- config and data -->
<script type="config">
downgrade: {
ios: {
os: '9', // all of 9.x.x
app: '~5.3.2',
framework: '^1.3', // all of 1.3.x
deviceModel: ['AAAA', 'BBBB']
},
android: {
os: '*', // all of version
app: '^5',
framework: '',
deviceModel: ''
}
}
</script>
<script type="data">
{ y: 200 }
</script>
<script type="config">
開發者可以在頂級 ViewModel 中加入這樣一段 <script>,以 JSON 格式描述頁面整體的配置信息。
目前支持的配置信息只有 downgrade:用來從平台、應用等維度描述頁面的降級規則。這樣設計對於產品迭代最大的幫助是可以在高版本中使用 Weex,而在低版本中使用之前已有的渲染方式,這部分控制降級的細節需要 native 接入的時候進行相應的識別和具體操作。
未來這里會有更多的配置項出現在這里。
<script type="data">
開發者可以在頂級 ViewModel 中加入這樣一段 <script>,以 JSON 格式額外配置頂級 ViewModel 的數據,它會覆蓋頂級 ViewModel 數據中相應的字段。比如上述例子中,最終的頂級 ViewModel 中的數據為 { x: 1, y: 200 }。
