1. 程式人生 > >微信小程式之自定義select下拉選項框元件

微信小程式之自定義select下拉選項框元件

知識點元件animation獲取當前點選元素的索引與內容

微信小程式中沒有select下拉選項框,所以只有自定義。自定義的話,可以選擇模板的方式,也可以選擇元件的方式來建立。

這次我選擇了元件,這樣只需引入元件和新增資料,其它的不用管,就能實現多個地方重複使用了。

第一步:建立元件所需的檔案

我喜歡把共用的內容都放在和pages檔案同級的地方,所以有了下面的目錄結構

 

(1) 先建立一個自定義名字的資料夾,例如我上面的Componet

(2) 再建立一個select資料夾,然後:右鍵這個資料夾,新建下面的這個Component。然後輸入需要建立的名稱,我這裡為了方便就取了select的名字。然後就會自動建立4個檔案,js、json、wxml、wxss。

第二步:開始配置元件

注意:如果通過第一步建立的可直接跳過第二步。

(1) 通過第一步建立的元件的資料夾中,已經自動配置好了。只需在引入元件的時候,在引入元件的頁面的json檔案中配置元件的名稱和元件的位置。

(2) 如果自己手動建立元件的js、json、wxml、wxss這個檔案,那麼需要在json檔案中填入 "component": true 表示自定義元件宣告。js檔案中也需要寫成這種格式: 

複製程式碼

Component({
  properties: {
    // 這裡定義了innerText屬性,屬性值可以在元件使用時指定
    innerText: {
      type: String,
      value: 'default value',
    }
  },
  data: {
    // 這裡是一些元件內部資料
    someData: {}
  },
  methods: {
    // 這裡是一個自定義方法
    customMethod: function(){}
  }
})

複製程式碼

第三步:自定義元件樣式及js。

注意:這裡可以在 app.json 的 pages 中把元件所在的頁面放到第一位,這樣就能在元件的頁面編寫程式碼了,比如我上面的目錄結構:就需要寫成 "Componet/select/select", 後面再是其它的頁面。這樣方便得多。

1. 元件的wxml

複製程式碼

<view class='com-selectBox'>
    <view class='com-sContent' bindtap='selectToggle'>
        <view class='com-sTxt'>{{nowText}}</view>
        <image src='../../public/img/local/down.png'  class='com-sImg'  animation="{{animationData}}"></image>
    </view>
    <view class='com-sList' wx:if="{{selectShow}}">
        <view wx:for="{{propArray}}" data-index="{{index}}" wx:key='' class='com-sItem' bindtap='setText'>{{item.text}}</view>
    </view>
</view>

複製程式碼

(1)  animation="{{animationData}}" 這個是下箭頭的動畫效果

(2)  data-index="{{index}}" 這個是當前元素被點選時的索引

(3) selectToggle是模仿下拉選項框隱藏和顯示的事件。

(4) setText是模仿下拉選項框選擇子項之後,設定內容的事件。

(5) selectShow是表示option選項顯示與否

2. 元件的wxss

複製程式碼

.com-selectBox{
    width: 200px;
}
.com-sContent{
    border: 1px solid #e2e2e2;
    background: white;
    font-size: 16px;
    position: relative;
    height: 30px;
    line-height: 30px;
}
.com-sImg{
    position: absolute;
    right: 10px;
    top: 11px;
    width: 16px;
    height: 9px;
    transition: all .3s ease;
}
.com-sTxt{
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding:0 20px 0 6px;
    font-size: 14px;
}
.com-sList{
    background: white;
    width: inherit;
    position: absolute;
    border: 1px solid #e2e2e2;
    border-top: none;
    box-sizing: border-box;
    z-index: 3;
    max-height: 120px;
    overflow: auto;
}
.com-sItem{
    height: 30px;
    line-height: 30px;
    border-top: 1px solid #e2e2e2;
    padding: 0 6px;
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 14px;
}
.com-sItem:first-child{
    border-top: none;
}

複製程式碼

 3. 元件的 js

複製程式碼

// Componet/Componet.js
Component({
  /**
   * 元件的屬性列表
   */
    properties: {
        propArray:{
            type:Array,
        }
    },
  /**
   * 元件的初始資料
   */
    data: {
        selectShow:false,//初始option不顯示
        nowText:"請選擇",//初始內容
        animationData:{}//右邊箭頭的動畫
    },
  /**
   * 元件的方法列表
   */
    methods: {
   //option的顯示與否
        selectToggle:function(){
            var nowShow=this.data.selectShow;//獲取當前option顯示的狀態
            //建立動畫
            var animation = wx.createAnimation({
                timingFunction:"ease"
            })
            this.animation=animation;
            if(nowShow){
                animation.rotate(0).step();
                this.setData({
                    animationData: animation.export()
                })
            }else{
                animation.rotate(180).step();                
                this.setData({
                    animationData: animation.export()
                })
            }
            this.setData({
                selectShow: !nowShow
            })
        },
        //設定內容
        setText:function(e){
            var nowData = this.properties.propArray;//當前option的資料是引入元件的頁面傳過來的,所以這裡獲取資料只有通過this.properties
            var nowIdx = e.target.dataset.index;//當前點選的索引
            var nowText = nowData[nowIdx].text;//當前點選的內容
            //再次執行動畫,注意這裡一定,一定,一定是this.animation來使用動畫
            this.animation.rotate(0).step();
            this.setData({
                selectShow: false,
                nowText:nowText,
                animationData: this.animation.export()
            })
        }
    }
})

複製程式碼

(1) 元件的 properties 屬性是對外屬性,我理解的是可以當做 data 資料來使用,它是一個含有三個屬性的物件,分別是 type 表示屬性型別、 value 表示屬性初始值、 observer 表示屬性值被更改時的響應函式。type 是必填的,其它的可選。如果只有 type,可以寫成:屬性名:type型別。

(2) 元件的 data 和普通頁面的data一樣,是元件的內部資料,和 properties 一同用於元件的模版渲染。

(3) 元件的 method 是專門用於 事件響應函式 和 任意的自定義方法。在這裡面獲取資料有兩種方法:一種是獲取data裡的資料:this.data.屬性名;一種是獲取 properties 中的屬性值: this.properties.屬性名

(4) 建立animation動畫,作用在通過 true 和 false 切換顯示狀態的內容上沒有過渡、沒有過渡、沒有過渡

第四步:引入元件,傳入元件所需資料

1. 引入前,需要在引入元件的頁面的json檔案中配置,比如我要在 index.wxml 中引入,那麼在 index.json 中我就需要配置:

"usingComponents": {
    "Select": "/Componet/select/select"
}

(1) Select 是你定義的元件的名稱,後面的是元件所在的位置。 /  單斜槓表示根目錄,是絕對路徑。

(2) 如果出現下面這種說沒找到路徑的,一定是自己填寫的路徑不對,認真查詢。

2. 配置好後,就可以引入元件。

<Select prop-array='{{selectArray}}'></Select>

(1) prop-array 是我自定義的屬性名,這個是和元件所在的 js 中properties中的屬性是對應的。在 properties 定義的屬性中,屬性名採用駝峰寫法(例如:propArray);在引入元件的 wxml 中,指定屬性值時則對應使用連字元寫法(例如:prop-array="...")。

3. 最後就是傳入資料了。在引入元件的js的data中,新增:

複製程式碼

selectArray: [{
    "id": "10",
    "text": "會計類"
}, {
    "id": "21",
    "text": "工程類"
}]

複製程式碼

 最終結果:

 如果引入兩個相同的元件,傳入的資料也相同: 

<Select prop-array='{{selectArray}}'></Select>
<Select prop-array='{{selectArray}}'></Select>

 這樣的方式元件並不會相互影響,都是獨立的。   

對了,元件樣式的規則可以檢視官方的規則

第五步:獲取點選的內容,即元件間的通訊

效果有了,最關鍵的是獲取選中的內容。這個怎麼實現呢,這時候需要組建間通訊與事件了。

1. 對元件的事件進行監聽:

<Select prop-array='{{selectArray}}' bind:myget='getDate'></Select>

(1) 這裡myget是自定義的子元件需要觸發的事件名,getDate是引入元件的頁面需要獲取傳過來的資料的自定義的事件名。

2. 子元件觸發事件

因為這裡的select元件是點選下拉列表的內容才進行內容的更新,所以這裡只需要在下拉列表裡新增一個點選事件,而原來已經設定了setText事件。所以只需要在setText函式裡面寫觸發事件就行了。

在setText函式的內容里加上:

var nowDate={
    id:nowIdx,
    text:nowText
}
this.triggerEvent('myget', nowDate)

(1) 這裡的 myget 和 bind:myget ,名稱一定要對應。

(2) nowDate是需要傳回的資料,不一定要弄成物件,想傳什麼傳什麼,我這裡只是演示而已。我試了一下也可以傳函式。。。

3. 引入元件的頁面的js

新增引入元件時,自定義的函式:

getDate:function(e){
    console.log(e.detail)
}

e的內容為:

傳過來的值就在detail裡面。

到此,一個完整的select元件就完成了。