縱觀現(xiàn)代前端框架中(不論ng react vue ) 基本四架馬車 聲明式渲染 路由 組件化 狀態(tài)管理洲敢。 反觀小程序開發(fā)環(huán)境 缺失蠻多特性的 好在 11月初微信團隊,發(fā)布了官方的component 化方案, 我們基本上可以告別現(xiàn)有的hack辦法去實現(xiàn) component 化蜗元。
hack方式
使用template實現(xiàn)組件化https://zhuanlan.zhihu.com/p/...
使用include組件化
這個簡單說下 include 組件wxml 和樣式文件到 page 然后 ,import 組件的js文件 通過合并方式將組件data method 合并到page 對于data,直接采用 Object.assign method 進行融合嗦随,先調(diào)用組件事件陡叠,然后調(diào)用父頁面事件.
以上方案核心: 將組件內(nèi)定義的 data 和 method 合并到page中去 實現(xiàn)組件化, 本質(zhì)上都在同一個作用域下組件作用域沒有隔離,難免會出現(xiàn) 命名沖突 覆蓋.
實現(xiàn)一個組件
方便快速理解,下面使用官方組件化方案 實現(xiàn)一個模態(tài)彈窗 easyModal.
請結(jié)合源碼看https://gitee.com/sherlock221...
閱讀前 請先讀通官方自定義組件文檔https://mp.weixin.qq.com/debu...
組件分析
首先分成2個小組件 來實現(xiàn)這個模態(tài)彈窗
基本模態(tài)彈窗 和 增強型模態(tài)彈窗
基本模態(tài)彈窗 具備
1.顯示/隱藏
2.backdrop
3.過度動畫
4.自定義頭尾
這幾部分基礎(chǔ)功能
增強型模態(tài)彈窗 具備
1.基礎(chǔ)模態(tài)彈窗功能
2.自定義內(nèi)容區(qū)域
3.title自定義
4.確定取消按鈕自定義
基本模態(tài)窗
首先在base文件夾下直接右鍵創(chuàng)建component -> baseModal
在baseModal.js中創(chuàng)建組件所需要props 這些屬性來自父組件或 外層page 中的數(shù)據(jù)籽御,
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
}
}
},
}
下來創(chuàng)建 data练慕,isShow控制 彈窗顯示和隱藏 animation則是彈窗動畫函數(shù).
/**
* 組件的初始數(shù)據(jù)
*/
data: {
isShow : false,
animation : ''
},
在生命周期函數(shù) ready中初始化animation
ready: function () {
this.animation = wx.createAnimation({
duration: this.data.animationOption.duration,
timingFunction: "linear",
delay: 0
});
},
組件有2個public方法 show hide 方法, private 有執(zhí)行動畫 和 切換顯隱的方法
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屬性來判斷 組件是否需要調(diào)用_executeAnimation 來執(zhí)行動畫顯示
頁面結(jié)構(gòu)
<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 節(jié)點,用于承載組件使用者提供的wxml結(jié)構(gòu)技掏。
默認情況下铃将,一個組件的wxml中只能有一個slot。需要使用多slot時哑梳,記得開啟配置
options : {
multipleSlots: true
},
下來創(chuàng)建樣式wxss
具體可以看github 文件這就不貼
/** 模態(tài) **/
.modal{
position: fixed;
top: 0rpx;
left: 0rpx;
right: 0rpx;
bottom: 0rpx;
width: 100%;
height: 100%;
z-index: 100;
}
..............
需要注意 組件wxss文件 具備
隔離性的
你在page 中定義的class 劲阎, 在app.wxss 中定義的class 都無法再組件中使用,如果真有一些需要復(fù)用到的樣式 可以抽取成一個wxss 通過import 導(dǎo)入 組件的wxss
@import "../../style/font.wxss";
這樣會增加組件和業(yè)務(wù)的耦合度 公共組件不建議使用
接下來可以在業(yè)務(wù)界面中去使用
<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>
別忘了在業(yè)務(wù)頁面的json中引入組件
{
"usingComponents": {
"base-modal": "/component/easyModal/base/baseModal"
}
}
還記得我們上面baseModal 有兩個public方法 怎么樣去調(diào)用呢 這里介紹下
Component 的一個實例方法 selectComponent
通過它 可以找到子組件實例 這個有點像是 jq 選擇器 通過selector去尋找dom(但是不是dom是js對象) 不過它更像是 react 或 vue ref this.$ [http://refs.xxx](http://link.zhihu.com/?target=http%3A//refs.xxx)
獲得組件實例.
我們給這個組件創(chuàng)建一個id 通過id選擇器就可以找到base-modal的實例 在ready中找到modal實例
onReady: function () {
this.thridModal = this.selectComponent("#thridModal");
},
然后就可以調(diào)用實例的public的方法.
this.thridModal.showModal();
this.thridModal.hideModal();
增強模態(tài)窗
增強模態(tài)窗是基于baseModal的.
{
"component": true,
"usingComponents": {
"base-modal" : "../base/baseModal"
}
}
注意 增強模態(tài)窗口 需要包含 基本模態(tài)窗口 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 發(fā)送事件通知的其進行業(yè)務(wù)操作的
//cancel
_cancelModal : function(){
this.hide();
this.triggerEvent("cancelEvent");
},
//success
_confirmModal : function(){
this.triggerEvent("confirmEvent");
}
通過triggerEvent觸發(fā)事件 這點和官網(wǎng)文檔沒有區(qū)別.
業(yè)務(wù)Page界面:
<easy-modal
id="easyModal"
title="這個是標題 01"
bind:cancelEvent="_cancelEvent"
bind:confirmEvent="_confirmEventFirst"
> <view class='modal-content'>
<text> 這是內(nèi)容部分 01 </text>
<text> 這是內(nèi)容部分 01 </text>
<text> 這是內(nèi)容部分 01 </text>
</view>
</easy-modal>
一個基本模態(tài)窗口 就完成了, 滿足基本業(yè)務(wù)使用 還有很多地方可以根據(jù)你們自身業(yè)務(wù) 進行 擴展.
本文作者:sherlock221
原文地址:微信小程序組件化 快速實現(xiàn)可用模態(tài)窗