微信小程序-自定義組件

一储笑、自定義組件介紹

微信小程序提供了自定義組件擴(kuò)展機(jī)制,允許我們使用自定義組件的方式來構(gòu)建頁面。

自定義組件可以使我們更好的復(fù)用一些功能伏钠。

二、創(chuàng)建自定義組件

在項(xiàng)目的pages文件夾下創(chuàng)建文件夾坏怪,例如customComponent文件夾贝润,然后右鍵這個文件夾绊茧,選擇新建Component铝宵,這時customComponent文件夾出現(xiàn)四個文件,和正常的創(chuàng)建的一樣华畏,下面介紹這四個文件和正常的不同之處:

#CusComponent.js:
Component({
  /**
   * 組件的屬性列表
   */
  properties: {
  },
  /**
   * 組件的初始數(shù)據(jù)
   */
  data: {
  },
  /**
   * 組件的方法列表
   */
  methods: {
  }
})
#CusComponent.json
{
  "component": true,  //代表當(dāng)前文件是一個組件
  "usingComponents": {} //使用組件寫在括號里
}

js文件的頭有Page變?yōu)?code>Component鹏秋,json文件里面多了"component": true,wxmlwxss文件和原來的一樣亡笑。

三侣夷、如何使用自定義組件

想在主頁index頁面使用組件,那么打開存放頁面的pages文件夾下的index文件夾中的index.json仑乌,在usingComponents中添加如下代碼:

{
  "usingComponents": {
    "CusComponent":"/pages/customComponent/cusComponent"
  }
}

usingComponents里面是鍵值對百拓,左邊是要使用組件的名字,右邊是其路徑晰甚。

接著在index.wxml中使用<CusComponent></CusComponent>引入組件衙传。

四、自定義組件中.js文件的屬性介紹

  • data屬性:組件的初始數(shù)據(jù)
    例如添加如下數(shù)據(jù):
#js文件中的data屬性:
data: {
    itemList:[
      {id:0,name:"首頁"},
      {id:1,name:"類別"},
      {id:2,name:"關(guān)于"},
    ]
  }

此時在wxml文件中可以像下面這樣寫:

<view wx:for="{{itemList}}" wx:key="key">{{item.name}}</view>

結(jié)果:首頁  類別  關(guān)于

因?yàn)?code>wx:for中列表遍歷默認(rèn)的是item厕九,所以可以直接用item.name來獲取name蓖捶。

  • methods屬性:組件的方法列表
    在正常頁面中方法是存放在.js文件data屬性的同層級下的。而在自定義組件中必須放在.js文件methods里面扁远,放在外面方法無效俊鱼。
<view bindTap="handleMethod"></view>

methods: {
  handleMethod(e){
    //語句let itemList = this.data.itemList;和下面的相等,解構(gòu)
    let {itemList} = this.data;
    //[].forEach遍歷數(shù)組畅买,遍歷的時候修改了v并闲,也會導(dǎo)致源數(shù)組被修改
    //使用這種寫法則相當(dāng)于重新拷貝了一份數(shù)據(jù)let items = JSON.parse(JSON.stringify(this.data.itemList));
    itemList.forEach((v,i) => i===index?v.isActive=true:v.isActive=false)
  }
}
  • properties屬性:組件的對外屬性,是屬性名到屬性設(shè)置的映射表谷羞。里面存放的是父組件傳遞過來的數(shù)據(jù)
    參見:五焙蚓、父組件向子組件傳值
  • options屬性:配置一些功能的選項(xiàng)
    可配置的選項(xiàng):

multipleSlots:true,在組件定義時的選項(xiàng)中啟動多slot支持
styleIsolation:isolated,啟動樣式隔離购公,具體配置選項(xiàng)參見:(八)自定義組件的樣式
addGlobalClass:true萌京,表示頁面 wxss 樣式將影響到自定義組件,但自定義組件 wxss 中指定的樣式不會影響頁面宏浩。這個選項(xiàng)等價于設(shè)置 styleIsolation: apply-shared
virtualHost:true知残,將自定義節(jié)點(diǎn)設(shè)置成虛擬的,我們不希望自定義組件的這個節(jié)點(diǎn)本身可以設(shè)置樣式比庄、響應(yīng) flex 布局等求妹,而是希望自定義組件內(nèi)部的第一層節(jié)點(diǎn)能夠響應(yīng) flex 布局或者樣式由自定義組件本身完全決定。

/* 組件 custom-component.js */
Component({
  options: {
    addGlobalClass: true,
  }
})
  • 其他屬性:
屬性 類型 是否必填 描述
properties Object|Map 組件的對外屬性佳窑,是屬性名到屬性設(shè)置的映射表
data Object 組件的內(nèi)部數(shù)據(jù)制恍,和properties用用于組件的模版渲染
observers Object 組件數(shù)據(jù)字段監(jiān)聽器,用于監(jiān)聽properties和data的變化
methods Object 組件的方法神凑,包括事件響應(yīng)函數(shù)和任意的自定義方法
created Function 組件生命周期函數(shù)净神,在組件實(shí)例剛剛被創(chuàng)建時執(zhí)行,注意此時不能調(diào)用setData
attached Function 組件生命周期函數(shù)溉委,在組件實(shí)例進(jìn)入頁面節(jié)點(diǎn)樹時執(zhí)行
ready Function 組件生命周期函數(shù)鹃唯,在組件布局完成后執(zhí)行
moved Function 組件生命周期函數(shù),在組件實(shí)例被移動到節(jié)點(diǎn)樹另一個位置時執(zhí)行
detached Function 組件生命周期函數(shù)瓣喊,在組件實(shí)例被從頁面節(jié)點(diǎn)樹移除時執(zhí)行

五坡慌、父組件向子組件傳值

直接看代碼:

#父組件的wxml文件,在此文件中引入CusComponent組件
//parentData為要傳遞的數(shù)據(jù)名稱藻三,parent_data為數(shù)據(jù)內(nèi)容
<CusComponent parentData="parent_data"></CusComponent>
#自定義組件的.js文件里的properties屬性
properties: {
    //要接收的數(shù)據(jù)名稱
    parentData:{
      //要接收的數(shù)據(jù)類型
      type:String,
      //要接收的數(shù)據(jù)
      value:''
    }
  }
<!-- 自定義組件的wxml文件 -->
<view wx:for="{{itemList}}" wx:key="key">{{item.name}}</view>
<!-- parentData就是要接收數(shù)據(jù)的名稱 -->
<view class="content">{{parentData}}</view>

過程:
1洪橘、父組件通過parentData="parent_data"將數(shù)據(jù)傳到子組件
2、子組件的properties接收到數(shù)據(jù)后棵帽,根據(jù)父組件數(shù)據(jù)名parentData熄求,存到parentDatavalue
3、子組件的wxml文件直接使用{{parentData}}來拿到父組件傳遞過來的數(shù)據(jù)岖寞。

六抡四、子組件向父組件傳值

子組件給父組件傳遞數(shù)據(jù)通過自定義組件觸發(fā)事件來進(jìn)行傳遞。先看代碼:

#子組件的.js文件
methods: {
  handleActive(e){
    const {index} = e.currentTarget.dataset;
    //triggerEvent("自定義事件名稱",要傳遞的數(shù)據(jù))仗谆,觸發(fā)事件
    this.triggerEvent("itemChange",{index});
  }
}
#父組件的wxml文件
<!--
當(dāng)子組件事件觸發(fā)后指巡,bindbinditemChange會執(zhí)行其后的方法changeItemList()
binditemChange="changeItemList";
1、binditemChange:其格式是bind+事件名稱隶垮,事件的名稱是子組件中this.triggerEvent("itemChange",{index});的事件名稱
2藻雪、changeItemList():是父組件.js文件中的方法
-->
< CusComponent itemList="{{itemList}}" binditemChange="changeItemList"></CusComponent>
#父組件.js文件中的方法
changeItemList(e){
  const index = e.detail.index;
  let itemList = this.data.itemList;
  itemList.forEach((v,i) => {
    i===index?v.isActive=true:v.isActive=false
  });
  this.setData({
    itemList:itemList
  })
}

過程:
1、點(diǎn)擊子組件后調(diào)用子組件的handleActive(e)狸吞,此方法中有個自定義組件觸發(fā)事件this.triggerEvent("itemChange",{index});
2勉耀、觸發(fā)父組件wxml文件引用的<CusComponent/>組件中的binditemChange指向的changeItemList()方法
3指煎、在父組件的.js文件中的changeItemList()方法中對子組件傳遞過來的數(shù)據(jù)進(jìn)行處理

  • triggerEvent方法參數(shù):triggerEvent('myevent',{myEventDetail},{myEventOption});

triggerEvent方法三個參數(shù)解釋:
?'myevent':自定義事件的名稱
?myEventDetail:detail對象,提供給事件監(jiān)聽函數(shù)便斥,如上面?zhèn)鬟f的數(shù)據(jù)
?myEventOption:觸發(fā)事件的選項(xiàng)至壤,不是必填項(xiàng)。

myEventOption的三個選項(xiàng)解釋:
?bubbles:事件是否冒泡枢纠。默認(rèn)值false
?composed:事件是否可以穿越組件邊界像街,為false時,事件將只能在引用組件的節(jié)點(diǎn)樹上觸發(fā)晋渺,不進(jìn)入其他任何組件內(nèi)部镰绎。默認(rèn)值false
?capturePhase:事件是否擁有捕獲階段。默認(rèn)值false

七木西、自定義組件中的 slot 標(biāo)簽

組件的寫法和頁面相同畴栖。組件與組件數(shù)據(jù)結(jié)合后生產(chǎn)的節(jié)點(diǎn)樹,將被插入到組件的引用位置上八千。

在組件中提供了一個<slot>節(jié)點(diǎn)吗讶,用于承載組件引用時提供的子節(jié)點(diǎn)。

注意:在模板中引用到的自定義組件及其對應(yīng)的節(jié)點(diǎn)名需要在 json 文件中顯式定義叼丑,否則會被當(dāng)作一個無意義的節(jié)點(diǎn)关翎。除此以外扛门,節(jié)點(diǎn)名也可以被聲明為抽象節(jié)點(diǎn)鸠信。

#父組件wxml中引用的子組件
<cusComponent>
  <view>父組件傳遞過來的節(jié)點(diǎn),相當(dāng)于子組件中的slot</view>
</cusComponent>
#子組件wxml中
<view class="content">
  <slot></slot>
</view>

上面的代碼就會讓父組件傳遞過來的節(jié)點(diǎn)论寨,相當(dāng)于子組件中的slot在你的自定義組件中顯示星立。

需要多個slot時,如何在組件js中聲明:

#子組件的.js文件
Component({
  options: {
    multipleSlots: true // 在組件定義時的選項(xiàng)中啟用多slot支持
  },
})

此時就可以在組件的wxml中使用多個slot葬凳,以不用的name來區(qū)分:

#子組件的.wxml文件
<view class="content">
  <slot name="name1"></slot>
  <slot name="name2"></slot>
</view>

八绰垂、自定義組件的樣式

1、組件樣式

組件對應(yīng) wxss 文件的樣式火焰,只對組件wxml內(nèi)的節(jié)點(diǎn)生效劲装。編寫組件樣式時,需要注意以下幾點(diǎn):

  • 請使用class選擇器:組件和引用組件的頁面不能使用id選擇器(#a)昌简、屬性選擇器([a])和標(biāo)簽名選擇器占业,請改用class選擇器。
  • 避免使用后代選擇器:組件和引用組件的頁面中使用后代選擇器(.a .b)在一些極端情況下會有非預(yù)期的表現(xiàn)纯赎,如遇谦疾,請避免使用。
  • 子元素選擇器只能用于view及子節(jié)點(diǎn):子元素選擇器(.a>.b)只能用于 view 組件與其子節(jié)點(diǎn)之間犬金,用于其他組件可能導(dǎo)致非預(yù)期的情況念恍。
  • 繼承樣式:繼承樣式六剥,如 font 、 color 峰伙,會從組件外繼承到組件內(nèi)疗疟。
  • app.wxss樣式組件對自定義組件無效:除繼承樣式外, app.wxss 中的樣式瞳氓、組件所在頁面的的樣式對自定義組件無效(除非更改組件樣式隔離選項(xiàng))秃嗜。
#a { } /* 在組件中不能使用 */
[a] { } /* 在組件中不能使用 */
button { } /* 在組件中不能使用 */
.a > .b { } /* 除非 .a 是 view 組件節(jié)點(diǎn),否則不一定會生效 */

除此以外顿膨,組件可以指定它所在節(jié)點(diǎn)的默認(rèn)樣式锅锨,使用 :host 選擇器(需要包含基礎(chǔ)庫 [1.7.2]。

/* 組件 custom-component.wxss */
:host {
  color: yellow;
}
2恋沃、組件樣式隔離

默認(rèn)情況下必搞,自定義組件的樣式只受到自定義組件 wxss 的影響。除非以下兩種情況:

  • app.wxss 或頁面的 wxss 中使用了標(biāo)簽名選擇器(或一些其他特殊選擇器)來直接指定樣式囊咏,這些選擇器會影響到頁面和全部組件恕洲。通常情況下這是不推薦的做法。
  • 指定特殊的樣式隔離選項(xiàng) styleIsolation 梅割。
Component({
  options: {
    styleIsolation: 'isolated'
  }
})

styleIsolation的選項(xiàng):
?isolated 表示啟用樣式隔離霜第,在自定義組件內(nèi)外,使用 class 指定的樣式將不會相互影響(一般情況下的默認(rèn)值)户辞;
?apply-shared 表示頁面 wxss 樣式將影響到自定義組件泌类,但自定義組件 wxss 中指定的樣式不會影響頁面;
?shared 表示頁面 wxss 樣式將影響到自定義組件底燎,自定義組件 wxss 中指定的樣式也會影響頁面和其他設(shè)置了 apply-shared 或 shared 的自定義組件刃榨。(這個選項(xiàng)在插件中不可用。)

使用后兩者時双仍,請務(wù)必注意組件間樣式的相互影響枢希。

如果這個Component 構(gòu)造器用于構(gòu)造頁面,則默認(rèn)值為 shared 朱沃,且還有以下幾個額外的樣式隔離選項(xiàng)可用:

  • page-isolated 表示在這個頁面禁用 app.wxss 苞轿,同時,頁面的 wxss 不會影響到其他自定義組件逗物;
  • page-apply-shared 表示在這個頁面禁用 app.wxss 搬卒,同時,頁面 wxss 樣式不會影響到其他自定義組件敬察,但設(shè)為 shared 的自定義組件會影響到頁面秀睛;
  • page-shared 表示在這個頁面禁用 app.wxss ,同時莲祸,頁面 wxss 樣式會影響到其他設(shè)為 apply-sharedshared 的自定義組件蹂安,也會受到設(shè)為 shared 的自定義組件的影響

在 Component 的 options中設(shè)置addGlobalClass: true 椭迎。 這個選項(xiàng)等價于設(shè)置 styleIsolation: apply-shared,但設(shè)置了 styleIsolation 選項(xiàng)后這個選項(xiàng)會失效田盈。

/* 組件 custom-component.js */
Component({
  options: {
    addGlobalClass: true,
  }
})
3畜号、外部樣式類、引用頁面或父組件的樣式允瞧、虛擬化組件節(jié)點(diǎn)

參見官方文檔:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html

寫在最后:

如果文章中有錯誤或是表達(dá)不準(zhǔn)確的地方简软,歡迎大家評論中指正,以便我完善述暂。
文章我也會根據(jù)所學(xué)到新的知識不斷更新痹升。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市畦韭,隨后出現(xiàn)的幾起案子疼蛾,更是在濱河造成了極大的恐慌,老刑警劉巖艺配,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件察郁,死亡現(xiàn)場離奇詭異,居然都是意外死亡转唉,警方通過查閱死者的電腦和手機(jī)皮钠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赠法,“玉大人麦轰,你說我怎么就攤上這事∑谙海” “怎么了原朝?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵驯嘱,是天一觀的道長镶苞。 經(jīng)常有香客問我,道長鞠评,這世上最難降的妖魔是什么茂蚓? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮剃幌,結(jié)果婚禮上聋涨,老公的妹妹穿的比我還像新娘。我一直安慰自己负乡,他們只是感情好牍白,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著抖棘,像睡著了一般茂腥。 火紅的嫁衣襯著肌膚如雪狸涌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天最岗,我揣著相機(jī)與錄音帕胆,去河邊找鬼。 笑死般渡,一個胖子當(dāng)著我的面吹牛懒豹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播驯用,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼脸秽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蝴乔?” 一聲冷哼從身側(cè)響起豹储,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎淘这,沒想到半個月后剥扣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铝穷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年钠怯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片曙聂。...
    茶點(diǎn)故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡晦炊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宁脊,到底是詐尸還是另有隱情断国,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布榆苞,位于F島的核電站稳衬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏坐漏。R本人自食惡果不足惜薄疚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望赊琳。 院中可真熱鬧街夭,春花似錦、人聲如沸躏筏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽趁尼。三九已至埃碱,卻和暖如春碴卧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背乃正。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工住册, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瓮具。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓荧飞,卻偏偏與公主長得像,于是被迫代替她去往敵國和親名党。 傳聞我的和親對象是個殘疾皇子叹阔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評論 2 359