微信小程序自定義組件
ps 由于作業(yè)部落貌似出了點問題黍檩,耽誤了點時間,找了一個stackedit.io準備寫塑煎。無奈,這是要自己建編輯器的節(jié)奏啊臭蚁。沒有一個能靠的注
為何存在組件
組件間的關系
使用relations實現組件的關系最铁,即父子關系讯赏。
定義和使用組件間的關系
有時需要使用如下的組件間的關系
<custom-ul>
<custom-li> item1 </ custom-li>
<custom-li> item2 </ custom-li>
</ custom-ul>
在上方中,
兩個<custom-ul>
以及<custom-li>
兩個組件都為自定義組件冷尉,如果進行通信會非常的難以操作漱挎,至此通過relations
完成子父組件的定義,簡化通信雀哨。
同樣的以上方的栗子作為舉例磕谅。
繼續(xù)上一個栗子,新建一個頁面雾棺,在新的頁面中使用組件間的關系膊夹。
由于同屬于一個custom大組件,所以直接在components中新建一個custom文件夾捌浩,表示一個大的新組件
由于其擁有一個子組件放刨,所以再新建一個li文件夾,表示custom-li
目錄如下
菜鳥一枚嘉栓,設置的不一定正確宏榕。也不一定是最正統(tǒng)的,只是感覺侵佃。╮(╯▽╰)╭
設置custom/custom.js文件的relations的值
// components/custom/custom.js
Component({
relations: {
'./li/li' : {
type: 'child', // 設置關聯(lián)的目標節(jié)點為子節(jié)點
}
}
})
接著設置祖先節(jié)點麻昼,即設置custom/li/li.js文件的內容
// components/custom/li/li.js
Component({
relations: {
'../../custom': {
type: 'parent' // 應為祖先節(jié)點
}
}
})
設置組件的wxml文件
<! - 組件/自定義/立/ li.wxml - >
< view > components / custom / li / li.wxml </ view > < slot />
<!--components/custom/custom.wxml-->
<view>components/custom/custom.wxml</view>
<slot/>
接著設置page頁面的wxml頁面
<!--pages/ming/ming.wxml-->
<text>hello world</text>
<custom-ul>
<custom-li></custom-li>
<custom-li></custom-li>
<custom-li></custom-li>
<custom-li></custom-li>
</custom-ul>
至此完成馋辈。
關聯(lián)一類組件
被微信的路徑折騰的不輕抚芦,好吧,無奈迈螟,決定重新寫
微信路徑
微信路徑太坑了叉抡。
理所應當應該是
/ 根目錄
../ 父級目錄
./ 當前目錄
結果非要
../../
至今也沒搞清楚路徑是這么回事。算了答毫,決定在同一個目錄下完成模塊的問題褥民,不在另外的分一個模塊的文件夾了。
總說
要形成的在page下的結構如下
<custom-form>
<view>
input
<custom-input></custom-input>
</view>
<custom-submit>shubmit</custom-submit>
</custom-form>
創(chuàng)建目錄
創(chuàng)建目錄如下
好啦洗搂,目錄如上
這一次放棄將模塊放在另外一個文件夾消返,這一場所有的和組件相關的內容都放在同一個文件夾下 。符合組件的精神
其中form表明該為一個form的組件耘拇。module表明組件的內容撵颊,其中module下還有一個behaviors表明是behaviors的內容的模塊,input和submit表明是其子組件惫叛。
behaviors
書寫behaviors的內容倡勇。
// components/form/module/behaviors/controls
module.exports = Behavior({
// ...
})
父組件
書寫父組件及form的內容
// components/form/form.js
var formControls = require('./module/behaviors/controls.js')
Component({
relations: {
'formControls': {
type: 'descendant', // 關聯(lián)目標的節(jié)點應為子孫節(jié)點
target: formControls // 所有設置behavior的組件的節(jié)點都為其子孫節(jié)點
}
}
})
繼續(xù)書寫wxml的內容,其實就是添加一個掛載點的問題。
<!--components/form/form.wxml-->
<text>components/form/form.wxml</text>
<slot/>
input組件
// components/form/input/input.js
var formControls = require('../module/behaviors/controls.js')
Component({
behaviors: [formControls],
relations: {
'../form': {
type: 'ancestor', // 關聯(lián)的目標節(jié)點應為祖先節(jié)點
}
}
})
wxml
<!--components/form/input/input.wxml-->
<text>components/form/input/input.wxml</text>
<slot/>
submit組件
此為from的子組件
// components/form/submit/submit.js
var formControls = require('../module/behaviors/controls.js')
Component({
behaviors: [formControls],
relations: {
'../form': {
type: 'ancestor', // 關聯(lián)的目標節(jié)點應為祖先節(jié)點s
}
}
})
繼續(xù)寫wxml加上一個
<!--components/form/submit/submit.wxml-->
<text>components/form/submit/submit.wxml</text>
<label><slot/></label>
json配置文件
{
"usingComponents": {
"component": "/components/component",
"body": "/components/body/body",
"custom-form": "/components/form/form",
"custom-input": "/components/form/input/input",
"custom-submit": "/components/form/submit/submit"
}
}
編寫頁面的wxml
<custom-form>
<view>
<custom-input/>
</view>
<custom-submit/>
</custom-form>
完成(o)/
至此嘉涌,根據一個behaviors完成一個組件
抽象性節(jié)點
抽象節(jié)點類似于掛載點妻熊,但是和掛載點不同的是夸浅,可以通過屬性來更改掛載的組件。需要注意的一點是固耘,其值需要為靜態(tài)值题篷,不能為動態(tài)值,抽象節(jié)點只能使用靜態(tài)的內容厅目。
但是個人感覺和掛載點還是有一點類似的作用番枚,不過這個是通過不同的條件達到調用的目的。
抽象節(jié)點核心在于調用的時候才能確定內部需要什么組件损敷,只有調用才能確認需要的組件葫笼,核心在于將業(yè)務和邏輯分離,徹底達到消除耦合的目的拗馒。
組件的目的在于盡可能的減少業(yè)務邏輯在里面路星。
注意,組件的確是要盡可能的減少邏輯在里面诱桂,因為組件的核心在于復用洋丐,在于大量的復用。減少重復代碼的書寫挥等,即將一段業(yè)務中的重復的友绝,多次的抽象出來,提取成為一個組件肝劲,如果因為某些原因迁客,必須要存在一定的業(yè)務邏輯在里面,這個時候就需要抽象節(jié)點辞槐。
抽象節(jié)點和掛載點的不同就在上方體現出來了而姐,抽象節(jié)點是必須有的嵌灰,但是掛載點可有可無
抽象節(jié)點的核心在于分離栓辜,抽象刹悴。
再次感受抽象的重要性
在組件中使用抽象節(jié)點
在自定義模板中的一些節(jié)點,其對應的自定義組件不是由自定義組件本身確定的鹿榜,由調用者確定先朦,稱為抽象節(jié)點
這定義╮(╯▽╰)╭
例如下面的代碼
<view>
<label>
<selectable disabled="{{false}}"/>
</label>
</view>
在上方的代碼中,selectable
是由調用者確定的犬缨,需要在調用的時候根據屬性值進行替換
還需要在json文件中添加如下的配置
{
"componentGenerics": {
"selectable": true
}
}
直接聲明該節(jié)點為抽象節(jié)點,其值由調用者確定
使用包含抽象節(jié)點的組件
上方是在代碼中定義抽象節(jié)點棉浸。僅僅是定義怀薛,還不能使用。
如果要是使用抽象節(jié)點迷郑,需要再次添加屬性
generic 為一個選項
在page頁面中寫入如下內容
<custom-form generic:selectable="component">
</custom-form>
表明引入一個組件枝恋,其中的抽象節(jié)點的selectable替換為component內容创倔。
需要注意的是,需要在json文件中引入component的內容
默認組件
即在未指定組件內容的時候使用的組件
在組件文件夾中的json聲明焚碌。
此時不需要使用true即可聲明抽象節(jié)點
{
"usingComponents": {},
"componentGenerics": {
"selectable": {
"default": "/components/component"
}
}
}
自定義組件擴展
自定義組件的擴展實質為提供了修改自定義組件定義段的能力畦攘。使用自定義組件的擴展能動態(tài)的修改的自定義組件的擴展。
一直別一個及其簡單的問題困擾了很久十电,es6中新增加的對象屬性聲明知押,并賦值,可以直接省去function關鍵字鹃骂。
關于es6
關于es6的問題台盯,是滴,被微信官方文檔的一個寫法糾結了很久
```js
module.exports = Behavior({
definitionFilter(defFields) {
defFields.data.from = 'behavior'
},
})
就上方的寫法畏线,由于是一種新的寫法静盅,上方的等價于下方的內容
module.exports = Behavior({
definitionFilter: function definitionfilter(defFields) {
defFields.data.form = 'behavior'
}
})
僅僅是一種新的es6的寫法。一種聲明私有函數的方式寝殴,一般在組件里聲明私有函數蒿叠。這個時候,可以直接省去function蚣常。
好啦市咽,最大的障礙解決了。
definitionfilter函數
Behavior()
構造器定義了一個新的段史隆,即definitionfilter
段魂务。
該函數具有兩個定義段,分別是defFields
以及 definitionFilterAll
此為兩個參數
下面解釋這兩個參數
defFields
參數
對于該參數來說泌射,是當前被調用使用的behavior粘姜,這個灰常簡單不在多說
definitionFilterAll
參數
這個參數為behaviors順序。
使用一個官方的栗子來解釋吧
// behavior3.js
module.exports = Behavior({
definitionFilter(defFields, definitionFilterArr) {},
})
// behavior2.js
module.exports = Behavior({
behaviors: [require('behavior3.js')],
definitionFilter(defFields, definitionFilterArr) {
// definitionFilterArr[0](defFields)
},
})
// behavior1.js
module.exports = Behavior({
behaviors: [require('behavior2.js')],
definitionFilter(defFields, definitionFilterArr) {},
})
// component.js
Component({
behaviors: [require('behavior1.js')],
})
在上方的栗子中熔酷,每個defFelds
都為當前調用的behaviors孤紧,而definitionFilterArr
是這樣的情況
當調用2的時候,因為會調用3的definitionFilter
函數拒秘,對其內容進行更改号显,在3中的definitionFilter
函數有兩個參數,第一個參數為2的behavior的定義段躺酒,即2中的各項內容進行更改押蚤,第二個參數為3的behaviors的內容,由于3沒有引用其他的behaviors羹应,所以為一個空數組
總結揽碘,當調用的時候,第一個參數為調用者的behaviors,而第二個參數為其本身的behaviors
當進行到1的時候雳刺,將會調用2的definitionFilter
劫灶,其2的該函數的第一個參數為1的behaviors,和其他的一些項掖桦,第二個參數為2引用的behaviors本昏,由于2引用了3的behaviors,而3沒有引用枪汪,所以是一個只有一項的數組涌穆,該數組的內容為2引用的behaviors,即3的definitionFilter
定義段
如果當調用1的時候料饥,要調用3的definitionFilter
函數
分析蒲犬,3的definitionFilter
函數由2的behaviors
函數調用,而2的·definitionFilter
函數是由1的behaviors
調用岸啡,并且3的definitionFilter
函數在2中的definitionFilter
函數的第二個參數的第一項(數組)中有其內容原叮,所以需要在2中寫數組,用來調用3的definitionFilter
函數巡蘸。
所以第2中有definitionFilterArr[0](defFields)
表明是調用3的definitionFilter
而參數defFields
表明是2中的behaviors
中的內容奋隶。
同理使用Component
構造函數的時候,將會調用1的definitionFilter
函數對Component
內容進行更改悦荒。
最后唯欣,總結就是一句話
當調用的時候,第一個參數為調用者的behaviors搬味,而第二個參數為其本身的behaviors
官方擴展包 https://github.com/wechat-miniprogram/computed 實現動態(tài)的計算屬性
哦境氢。貌似切圖仔最重要的瀑布流還沒有學習
第三方自定義組件
終于到自己的知識范疇啦。目前已經會node.js和npm碰纬,下面的就比較好學習了萍聊。
微信小程序的官方ide支持npm
官方提供有一個模板 https://github.com/wechat-miniprogram/miniprogram-custom-component
屬于小程序的自定義腳手架的相關內容。
官方的事例的組件 https://github.com/wechat-miniprogram/slide-view
以及官方提供的命令行工具 https://github.com/wechat-miniprogram/miniprogram-cli
命令行工具
npm install -g @wechat-miniprogram/miniprogram-cli
東西有點多
安裝完成以后進行初始化
miniprogram init [options] [dirPath]
進行選擇即可悦析。
miniprogram
即第三方的自定義組件寿桨,custom-component為創(chuàng)建一個空的自定義組件目錄,miniprogram為一個小程序的自定義組件的快速的開始强戴,會有一個從github上下的一個模板亭螟,寫代碼即可。
屬于腳手架的一部分骑歹。
由于涉及到glup预烙,暫時擱置。
目錄如下
|--miniprogram_dev // 開發(fā)環(huán)境構建目錄
|--miniprogram_dist // 生產環(huán)境構建目錄
|--src // 源碼
| |--common // 通用 js 模塊
| |--components // 通用自定義組件
| |--images // 圖片資源
| |--wxml // 通用 wxml 模版資源
| |--wxs // 通用 wxs 資源
| |--wxss // 通用 wxss 資源
| |
| |--xxx.js/xxx.wxml/xxx.json/xxx.wxss // 暴露的 js 模塊/自定義組件入口文件
|
|--test // 測試用例
|--tools // 構建相關代碼
| |--demo // demo 小程序目錄道媚,開發(fā)環(huán)境下會被拷貝生成到 miniprogram_dev 目錄中
| |--test // 測試工具相關目錄
| |--config.js // 構建相關配置文件
|
|--gulpfile.js
即扁掸,按照上方進行構建相關的組件即可欢嘿。目前src部分能看明白,暴露的接口和node.js的包如出一轍也糊,都是直接在主文件中進行暴露出接口的,最上方兩個文件羡宙,最開始接觸到的是git的工作流狸剃,根據git的工作流也能明白,最后test和tools這一點還有點暈狗热。測試用例使用下方的命令構建出測試用例钞馁。
npm run test
tools中的demo為一個演示,即開發(fā)者下載下來內容以后將會直接出現的內容匿刮,例如僧凰,文檔中的使用微信小程序打開這一點就是參考這樣的,
test測試工具相關目錄熟丸,進行測試的工具存放的目錄训措。例如進行自動化測試的一些腳本要書寫在這里。
config.js為進行自動化構建所要進行的文件光羞,
ps 由于構建工具未學绩鸣,構建工具的學習重點肯定是配置文件的書寫。以及對接口的暴露等纱兑。
至此呀闻,暫時結束微信小程序的自定義組件化,明天寫插件潜慎。