ylbtech-小程序:自定義組件 |
1. 自定義組件返回頂部 |
從小程序基礎庫版本 1.6.3 開始,小程序支持簡潔的組件化編程。html
開發者能夠將頁面內的功能模塊抽象成自定義組件,以便在不一樣的頁面中重複使用;也能夠將複雜的頁面拆分紅多個低耦合的模塊,有助於代碼維護。自定義組件在使用時與基礎組件很是類似。node
相似於頁面,一個自定義組件由 json
wxml
wxss
js
4個文件組成。要編寫一個自定義組件,首先須要在 json
文件中進行自定義組件聲明(將 component
字段設爲 true
可這一組文件設爲自定義組件):編程
{
"component": true
}
同時,還要在 wxml
文件中編寫組件模版,在 wxss
文件中加入組件樣式,它們的寫法與頁面的寫法相似。具體細節和注意事項參見 組件模版和樣式 。json
代碼示例:小程序
<!-- 這是自定義組件的內部WXML結構 --> <view class="inner"> {{innerText}} </view> <slot></slot>
/* 這裏的樣式只應用於這個自定義組件 */
.inner {
color: red;
}
注意:在組件wxss中不該使用ID選擇器、屬性選擇器和標籤名選擇器。api
在自定義組件的 js
文件中,須要使用 Component()
來註冊組件,並提供組件的屬性定義、內部數據和自定義方法。數組
組件的屬性值和內部數據將被用於組件 wxml
的渲染,其中,屬性值是可由組件外部傳入的。更多細節參見 Component構造器 。app
代碼示例:xss
Component({
properties: {
// 這裏定義了innerText屬性,屬性值能夠在組件使用時指定
innerText: {
type: String,
value: 'default value',
}
},
data: {
// 這裏是一些組件內部數據
someData: {}
},
methods: {
// 這裏是一個自定義方法
customMethod: function(){}
}
})
使用已註冊的自定義組件前,首先要在頁面的 json
文件中進行引用聲明。此時須要提供每一個自定義組件的標籤名和對應的自定義組件文件路徑:編程語言
{
"usingComponents": {
"component-tag-name": "path/to/the/custom/component"
}
}
這樣,在頁面的 wxml
中就能夠像使用基礎組件同樣使用自定義組件。節點名即自定義組件的標籤名,節點屬性即傳遞給組件的屬性值。
代碼示例:
<view> <!-- 如下是對一個自定義組件的引用 --> <component-tag-name inner-text="Some text"></component-tag-name> </view>
自定義組件的 wxml
節點結構在與數據結合以後,將被插入到引用位置內。
Tips:
usingComponents
字段)。2. 組件模版和樣式返回頂部 |
相似於頁面,自定義組件擁有本身的 wxml
模版和 wxss
樣式。
組件模版的寫法與頁面模板相同。組件模版與組件數據結合後生成的節點樹,將被插入到組件的引用位置上。
在組件模板中能夠提供一個 <slot>
節點,用於承載組件引用時提供的子節點。
代碼示例:
<!-- 組件模板 --> <view class="wrapper"> <view>這裏是組件的內部節點</view> <slot></slot> </view>
<!-- 引用組件的頁面模版 --> <view> <component-tag-name> <!-- 這部份內容將被放置在組件 <slot> 的位置上 --> <view>這裏是插入到組件slot中的內容</view> </component-tag-name> </view>
在組件的wxml中能夠包含 slot
節點,用於承載組件使用者提供的wxml結構。
默認狀況下,一個組件的wxml中只能有一個slot。須要使用多slot時,能夠在組件js中聲明啓用。
Component({
options: {
multipleSlots: true // 在組件定義時的選項中啓用多slot支持
},
properties: { /* ... */ },
methods: { /* ... */ }
})
此時,能夠在這個組件的wxml中使用多個slot,以不一樣的 name
來區分。
<!-- 組件模板 --> <view class="wrapper"> <slot name="before"></slot> <view>這裏是組件的內部細節</view> <slot name="after"></slot> </view>
使用時,用 slot
屬性來將節點插入到不一樣的slot上。
<!-- 引用組件的頁面模版 --> <view> <component-tag-name> <!-- 這部份內容將被放置在組件 <slot name="before"> 的位置上 --> <view slot="before">這裏是插入到組件slot name="before"中的內容</view> <!-- 這部份內容將被放置在組件 <slot name="after"> 的位置上 --> <view slot="after">這裏是插入到組件slot name="after"中的內容</view> </component-tag-name> </view>
組件對應 wxss
文件的樣式,只對組件wxml內的節點生效。編寫組件樣式時,須要注意如下幾點:
#a
)、屬性選擇器([a]
)和標籤名選擇器,請改用class選擇器。.a .b
)在一些極端狀況下會有非預期的表現,如遇,請避免使用。.a>.b
)只能用於 view
組件與其子節點之間,用於其餘組件可能致使非預期的狀況。font
、 color
,會從組件外繼承到組件內。app.wxss
中的樣式、組件所在頁面的的樣式對自定義組件無效。#a { } /* 在組件中不能使用 */
[a] { } /* 在組件中不能使用 */
button { } /* 在組件中不能使用 */
.a > .b { } /* 除非 .a 是 view 組件節點,不然不必定會生效 */
除此之外,組件能夠指定它所在節點的默認樣式,使用 :host
選擇器(須要 1.7.2 或更高版本的開發者工具支持)。
代碼示例:
/* 組件 custom-component.wxss */
:host {
color: yellow;
}
:host(.dark) {
color: black;
}
<!-- 頁面的 WXML --> <custom-component>這段文本是黃色的</custom-component> <custom-component class="dark">這段文本是黑色的</custom-component>
3. Component構造器返回頂部 |
Component構造器可用於定義組件,調用Component構造器時能夠指定組件的屬性、數據、方法等。
定義段 | 類型 | 是否必填 | 描述 |
---|---|---|---|
properties | Object Map | 否 | 組件的對外屬性,是屬性名到屬性設置的映射表,屬性設置中可包含三個字段, type 表示屬性類型、 value 表示屬性初始值、 observer 表示屬性值被更改時的響應函數 |
data | Object | 否 | 組件的內部數據,和 properties 一同用於組件的模版渲染 |
methods | Object | 否 | 組件的方法,包括事件響應函數和任意的自定義方法,關於事件響應函數的使用,參見 組件事件 |
behaviors | String Array | 否 | 相似於mixins和traits的組件間代碼複用機制,參見 behaviors |
created | Function | 否 | 組件生命週期函數,在組件實例進入頁面節點樹時執行,注意此時不能調用 setData |
attached | Function | 否 | 組件生命週期函數,在組件實例進入頁面節點樹時執行 |
ready | Function | 否 | 組件生命週期函數,在組件佈局完成後執行,此時能夠獲取節點信息(使用 SelectorQuery ) |
moved | Function | 否 | 組件生命週期函數,在組件實例被移動到節點樹另外一個位置時執行 |
detached | Function | 否 | 組件生命週期函數,在組件實例被從頁面節點樹移除時執行 |
relations | Object | 否 | 組件間關係定義,參見 組件間關係 |
options | Object Map | 否 | 一些組件選項,請參見文檔其餘部分的說明 |
生成的組件實例能夠在組件的方法、生命週期函數和屬性 observer
中經過 this
訪問。組件包含一些通用屬性和方法。
屬性名 | 類型 | 描述 |
---|---|---|
is | String | 組件的文件路徑 |
id | String | 節點id |
dataset | String | 節點dataset |
data | Object | 組件數據,包括內部數據和屬性值 |
方法名 | 參數 | 描述 |
---|---|---|
setData | Object newData |
設置data並執行視圖層渲染 |
hasBehavior | Object behavior |
檢查組件是否具備 behavior (檢查時會遞歸檢查被直接或間接引入的全部behavior) |
triggerEvent | String name , Object detail , Object options |
觸發事件,參見 組件事件 |
createSelectorQuery | 建立一個 SelectorQuery 對象,選擇器選取範圍爲這個組件實例內 | |
selectComponent | String selector |
使用選擇器選擇組件實例節點,返回匹配到的第一個組件實例對象 |
selectAllComponents | String selector |
使用選擇器選擇組件實例節點,返回匹配到的所有組件實例對象組成的數組 |
getRelationNodes | String relationKey |
獲取全部這個關係對應的全部關聯節點,參見 組件間關係 |
代碼示例:
Component({
behaviors: [],
properties: {
myProperty: { // 屬性名
type: String, // 類型(必填),目前接受的類型包括:String, Number, Boolean, Object, Array, null(表示任意類型)
value: '' // 屬性初始值(可選),若是未指定則會根據類型選擇一個
observer: function(newVal, oldVal){} // 屬性被改變時執行的函數(可選),也能夠寫成在methods段中定義的方法名字符串
},
myProperty2: String // 簡化的定義方式
},
data: {}, // 私有數據,可用於模版渲染
// 生命週期函數,能夠爲函數,或一個在methods段中定義的方法名
attached: function(){},
moved: function(){},
detached: function(){},
methods: {
onMyButtonTap: function(){
this.setData({
// 更新屬性和數據的方法與更新頁面數據的方法相似
})
},
_myPrivateMethod: function(){
// 內部方法建議如下劃線開頭
this.replaceDataOnPath(['A', 0, 'B'], 'myPrivateData') // 這裏將 data.A[0].B 設爲 'myPrivateData'
this.applyDataUpdates()
}
}
})
注意:在 properties
定義段中,屬性名採用駝峯寫法(propertyName
);在 wxml
中,指定屬性值時則對應使用連字符寫法(component-tag-name property-name="attr value"
),應用於數據綁定時採用駝峯寫法(attr="{{propertyName}}"
)。
Tips:
Component
構造器構造的組件也能夠做爲頁面使用。this.data
能夠獲取內部數據和屬性值,但不要直接修改它們,應使用 setData
修改。this
訪問到。dataXyz
這樣的形式,由於在 WXML 中, data-xyz=""
會被做爲節點 dataset 來處理,而不是組件屬性。4. 組件事件返回頂部 |
事件系統是組件間交互的主要形式。自定義組件能夠觸發任意的事件,引用組件的頁面能夠監聽這些事件。關於事件的基本概念和用法,參見 事件 。
監聽自定義組件事件的方法與監聽基礎組件事件的方法徹底一致:
代碼示例:
<!-- 當自定義組件觸發「myevent」事件時,調用「onMyEvent」方法 --> <component-tag-name bindmyevent="onMyEvent" /> <!-- 或者能夠寫成 --> <component-tag-name bind:myevent="onMyEvent" />
Page({
onMyEvent: function(e){
e.detail // 自定義組件觸發事件時提供的detail對象
}
})
自定義組件觸發事件時,須要使用 triggerEvent
方法,指定事件名、detail對象和事件選項:
代碼示例:
<!-- 在自定義組件中 --> <button bindtap="onTap">點擊這個按鈕將觸發「myevent」事件</button>
Component({
properties: {}
methods: {
onTap: function(){
var myEventDetail = {} // detail對象,提供給事件監聽函數
var myEventOption = {} // 觸發事件的選項
this.triggerEvent('myevent', myEventDetail, myEventOption)
}
}
})
觸發事件的選項包括:
選項名 | 類型 | 是否必填 | 默認值 | 描述 |
---|---|---|---|---|
bubbles | Boolean | 否 | false | 事件是否冒泡 |
composed | Boolean | 否 | false | 事件是否能夠穿越組件邊界,爲false時,事件將只能在引用組件的節點樹上觸發,不進入其餘任何組件內部 |
capturePhase | Boolean | 否 | false | 事件是否擁有捕獲階段 |
關於冒泡和捕獲階段的概念,請閱讀 事件 章節中的相關說明。
代碼示例:
// 頁面 page.wxml <another-component bindcustomevent="pageEventListener1"> <my-component bindcustomevent="pageEventListener2"></my-component> </another-component>
// 組件 another-component.wxml <view bindcustomevent="anotherEventListener"> <slot /> </view>
// 組件 my-component.wxml <view bindcustomevent="myEventListener"> <slot /> </view>
// 組件 my-component.js
Component({
methods: {
onTap: function(){
this.triggerEvent('customevent', {}) // 只會觸發 pageEventListener2
this.triggerEvent('customevent', {}, { bubbles: true }) // 會依次觸發 pageEventListener2 、 pageEventListener1
this.triggerEvent('customevent', {}, { bubbles: true, composed: true }) // 會依次觸發 pageEventListener2 、 anotherEventListener 、 pageEventListener1
}
}
})
5. behaviors返回頂部 |
behaviors
是用於組件間代碼共享的特性,相似於一些編程語言中的「mixins」或「traits」。
每一個 behavior
能夠包含一組屬性、數據、生命週期函數和方法,組件引用它時,它的屬性、數據和方法會被合併到組件中,生命週期函數也會在對應時機被調用。每一個組件能夠引用多個 behavior
。 behavior
也能夠引用其餘 behavior
。
behavior
須要使用 Behavior()
構造器定義。
代碼示例:
// my-behavior.js
module.exports = Behavior({
behaviors: [],
properties: {
myBehaviorProperty: {
type: String
}
},
data: {
myBehaviorData: {}
},
attached: function(){},
methods: {
myBehaviorMethod: function(){}
}
})
組件引用時,在 behaviors
定義段中將它們逐個列出便可。
代碼示例:
// my-component.js
var myBehavior = require('my-behavior')
Component({
behaviors: [myBehavior],
properties: {
myProperty: {
type: String
}
},
data: {
myData: {}
},
attached: function(){},
methods: {
myMethod: function(){}
}
})
在上例中, my-component
組件定義中加入了 my-behavior
,而 my-behavior
中包含有 myBehaviorProperty
屬性、 myBehaviorData
數據字段、 myBehaviorMethod
方法和一個 attached
生命週期函數。這將使得 my-component
中最終包含 myBehaviorProperty
、 myProperty
兩個屬性, myBehaviorData
、 myData
兩個數據字段,和 myBehaviorMethod
、 myMethod
兩個方法。當組件觸發 attached
生命週期時,會依次觸發 my-behavior
中的 attached
生命週期函數和 my-component
中的 attached
生命週期函數。
組件和它引用的 behavior
中能夠包含同名的字段,對這些字段的處理方法以下:
behavior
中的屬性或方法,若是引用了多個 behavior
,在定義段中靠後 behavior
中的屬性或方法會覆蓋靠前的屬性或方法;behavior
被一個組件屢次引用,它定義的生命週期函數只會被執行一次。自定義組件能夠經過引用內置的 behavior
來得到內置組件的一些行爲。
代碼示例:
Component({
behaviors: ['wx://form-field']
})
在上例中, wx://form-field
表明一個內置 behavior
,它使得這個自定義組件有相似於表單控件的行爲。
內置 behavior
每每會爲組件添加一些屬性。在沒有特殊說明時,組件能夠覆蓋這些屬性來改變它的 type
或添加 observer
。
使自定義組件有相似於表單控件的行爲。 form 組件能夠識別這些自定義組件,並在 submit 事件中返回組件的字段名及其對應字段值。這將爲它添加如下兩個屬性。
屬性名 | 類型 | 描述 | 最低版本 |
---|---|---|---|
name | String | 在表單中的字段名 | 1.6.7 |
value | 任意 | 在表單中的字段值 | 1.6.7 |
6. 組件間關係返回頂部 |
有時須要實現這樣的組件:
<custom-ul> <custom-li> item 1 </custom-li> <custom-li> item 2 </custom-li> </custom-ul>
這個例子中, custom-ul
和 custom-li
都是自定義組件,它們有相互間的關係,相互間的通訊每每比較複雜。此時在組件定義時加入 relations
定義段,能夠解決這樣的問題。示例:
// path/to/custom-ul.js
Component({
relations: {
'./custom-li': {
type: 'child', // 關聯的目標節點應爲子節點
linked: function(target) {
// 每次有custom-li被插入時執行,target是該節點實例對象,觸發在該節點attached生命週期以後
},
linkChanged: function(target) {
// 每次有custom-li被移動後執行,target是該節點實例對象,觸發在該節點moved生命週期以後
},
unlinked: function(target) {
// 每次有custom-li被移除時執行,target是該節點實例對象,觸發在該節點detached生命週期以後
}
}
},
methods: {
_getAllLi: function(){
// 使用getRelationNodes能夠得到nodes數組,包含全部已關聯的custom-li,且是有序的
var nodes = this.getRelationNodes('path/to/custom-li')
}
},
ready: function(){
this._getAllLi()
}
})
// path/to/custom-li.js
Component({
relations: {
'./custom-ul': {
type: 'parent', // 關聯的目標節點應爲父節點
linked: function(target) {
// 每次被插入到custom-ul時執行,target是custom-ul節點實例對象,觸發在attached生命週期以後
},
linkChanged: function(target) {
// 每次被移動後執行,target是custom-ul節點實例對象,觸發在moved生命週期以後
},
unlinked: function(target) {
// 每次被移除時執行,target是custom-ul節點實例對象,觸發在detached生命週期以後
}
}
}
})
注意:必須在兩個組件定義中都加入relations定義,不然不會生效。
有時,須要關聯的是一類組件,如:
<custom-form> <view> input <custom-input></custom-input> </view> <custom-submit> submit </custom-submit> </custom-form>
custom-form
組件想要關聯 custom-input
和 custom-submit
兩個組件。此時,若是這兩個組件都有同一個behavior:
// path/to/custom-form-controls.js
module.exports = Behavior({
// ...
})
// path/to/custom-input.js
var customFormControls = require('./custom-form-controls')
Component({
behaviors: [customFormControls],
relations: {
'./custom-form': {
type: 'ancestor', // 關聯的目標節點應爲祖先節點
}
}
})
// path/to/custom-submit.js
var customFormControls = require('./custom-form-controls')
Component({
behaviors: [customFormControls],
relations: {
'./custom-form': {
type: 'ancestor', // 關聯的目標節點應爲祖先節點
}
}
})
則在 relations
關係定義中,可以使用這個behavior來代替組件路徑做爲關聯的目標節點:
// path/to/custom-form.js
var customFormControls = require('./custom-form-controls')
Component({
relations: {
'customFormControls': {
type: 'descendant', // 關聯的目標節點應爲子孫節點
target: customFormControls
}
}
})
relations
定義段包含目標組件路徑及其對應選項,可包含的選項見下表。
選項 | 類型 | 是否必填 | 描述 |
---|---|---|---|
type | String | 是 | 目標組件的相對關係,可選的值爲 parent 、 child 、 ancestor 、 descendant |
linked | Function | 否 | 關係生命週期函數,當關系被創建在頁面節點樹中時觸發,觸發時機在組件attached生命週期以後 |
linkChanged | Function | 否 | 關係生命週期函數,當關系在頁面節點樹中發生改變時觸發,觸發時機在組件moved生命週期以後 |
unlinked | Function | 否 | 關係生命週期函數,當關系脫離頁面節點樹時觸發,觸發時機在組件detached生命週期以後 |
target | String | 否 | 若是這一項被設置,則它表示關聯的目標節點所應具備的behavior,全部擁有這一behavior的組件節點都會被關聯 |
7.返回頂部 |
8.返回頂部 |
9.返回頂部 |
10.返回頂部 |
11.返回頂部 |
做者:ylbtech 出處:http://ylbtech.cnblogs.com/ 本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。 |