微信小程序自定义组件详解
自定義組件能夠幫我們更好的復用代碼和重構簡化代碼復雜度。一起來學習一下小程序自定義組件的內容吧。
從小程序基礎庫版本 1.6.3 開始,小程序支持簡潔的組件化編程。所有自定義組件相關特性都需要基礎庫版本 1.6.3 或更高。
開發者可以將頁面內的功能模塊抽象成自定義組件,以便在不同的頁面中重復使用;也可以將復雜的頁面拆分成多個低耦合的模塊,有助于代碼維護。自定義組件在使用時與基礎組件非常相似
總覽
一、Component概念
Component像頁面一樣由wxml、wxss、js和json4個文件組成,且需要把這4個文件放在同一個目錄中。與頁面不一樣的是,Component中的構造函數(也可以稱構造器)是Component({}),而頁面中的構造函數是Page({})。要編寫一個自定義組件,首先需要在 json 文件中進行自定義組件聲明(將component字段設為true可這一組文件設為自定義組件):
{
"component": true
}
slot
Component的slot(slot意思是插槽),主要是讓你在外部的wxml可以自由的在你的Component的wxml里插入模塊。默認情況下,一個組件的wxml只可能有一個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>
組件樣式編寫注意事項
- 組件和引用組件的頁面不能使用id選擇器(#a)、屬性選擇器([a])和標簽名選擇器,請改用class選擇器。
- 組件和引用組件的頁面中使用后代選擇器(.a .b)在一些極端情況下會有非預期的表現,如遇,請避免使用。
- 子元素選擇器(.a>.b)只能用于 view 組件與其子節點之間,用于其他組件可能導致非預期的情況。
- 繼承樣式,如 font 、 color ,會從組件外繼承到組件內。
- 除繼承樣式外, app.wxss 中的樣式、組件所在頁面的的樣式對自定義組件無效。
#a { } /* 在組件中不能使用 */
[a] { } /* 在組件中不能使用 */
button { } /* 在組件中不能使用 */
.a > .b { } /* 除非 .a 是 view 組件節點,否則不一定會生效 */
外部樣式類
使用外部樣式類可以讓組件使用指定的組件外樣式類,如果希望組件外樣式類能夠完全影響組件內部,可以將組件構造器中的options.addGlobalClass字段置為true。
/* 組件 custom-component.js */
Component({
externalClasses: ['my-class']
})
<!-- 組件 custom-component.wxml --> <custom-component class="my-class">這段文本的顏色由組件外的 class 決定</custom-component>
/* 組件外的樣式定義 */
.red-text {
color: red;
}
創建一個組件
一個組件需要包括json、wxml、wxss、js四個文件組成,下面我們先看看一個簡單的入門:
<!--components/component/component.wxml-->
<view class="inner">
{{innerText}}
</view>
<slot></slot>
編寫JS文件,組件的屬性值和內部數據將被用于組件 wxml 的渲染,其中,屬性值是可由組件外部傳入的
// components/component/component.js
Component({
/**
* 組件的屬性列表
*/
properties: {
innerText: {
type: String,
value: 'hello world'
},
myProperties:String
},
/**
* 組件的初始數據
*/
data: {
},
/**
* 組件的方法列表
*/
methods: {
}
})
設置字體的顏色
/* components/component/component.wxss */
.inner{color: red;}
完成對組件的初始化,包括設置屬性列表,初始化數據,以及設置相關的方法。
使用自定義組件
使用已注冊的自定義組件前,首先要在頁面的 json 文件中進行引用聲明。此時需要提供每個自定義組件的標簽名和對應的自定義組件文件路徑:
{
"usingComponents": {
"component": "/components/component/component"
}
}
在page頁面下添加聲明過的自定義組件:
<component></component>
<view>
<component>
<!-- 這部分內容將被放置在組件 <slot> 的位置上 -->
<view>這里是插入到組件slot中的內容</view>
</component>
</view>
上方的是一個最簡單的自定義組件。
注意事項:
1.對于基礎庫的1.5.x版本, 1.5.7 也有部分自定義組件支持。
2.因為WXML節點標簽名只能是小寫字母、中劃線和下劃線的組合,所以自定義組件的標簽名也只能包含這些字符。
3.自定義組件也是可以引用自定義組件的,引用方法類似于頁面引用自定義組件的方式(使用 usingComponents 字段)。
4.自定義組件和使用自定義組件的頁面所在項目根目錄名不能以“wx-”為前綴,否則會報錯。
5.舊版本的基礎庫不支持自定義組件,此時,引用自定義組件的節點會變為默認的空節點。
Component構造器
使用component構造器,進行構造。 該構造函數用于定義組件。調用Component函數能指定組件的數據,屬性和方法。來看看這個完整的列表代碼含義:
Component({
behaviors: [],
properties: {
myProperty: { // 屬性名
type: String, // 類型(必填),目前接受的類型包括:String, Number, Boolean, Object, Array, null(表示任意類型)
value: '', // 屬性初始值(可選),如果未指定則會根據類型選擇一個
observer: function (newVal, oldVal) {
this._propertyChange(newVal, oldVal);
} // 屬性被改變時執行的函數(可選),也可以寫成在methods段中定義的方法名字符串, 如:'_propertyChange'
},
myProperty2: String // 簡化的定義方式
},
data: {
A: [{
B: 'init data.A[0].B'
}]
}, // 私有數據,可用于模版渲染
lifetimes: {
// 生命周期函數,可以為函數,或一個在methods段中定義的方法名
attached: function () { },
moved: function () { },
detached: function () { },
},
// 生命周期函數,可以為函數,或一個在methods段中定義的方法名
attached: function () { }, // 此處attached的聲明會被lifetimes字段中的聲明覆蓋
ready: function() { },
pageLifetimes: {
// 組件所在頁面的生命周期函數
show: function () { },
},
methods: {
onMyButtonTap: function () {
this.setData({
// 更新屬性和數據的方法與更新頁面數據的方法類似
myProperty: 'Test'
})
},
_myPrivateMethod: function () {
// 內部方法建議以下劃線開頭
this.replaceDataOnPath(['A', 0, 'B'], 'myPrivateData') // 這里將 data.A[0].B 設為 'myPrivateData'
this.applyDataUpdates()
},
_propertyChange: function (newVal, oldVal) {
console.log(newVal);
console.log(oldVal);
}
}
})
組件與數據通信
組件間的通信方法有以下幾種:
- WXML 數據綁定:用于父組件向子組件的指定屬性設置數據,僅能設置 JSON 兼容數據(自基礎庫版本 2.0.9 開始,還可以在數據中包含函數)。具體在 組件模板和樣式 章節中介紹。
- 事件:用于子組件向父組件傳遞數據,可以傳遞任意數據。
- 如果以上兩種方式不足以滿足需要,父組件還可以通過?this.selectComponent?方法獲取子組件實例對象,這樣就可以直接訪問組件的任意數據和方法。
通過在頁面中給組件加了一個id值,這樣子我們就能查到組件的方法了。
<compontent id="modal"></compontent>
/*js*/
var modal = this.setlectComponet('#modal');
這樣子就能在外面調用組件里面的任意數據和方法了。
- properties:主頁面傳入數據到組件,相當于vue的props,是傳入外部數據的入口。
- data:則用于組件的內部數據變化,外部數據沒法初始化
在 properties 定義段中,屬性名采用駝峰寫法(propertyName);在 wxml 中,指定屬性值時則對應使用連字符寫法(component-tag-name property-name="attr value"),應用于數據綁定時采用駝峰寫法(attr="{{propertyName}}")
傳入的數據,不管是簡單數據類型,還是引用類型,都如同值復制一樣
方法函數調用
methods:需要在組件中調用的方法,都寫在這個對象里面。跟Page中的對象里面的方法同級。
生命周期:可單獨某個生命周期放在Components下(舊式的定義方式,可以保持對 <2.2.3 版本基礎庫的兼容),也可以放在lifetimes,如果兩個地方有同名生命周期,則lifetimes里面的方法會覆蓋前者。
Component({
lifetimes: {
attached: function() {
// 在組件實例進入頁面節點樹時執行
},
detached: function() {
// 在組件實例被從頁面節點樹移除時執行
},
},
// 以下是舊式的定義方式,可以保持對 <2.2.3 版本基礎庫的兼容
attached: function() {
// 在組件實例進入頁面節點樹時執行
},
detached: function() {
// 在組件實例被從頁面節點樹移除時執行
},
// ...
})
組件所在的生命周期
還有一些特殊的生命周期,它們并非與組件有很強的關聯,但有時組件需要獲知,以便組件內部處理。這樣的生命周期稱為“組件所在頁面的生命周期”,在 pageLifetimes 定義段中定義。其中可用的生命周期包括:
生成的組件實例可以在組件的方法、生命周期函數和屬性 observer 中通過 this 訪問。組件包含一些通用屬性和方法
image.png
組件傳出數據到主頁面
組件間交互的主要形式是自定義事件。
組件通過 this.triggerEvent() 觸發自定義事件,主頁面在組件上 bind:myevent="onMyEvent" 來接收自定義事件。
其中,this.triggerEvent() 方法接收自定義事件名稱外,還接收兩個對象,eventDetail 和 eventOptions。
<!-- 在自定義組件中 --> <button bindtap="onTap">點擊這個按鈕將觸發“myevent”事件</button>
Component({
properties: {}
methods: {
// 子組件觸發自定義事件
ontap () {
// 所有要帶到主頁面的數據,都裝在eventDetail里面
var eventDetail = {
name:'sssssssss',
test:[1,2,3]
}
// 觸發事件的選項 bubbles是否冒泡,composed是否可穿越組件邊界,capturePhase 是否有捕獲階段
var eventOption = {
composed: true
}
this.triggerEvent('myevent', eventDetail, eventOption)
}
}
})
觸發的事件包括:
監聽事件
自定義組件可以觸發任意的事件,引用組件的頁面可以監聽這些事件。監聽自定義組件事件的方法與監聽基礎組件事件的方法完全一致:
在Page事件中監聽組件中傳遞過來的值。
Page({
onMyEvent: function(e){
e.detail // 自定義組件觸發事件時提供的detail對象
}
})
behaviors
behaviors 是用于組件間代碼共享的特性,類似于一些編程語言中的“mixins”或“traits”。
每個 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(){}
}
})
字段的覆蓋和組合規則
組件和它引用的 behavior 中可以包含同名的字段,對這些字段的處理方法如下:
如果有同名的屬性或方法,組件本身的屬性或方法會覆蓋 behavior 中的屬性或方法,如果引用了多個 behavior ,在定義段中靠后 behavior 中的屬性或方法會覆蓋靠前的屬性或方法;
如果有同名的數據字段,如果數據是對象類型,會進行對象合并,如果是非對象類型則會進行相互覆蓋;
生命周期函數不會相互覆蓋,而是在對應觸發時機被逐個調用。如果同一個 behavior 被一個組件多次引用,它定義的生命周期函數只會被執行一次。
內置behavior
組件間關系
<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生命周期之后
}
}
}
})
更多:
- 關聯一類組件
- 抽象節點
- 自定義組件擴展
- 開發第三方自定義組件
制作一個彈窗組件
https://developers.weixin.qq.com/s/M55masmW764P
PPT:https://ppt.baomitu.com/d/baf2b116
總結
以上是生活随笔為你收集整理的微信小程序自定义组件详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自卑症状
- 下一篇: 关于孟子的名言名句223个