小程式檔案館——自定義元件

百度智慧小程式學院發表於2018-11-02

自定義元件簡介

百度智慧小程式為您提供了很多元件,供開發過程中使用,但是當已有的元件不能完全滿足您的需求時,該怎麼辦呢?當然是自己造一個~元件化開發一直是前端er們追求的優美的解決方案,本期檔案館,我們一起聊一下智慧小程式中的一個重要功能 -- 自定義元件。

自定義元件的原理

執行基本原理

自定義元件的具體建立方法,hello world示例,請參考智慧小程式官網: smartprogram.baidu.com/docs/develo…

瞭解原理之前,我們來看一下自定義元件中的js構造器:

Component({
    properties: {
    },
    data: {},
    attached: function () {},
    methods: {}
});
複製程式碼

以上包括了自定義元件的邏輯部分內容,開發者可以在Component構造器的各個生命週期回撥函式中,編寫自己的邏輯程式碼。

Component構造器中寫的自定義元件的原型,執行在小程式的邏輯層(jscore)中,並不與自己的swan模板執行在一起--swan模板執行在檢視層(webview)中。

所以,setData等操作,都是通過資料通訊,將要設定的資料傳遞到真正的檢視層,然後進行自定義元件的渲染。同理,所有的生命週期,也是當元件的模板在檢視層渲染完畢之後,傳遞迴邏輯層進行觸發的。

圖片

所以對於setData的呼叫,也如同頁面的setData一樣,需要謹慎呼叫。因為每一次setData都意味著一次jscore與webview的資料通訊。

類 or 累?

看過自定義元件基本使用方法的同學肯定知道,自定義元件內使用的樣式類是獨立空間,即: 元件模板中使用的css樣式類並不會應用上使用該自定義元件的頁面上的樣式類。

emmmmm,如果上面那句話把你繞暈了,我們來看一下例子:

// page.css
.page-class {
    background: #0f0;
    height: 100px;
    width: 100px;
}
複製程式碼
// page.swan
<view>
	<view class="page-class"></view>
	<mycomp></mycomp>
</view>
複製程式碼
// mycomp.swan
<view>
	<view class="page-class"></view>
</view>
複製程式碼

展示效果如下: ![圖片](agroup-bos.cdn.bcebos.com/51486aa7964… =200x370)

我們可以看到,雖然都是渲染到同一個頁面上,但是頁面上定義的樣式類,在元件中並沒有生效。

那麼同樣的,在元件中定義的類,也不會透出去,影響整個頁面,例:

// page.swan
<view>
	<view class="page-class"></view>
	<mycomp></mycomp>
</view>
複製程式碼
// mycomp.css
.page-class {
    background: #0f0;
    height: 100px;
    width: 100px;
}
複製程式碼
// mycomp.swan
<view>
	<view class="page-class"></view>
</view>
複製程式碼

效果如下: ![圖片](agroup-bos.cdn.bcebos.com/142f3e35f1e… =200x370)

那麼這個“隔離“是如何做到的呢? 我們仔細觀察一下自定義元件最後生成的模板,和樣式:

圖片

真相大白,原來是自定義元件中使用的樣式類,都被編譯增加了字首。這才使內外的類可以互相隔離。這種設計也有好處也有缺點,好處就不用再想之前用很多框架那樣自己去尋找解決方案(如:CSSinJS或css modules)自定義元件中直接整合了內建解決方案。壞處就是可能有些css上的使用限制,比如(摘自官網):

圖片
這塊也請讀者在開發過程中多注意。

TIPS: 關於css的解決方案,官方貌似還在持續優化,相信不久就可以迎來限制更小的集合了。

元件間的通訊

父子自定義元件之間,可以使用兩種方式進行通訊:

  • 利用自定義事件
  • 利用dispatch訊息

利用自定義事件

利用自定義事件在父元件中進行事件的繫結,在子元件中進行自定義事件的派發。 例:

// 父元件的swan中
<view>
	<component-tag-name bindmyevent="onMyEvent" />
</view>
複製程式碼
// 父元件的Component
Component({
    methods: {
		onMyEvent: function (e) {
            console.log('I got message:', e);
        }
	}
});
複製程式碼
// 子元件的Component
Component({
	attached: function () {
		this.triggerEvent('myevent', {message: 'you got?'});
	}
});
複製程式碼

dispatch訊息

通過 dispatch 方法,元件可以向元件樹的上層派發訊息。訊息將沿著元件樹向上傳遞,直到遇到第一個處理該訊息的元件,則停止。通過 messages 可以宣告元件要處理的訊息。messages 是一個物件,key 是訊息名稱,value 是訊息處理的函式,接收一個包含 target(派發訊息的元件) 和 value(訊息的值) 的引數物件。 (摘自san官網)

如果元件有訊息需要一直向上透傳,則可以使用這個方法,只要沒有元件元件攔截,訊息則會一直向上傳遞。

例:

// 根元件
Component({
    messages: {
        'childmessage': function (e) {
            console.log('childmessage', e);
        }
    }
});

// 父元件
Component({});

// 子元件
Component({
    created() {
        this.dispatch('childmessage', {
            name: 'swan'
        });
    }
});
複製程式碼

其中根元件中使用了父元件,父元件中使用了子元件。當子元件呼叫dispatch方法時,則會一直傳遞到根元件上(因為父元件並沒有message消費本次dispatch)。

至於父元件想通知子元件嘛,可以通過props的改變,來觸發子元件。

通過上述兩種方式均可以實現父子元件的通訊,當然,各位讀者也可以試試自己引入事件流,或者其他三方庫,來豐富自己的應用通訊方式。 以上~~~~~~~~ 週末啦,祝大家都有個不用加班的週末!

相關文章