微信小程序自定義組件原理探究

組件化是web、移動開發的大趨勢,一次開發多次使用,調用方便,解耦性好。當然在小程序開發是一個趨勢。

官網:https://mp.weixin.qq.com/debug/wxadoc/dev/component/

雖然說從自定義組件化有其官網介紹,但是在開發過程中總是不盡如人意,踩過 幾次坑后還是決定自己基于基礎的原理按照極簡的思想搞一下吧。

0x00 原理

本篇文章傾向于對于小程序或組件化原理有一定了解的群體。說來很簡單,所謂的組件化包括幾個部分,類html,css,和js,這幾個部分分別控制元素,樣式,和代碼邏輯,這幾個部分是要在被加載的地方分別把這三樣加入到容器里面去,可以說是重新為這個組件開辟了一塊內存空間,重新在加載的地方渲染了樣式和元素。簡單點說是,在page中把模板里面的東西塞進去,在一定的條件下顯示出來。或者說是把本來屬于本頁面的東西獨立開了放在了另外的文件里面。拆分出去的元素樣式和邏輯只是跟自己相關,加上一些數據傳遞和接收,就變成了組件。

0x01 插槽/模板加載

小程序里面有個template的東西,就是一個插槽,在一次申明中

<template name="ShareData">
this is a template
</template>

即完成了包裝。里面的樣式寫法就是普通的方式,這就是模板的寫法
在需要用的時候,在wxml中引用它

<import src="ShareData"/>

0x01 CSS加載

樣式是在wxss里面設定的,在容器中添加

@import "../../componts/section/index";
@import "ShareData";

即可把樣式添加到對應的page或其他組件中去。

0x02 JS加載與轉移

這個是重點,很多人并不知道組件化的根本原因是不知道組件的js屬性和方法是要添加到page里面去的。基于此其實也是兩句話的問題就可以完成導入方法和組件。

做一個簡單的例子,實現sectioncontrol

let __outcomp__ = "__SegmentedControl__"
let SegmentedControl = {
  data: {
    radioValues: [
      {'value': '男','selected': false},
      {'value': '女','selected': true},
      {'value': '保密','selected': false},
    ],
clazz: ['selected','last']
  },
methods:{
indexChanged: function (e) {
// 點中的是組中第個元素
var index = e.target.dataset.index;
// 讀取原始的數組
var radioValues = this.data[__outcomp__].radioValues;
for (var i = 0; i < radioValues.length; i++) {
// 全部改為非選中
radioValues[i].selected = false;
// 當前那個改為選中
radioValues[index].selected = true;
}
// 寫回數據
this.setData({
[__outcomp__]: this.data[__outcomp__]
});
// clazz狀態
this.clazzStatus();
},
onLoad: function () {
// onLoad 比 onReady 更早調用,后者為選中時屏幕閃動一下
this.clazzStatus();
},
clazzStatus: function () {
/* 此方法分別被加載時調用,點擊某段時調用 */
// class樣式表如"selected last","selected"
var clazz = [];
// 參照數據源
var radioValues = this.data[__outcomp__].radioValues;
for (var i = 0; i < radioValues.length; i++) {
// 默認為空串,即普通按鈕
var cls = '';
// 高亮,追回selected
if (radioValues[i].selected) {
cls += 'selected ';
}
// 最后個元素, 追加last
if (i == radioValues.length - 1) {
cls += 'last ';
}
//去掉尾部空格
cls = cls.replace(/(\s*$)/g, '');
clazz[i] = cls;
}
// 寫回數據
this.data[__outcomp__].clazz = clazz;
this.setData({
[__outcomp__]: this.data[__outcomp__]
});
}
},
};

function LoadSegmentedControl(fromData) {
let pages = getCurrentPages()
let curPage = pages[pages.length - 1]
Object.assign(curPage, SegmentedControl.methods);

curPage.setData({ [__outcomp__]: SegmentedControl.data });

console.log(curPage.data[__outcomp__])
return this;
}

module.exports = {
LoadSegmentedControl
};

重點看model.exports={LoadSegmentedControl},這其實是導出一個加載的方法的,這個方法用來把該組件中的data和method復制到當前頁面中去。是的,使用的是object.assign,另外data里面的數據是放到頁面data中的[outcomp]屬性值中。

0x03 數據傳遞

有幾種數據需要傳遞,在wxml中如何傳遞,組件中的js如何更改里面的屬性,組件間的數據如何傳遞。

還是基于模板的思想,從原理得知,組件中的標簽和方法其實已經加入到page中去了,所以只需要去page樹中取值和方法即可。

如在加載模板的過程中如下傳遞數據
<template is="SegmentedControl" data='{{...SegmentedControl}}' />
這里有個技巧,用...擴展運算符,把組件中的數據都一次性傳遞過來,并且傳遞之后的key和value都是同一個,這是es6的語法。

然而在js中的method需要改變屬性的方式則可以用

FSHeaderItemTap:function(e){
var index = e.currentTarget.dataset.idx;
console.log(e.currentTarget.dataset.idx);
this.data[outcomp].fsSelectIdx = e.currentTarget.dataset.idx;
this.setData({ [outcomp]: this.data[outcomp]})
if(index == 1){
LoadShareData();
}
},

可以看到,更改本組件中的屬性用的是this.data[outcomp]取值和賦值

0x04 應用

組件與組件的嵌套,或者Page直接的使用都是用的這個原理,在使用的過程中需要注意幾個規范,組件名要有前綴,這樣方便查找方法和屬性。其他方式使用的命名空間就是這個作用吧。下面再來看看下面的界面,這高仿“阿拉丁小程序統計”的界面,有興趣的可以去看看如何實現,結合本例原理簡要分析一下。

image.png
極限水果,專注高端程序員技術與理財人生
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,401評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,011評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,263評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,543評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,323評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,874評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,968評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,095評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,605評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,551評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,720評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,242評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,961評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,358評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,612評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,330評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,690評論 2 370

推薦閱讀更多精彩內容