縱觀現代前端框架中(不論ng react vue ) 基本四架馬車 宣告式渲染 路由 元件化 狀態管理。 反觀小程式開發環境 缺失蠻多特性的 好在 11月初微信團隊,釋出了官方的component 化方案, 我們基本上可以告別現有的hack辦法去實現 component 化。
hack方式
使用template實現元件化 https://zhuanlan.zhihu.com/p/26785726 使用include元件化 這個簡單說下 include 元件wxml 和樣式檔案到 page 然後 ,import 元件的js檔案 通過合併方式將元件data method 合併到page 對於data,直接採用 Object.assign method 進行融合,先呼叫元件事件,然後呼叫父頁面事件.
以上方案核心: 將元件內定義的 data 和 method 合併到page中去 實現元件化, 本質上都在同一個作用域下 元件作用域沒有隔離 難免會出現 命名衝突 覆蓋.
實現一個元件
方便快速理解,下面使用官方元件化方案 實現一個模態彈窗 easyModal.
請結合原始碼看 https://github.com/sherlock221/wx-easyModal 如果覺得不錯請點個star
閱讀前 請先讀通官方自定義元件文件 https://mp.weixin.qq.com/debug/wxadoc/dev/framework/custom-component/
元件分析
首先分成2個小元件 來實現這個模態彈窗 基本模態彈窗 和 增強型模態彈窗
基本模態彈窗 具備
1.顯示/隱藏
2.backdrop
3.過度動畫
4.自定義頭尾
這幾部分基礎功能
增強型模態彈窗 具備
1.基礎模態彈窗功能 2.自定義內容區域 3.title自定義 4.確定取消按鈕自定義
基本模態窗
首先在base資料夾下直接右鍵建立component -> baseModal 在baseModal.js中建立元件所需要props 這些屬性來自父元件或 外層page 中的資料,
Component({
options : {
multipleSlots: true
},
/**
* 元件的屬性列表
*/
properties: {
backdrop: {
type: Boolean,
value: true
},
animated : {
type: Boolean,
value: true
},
modalSize : {
type: String,
value: "md"
},
animationOption : {
type : Object,
value : {
duration : 300
}
}
},
}
複製程式碼
下來建立 data,isShow控制 彈窗顯示和隱藏 animation則是彈窗動畫函式.
/**
* 元件的初始資料
*/
data: {
isShow : false,
animation : ''
},
複製程式碼
在生命週期函式 ready中初始化animation
ready: function () {
this.animation = wx.createAnimation({
duration: this.data.animationOption.duration,
timingFunction: "linear",
delay: 0
});
},
複製程式碼
元件有2個public方法 show hide 方法, private 有執行動畫 和 切換顯隱的方法
methods: {
hideModal : function(e){
if(e){
let type = e.currentTarget.dataset.type;
if (type == 'mask' && !this.data.backdrop) {
return;
}
}
if (this.data.isShow) this._toggleModal();
},
showModal : function(){
if (!this.data.isShow) {
this._toggleModal();
}
},
_toggleModal : function(){
if(!this.data.animated){
this.setData({
isShow: !this.data.isShow
})
}
else{
let isShow = !this.data.isShow;
this._executeAnimation(isShow);
}
},
_executeAnimation: function (isShow) {
......
}
}
複製程式碼
可以通過animated屬性來判斷 元件是否需要呼叫_executeAnimation 來執行動畫顯示
頁面結構
<view animation="{{animationData}}" hidden="{{!isShow}}" class='modal'>
<view data-type="mask" catchtap='hideModal' class='modal-mask' ></view>
<view class='modal-layer modal-layer-radius {{modalSize == "sm" ? " modal-layer-sm" : " modal-layer-md" }} ' >
<!-- 頭部 -->
<view class='modal-header'>
<slot name="header"></slot>
</view>
<!-- 內容區域 -->
<view class='modal-body'>
<slot name="body"></slot>
</view>
<view class='modal-footer'>
<slot name="footer"></slot>
</view>
</view>
</view>
複製程式碼
slot 節點,用於承載元件使用者提供的wxml結構。 預設情況下,一個元件的wxml中只能有一個slot。需要使用多slot時,記得開啟配置
options : {
multipleSlots: true
},
複製程式碼
下來建立樣式wxss 具體可以看github 檔案這就不貼
/** 模態 **/
.modal{
position: fixed;
top: 0rpx;
left: 0rpx;
right: 0rpx;
bottom: 0rpx;
width: 100%;
height: 100%;
z-index: 100;
}
..............
複製程式碼
需要注意 元件wxss檔案 具備 隔離性的 你在page 中定義的class , 在app.wxss 中定義的class 都無法再元件中使用,如果真有一些需要複用到的樣式 可以抽取成一個wxss 通過import 匯入 元件的wxss
@import "../../style/font.wxss";
複製程式碼
這樣會增加元件和業務的耦合度 公共元件不建議使用
接下來可以在業務介面中去使用
<base-modal id="thridModal">
<view slot="header" class='modal-header'>
頭部
</view>
<view slot="body" class='modal-body'>
中間
</view>
<view slot="footer" class='modal-footer'>
尾部
</view>
</base-modal>
複製程式碼
別忘了在業務頁面的json中引入元件
{
"usingComponents": {
"base-modal": "/component/easyModal/base/baseModal"
}
}
複製程式碼
還記得我們上面baseModal 有兩個public方法 怎麼樣去呼叫呢 這裡介紹下
Component 的一個例項方法 selectComponent 通過它 可以找到子元件例項 這個有點像是 jq 選擇器 通過selector去尋找dom(但是不是dom是js物件) 不過它更像是 react 或 vue ref this.$refs.xxx 獲得元件例項.
我們給這個元件建立一個id 通過id選擇器就可以找到base-modal的例項 在ready中找到modal例項
onReady: function () {
this.thridModal = this.selectComponent("#thridModal");
},
複製程式碼
然後就可以呼叫例項的public的方法.
this.thridModal.showModal();
this.thridModal.hideModal();
複製程式碼
增強模態窗
增強模態窗是基於baseModal的.
{
"component": true,
"usingComponents": {
"base-modal" : "../base/baseModal"
}
}
複製程式碼
注意 增強模態視窗 需要包含 基本模態視窗 json中引用才能使用
<base-modal id="baseModal" modalSize="{{modalSize}}" animated="{{animated}}" backdrop="{{backdrop}}">
<view slot="header" class='modal-header'>
<text>{{title}}</text>
</view>
<view slot="body" class='modal-body'>
<slot></slot>
</view>
<view slot="footer" class='modal-footer'>
<text catchtap='_cancelModal' class='btn btn-default'>{{cancelText}}</text>
<text catchtap='_confirmModal' class='btn btn-primary'>{{confirmText}}</text>
</view>
</base-modal>
複製程式碼
說下event部分 確定 取消按鈕是需要 向外部page 傳送事件通知的其進行業務操作的
//cancel
_cancelModal : function(){
this.hide();
this.triggerEvent("cancelEvent");
},
//success
_confirmModal : function(){
this.triggerEvent("confirmEvent");
}
複製程式碼
通過triggerEvent觸發事件 這點和官網文件沒有區別.
業務Page介面:
<easy-modal
id="easyModal"
title="這個是標題 01"
bind:cancelEvent="_cancelEvent"
bind:confirmEvent="_confirmEventFirst"
> <view class='modal-content'>
<text> 這是內容部分 01 </text>
<text> 這是內容部分 01 </text>
<text> 這是內容部分 01 </text>
</view>
</easy-modal>
複製程式碼
一個基本模態視窗 就完成了, 滿足基本業務使用 還有很多地方可以根據你們自身業務 進行 擴充套件.
本文原創 轉載請註明署名和出處