微信小程序自定義標簽組件component封裝、組件生命周期,組件通信

微信小程序自定義標簽組件component封裝、組件生命周期,組件通信

本文來說下小程序的自定義標簽組件封裝。
相比于vue,react的非路由組件,微信小程序的component組件要麻煩些,而且生命周期,數(shù)據(jù)接收傳遞方式也和路由組件不同!
假設(shè)你已經(jīng)創(chuàng)建好了微信小程序項目!

新建component組件

本文以封裝一個可用于關(guān)閉,添加,刪除的按鈕組件為例。
首先找到項目里面pages文件夾,鼠標右鍵pages文件夾,選擇新建目錄,輸入名字globalComponents,該文件夾用于存放component組件。鼠標右鍵globalComponents文件夾,選擇新建目錄,輸入名字closeAddReduceBtn,再右鍵closeAddReduceBtn文件夾,選擇新建Component,輸入名字closeAddReduceBtn。現(xiàn)在一個名為closeAddReduceBtn的component組件就創(chuàng)建好了。


在這里插入圖片描述

component組件配置

創(chuàng)建好closeAddReduceBtn組件后,到pages下面的index文件夾,找到index.json文件,加上component組件配置,即usingComponents配置項。
index.json文件代碼:

{
  "usingComponents": {
   "Radios": "../../globalComponents/Radios/closeAddReduceBtn"
  }
}

此行: "Radios": "../../globalComponents/closeAddReduceBtn/closeAddReduceBtn",closeAddReduceBtn是自定義的標簽名,后面是組件相對路徑

引入標簽組件

配置好后,到index.wxml文件中,寫上自定義標簽組件即可


在這里插入圖片描述

component組件關(guān)鍵生命周期

這里只說關(guān)鍵,重要的生命周期
打開closeAddReduceBtn.js,我們可以看到,里面的內(nèi)容,不同玉路由組件,component組件是由Component構(gòu)造函數(shù)渲染的,onLoad,onShow什么的都沒了。

// globalComponents/closeAddReduceBtn/closeAddReduceBtn.js
Component({
  /**
   * 組件的屬性列表
   */
  properties: {

  },

  /**
   * 組件的初始數(shù)據(jù)
   */
  data: {

  },

  /**
   * 組件的方法列表
   */
  methods: {

  }
})

properties 是屬性列表,通常用于接收父組件傳遞的值
data 用于存放組件本身的值
methods 用于存放自定義的函數(shù),類似vue的methods,在component里面,你直接像在路由組件里面寫方法是不能生效的,方法必須寫在methods里面。
組件加載執(zhí)行的函數(shù)是attached() {},需要我們手動加上,
組件頁面初始化完成執(zhí)行的函數(shù)是ready(){},手動給加上后,組件代碼

// globalComponents/closeAddReduceBtn/closeAddReduceBtn.js
Component({
  /**
   * 組件的屬性列表
   */
  properties: {

  },

  /**
   * 組件的初始數(shù)據(jù)
   */
  data: {

  },
  /**
  *組件加載執(zhí)行
  */
  attached() {
  },
   /**
  *組件初始化完成執(zhí)行
  */
  ready(){
  },
  /**
   * 組件的方法列表
   */
  methods: {

  }
})

closeAddReduceBtn組件頁面構(gòu)建

下面我們將closeAddReduceBtn組件頁面寫完
closeAddReduceBtn.wxml

<view  
   class="closeAddReduceBox"
   style="width:{{boxSize}}rpx;height:{{boxSize}}rpx;background-color:{{boxBackgroundColor}};border-width:{{boxBorderWidth}}rpx; transform: rotate({{rotate}});border-color:{{boxBorderColor}}"
   bindtap="clickBtn"
   >
  <text style="background-color:{{childBackgroundColor}};width:{{firstChildWidth}}rpx;height:{{firstChildHeight}}rpx"></text>
  <text wx:if="{{!isSingle}}" style="background-color:{{childBackgroundColor}};width:{{lastChildWidth}}rpx;height:{{lastChildHeight}}rpx"></text>
</view>

closeAddReduceBtn.wxss

.closeAddReduceBox{
  position: relative;
  border-radius: 50%;
  border-style: solid;
}
.closeAddReduceBox text{
  position: absolute;
  left:50%;
  top:50%;
  transform: translate(-50%,-50%)  
}

需要重點說的是closeAddReduceBtn.js
首先在properties中定義需要父組件傳遞的數(shù)據(jù),定義數(shù)據(jù)為對象,其中type屬性是定義接收的數(shù)據(jù)類型,value是默認值,如果需要默認值,可以在value里面定義。observer是定義傳遞值有變化時的監(jiān)聽函數(shù),不過注意observer的值是函數(shù)名字符串,然后需要到methods中定義該函數(shù)
屬性示例:
boxSize:{
type:Number,
value: 32,
observer:"getBoxSize"
},//按鈕尺寸

Component({
  /**
   * 組件的屬性列表
   */
  properties: {
    boxSize:{
      type:Number,
      value: 32,
      observer:"getBoxSize"
    },//按鈕尺寸
    boxBackgroundColor:{
      type:String
    },//背景顏色
    boxBorderWidth:{
      type:Number
    },//邊框?qū)挾?    boxBorderColor:{
      type: String
    },//邊框顏色
    rotate:{
      type:String
    },//選擇角度
    childBackgroundColor:{
      type:String,
      value:'#ffffff'
    },//按鈕里面橫線顏色,即加減圖標顏色
    childSize:{
      type:Number,
      value:0
    },//按鈕里面橫線尺寸,即加減圖標尺寸
    isSingle:{
      type:Boolean,
      value:false
    },//是否只有一條線,即刪除按鈕,或者減號按鈕
    bold:{
      type:Boolean,
      value:false
    }//是否加粗邊框
  },

  /**
   * 組件的初始數(shù)據(jù)
   */
  data: {
    firstChildWidth:0,//第一根橫線寬度
    firstChildHeight:0,//第一根橫線高度
    lastChildWidth:0,//第二根橫線寬度
    lastChildHeight:0,//第二根橫線高度
  },
    /**
  *組件加載執(zhí)行
  */
  attached() { 
    let { boxSize, boxBorderWidth, boxBorderColor, childSize, childHeight, rotate, onPressFun, bold } = this.data
    if (boxSize !== 32) {
      ; !childSize && (childSize = (20 / 32) * boxSize)
      // console.log(boxSize)
        ; !childHeight && (childHeight = (2 / 20) * childSize)
    }
    
    ; !childSize && (childSize = 20)
      ; !childHeight && (childHeight = 2)
    childHeight = bold ? (childHeight + 2) : childHeight
    boxBorderColor && !boxBorderWidth && (boxBorderWidth = 2)
    // console.log(boxBorderWidth)
    this.setData({
      firstChildWidth:childSize,
      firstChildHeight: childHeight,
      lastChildWidth: childHeight,
      lastChildHeight: childSize,
      boxBorderWidth
    })
  },

  /**
   * 組件的方法列表
   */
  methods: {
  //a按鈕點擊事件
    clickBtn(){
    //組件按鈕點擊事件,若需要向父組件傳遞數(shù)據(jù)或者讓父組件監(jiān)聽到相應(yīng)的操作,通過this.triggerEnent向父組件傳遞,三個參數(shù),第一個參數(shù)是父組件的監(jiān)聽事件名,第二個是傳遞給父組件的值,第三個參數(shù)是觸發(fā)事件的選項
    let value='click'
    let eventOption={
        bubbles:false,//    默認false,事件是否冒泡
        composed:false,//   默認false,事件是否可以穿越組件邊界,為false時,事件將只能在引用組件的節(jié)點樹上觸發(fā),不進入其他任何組件內(nèi)部
        capturePhase:false,//   默認false,事件是否擁有捕獲階段
    }
      this.triggerEvent('event',value,eventOption)
    },
    //尺寸監(jiān)聽
    getBoxSize(value){
    //value是監(jiān)聽到的值
    console.log(value)
    }
  }
})

父組件使用

接下來看父組件的使用
在index.wxml中

<closeAddReduceBtn class="closeAddReduceBtn" boxBackgroundColor="#999999" rotate="45deg" bindevent="delImg" data-index="{{index}}"/>

將需要的屬性直接傳遞即可。

特別注意的是bindevent,這是bind和組件事件名event的組合,event就是組件里面this.triggerEvent('event',value,eventOption)定義的event,假設(shè)我們在組件里面寫成this.triggerEvent('getBtn',value,eventOption),那么在父組件就要對應(yīng)寫成bingetBtn

下面看父級組件觸發(fā)的事件,component組件向父級組件傳遞的數(shù)據(jù),父級組件通過e.detail獲取

// 刪除圖片
  delImg(e){
    let {index}=e.currentTarget.dataset
    let value=e.detail //value是component組件向父組件傳遞的數(shù)據(jù)
    console.log(value)
    let { showImgs}=this.data
    showImgs.splice(index,1)
    this.setData({
      showImgs
    })
  },

關(guān)鍵生命周期函數(shù)的其他寫法以及其他類型生命周期

關(guān)鍵生命周期函數(shù)也可以用下面寫法

lifetimes: {
  attached: function () {
    // 在組件實例進入頁面節(jié)點樹時執(zhí)行
   
  },
  detached: function () {
    // 在組件實例被從頁面節(jié)點樹移除時執(zhí)行
  },
},

即將函數(shù)都寫在lifetimes中。

還有一些特殊的生命周期,它們并非與組件有很強的關(guān)聯(lián),但有時組件需要獲知,以便組件內(nèi)部處理。這樣的生命周期稱為“組件所在頁面的生命周期”,在 pageLifetimes 定義段中定義

 pageLifetimes: {
  show: function() {
    // 頁面被展示
  },
  hide: function() {
    // 頁面被隱藏
  },
  resize: function(size) {
    // 頁面尺寸變化
  }
}

在 behaviors 中也可以編寫生命周期方法,同時不會與其他 behaviors 中的同名生命周期相互覆蓋。但要注意,如果一個組件多次直接或間接引用同一個 behavior ,這個 behavior 中的生命周期函數(shù)在一個執(zhí)行時機內(nèi)只會執(zhí)行一次。

behaviors :{
      created(){
      },  //在組件實例剛剛被創(chuàng)建時執(zhí)行
      attached(){
      },//在組件實例進入頁面節(jié)點樹時執(zhí)行
      ready(){
      },//在組件在視圖層布局完成后執(zhí)行  
      moved(){
      },//在組件實例被移動到節(jié)點樹另一個位置時執(zhí)行    
      detached(){
      },//在組件實例被從頁面節(jié)點樹移除時執(zhí)行   
      error(){
      },//Object Error    每當組件方法拋出錯誤時執(zhí)行   
}

配置全局組件

有些組件,我們可能在很多頁面都會使用,因此希望只做一次配置即可,只需要在app.json中添加usingComponents配置即可
app.json

{
"pages": [
  "pages/index/index",
  "pages/hmongb/hmongb"
],
"window": {
  "backgroundColor": "#633319",
  "backgroundTextStyle": "light",
  "navigationBarBackgroundColor": "#633319",
  "navigationBarTitleText": "苗文hmongb",
  "navigationBarTextStyle": "white"
},
"tabBar": {
  "selectedColor": "#633319",
  "color": "#898888",
  "list": [
    {
      "iconPath": "./images/index-gray.png",
      "selectedIconPath": "./images/index-active.png",
      "text": "查詢",
      "backgroundColor": "#ffffff",
      "pagePath": "pages/index/index"
    },
    {
      "iconPath": "./images/hmongb-gray.png",
      "selectedIconPath": "./images/hmongb-active.png",
      "text": "我的",
      "backgroundColor": "#ffffff",
      "pagePath": "pages/hmongb/hmongb"
    }
  ]
},
  "subpackages": [
    {
      "name": "hmongbPage",
      "root": "hmongbPage",
      "pages": [
        "giveUsMsg/giveUsMsg"
      ]
    }
  ],
"sitemapLocation": "sitemap.json",
"style": "v2",
"usingComponents": {
  "Radios": "../../globalComponents/Radios/Radios",
   "doubleTopBar": "../../globalComponents/doubleTopBar/doubleTopBar",
  "leftScroll": "../../globalComponents/leftScroll/leftScroll",
  "searchTopBar": "../../globalComponents/searchTopBar/searchTopBar",
  "topTitleBar": "../../globalComponents/topTitleBar/topTitleBar"
}
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容