自定義微信小程序的星星評分組件


設計需求如下,根據使用功能塊的不同,有三種大小的評分設計。

 由於需求中的設計樣式與功能基本一致,只是在不同顯示區域的大小有些區別。還有就是一些功能上的,如:多事件監聽,只讀。

那么完全可以把上述的不同作為properties傳入自定義組件,來實現不同的需求功能。

那么就先配置好自定義組件的相關文件,首先我們可定義一個文件夾custom-star,包含文件有star.wxml, star.js, star.json, star.wxss。

第一步在star.json中我們需要這么配置:

{
  "component": true,
  "usingComponent": ""
}

將 component字段設為 true 可將這一組文件設為自定義組件。而 usingComponent 這一字段是作為引用組件的頁面的json的聲明配置項,其值為引用的組件路徑。

然后我們在star.wxml中編寫組件的基本機構和需要綁定的屬性,值和事件:

<view class="star_wrapper star_wrapper_{{starSize}}">
  <view wx:for="{{star}}" wx:key="{{item.id}}" data-index="{{item.id}}" data-gradable="{{gradable}}" bindtap="grade">
    <image src="{{item.id > score ? defaultSrc : activeSrc}}"></image>
  </view>
</view>

starSize 我們作為定義組件顯示的樣式屬性,通過properties來獲取,默認值為normal。對應的還有small, large。這個對應相關的wxss來顯示相應的效果、

star 為數據對象、

gradable 為當前組件是否可評分(非只讀)、

grade 即為點擊事件、

通過點擊事件來改變score值,而來改變image點亮狀態。

對應的star.wxss:

view{box-sizing: border-box;}
/* 注意組件的寬度,默認橫向撐開整個容器 */
.star_wrapper{
  display: flex;
  flex: row;
  justify-content: space-between;
  width: 100%;
  height: auto;
}
.star_wrapper_normal image{
  width: 38rpx;
  height: 36rpx;
}
.star_wrapper_large image{
  width: 52rpx;
  height: 50rpx;
}
.star_wrapper_small image{
  width: 30rpx;
  height: 28rpx;
}

star.js:

Component({
  properties: {
    /**
    * 組件大小
    * small: 小
    * normal: 正常
    * large: 大
    */ 
    starSize: {
      type: String,
      value: 'normal'
    },
    // 評分值
    score: {
      type: Number,
      value: 0
    },
    // 同時使用多個組件,事件監聽的方法名
    starIdx: {
      type: String,
      value: 'I'
    },
    // 是否可評分
    gradable: {
      type: Boolean,
      value: true
    }
  },
  data: {
    star: [
      {id: 1},
      {id: 2},
      {id: 3},
      {id: 4},
      {id: 5}
    ],
    defaultSrc: '/image/star.png',
    activeSrc: '/image/star_active.png'
  },
  // 組件生命周期
  lifetimes: {
    attached () {

    },
    detached () {

    }
  },
  // 兼容v2.2.3以下寫法
  attached () {

  },
  // 掛載頁面的生命周期
  pageLifetimes: {

  },
  methods: {
    grade (e) {
      // 如果只是展示分值,就屏蔽評分
      if (!this.data.gradable) return;
      this.setData({
        score: e.currentTarget.dataset.index
      }, () => {
        const scoreDetail = {
          score: e.currentTarget.dataset.index
        };
        let evenName = 'getscore' + this.data.starIdx;
        this.triggerEvent(evenName, scoreDetail)
      })
    }
  }
})

js中我還定義了一個starIdx, 這里我的思路是如果一個頁面有多個star組件被引用了。需要在該頁面監聽不同的子組件事件,用這個字段來作區別。

下面我們就可以在其他常規頁面中去引用這個組件了。首先在.json文件中,先聲明一下:

{
  "usingComponents": {
    "star": "/custom-star/star"
  }
}

然后就直接引用了。注意傳值和事件的定義:

<view class="container">
  <star bind:getscoreI="getscoreI" starSize="{{stars[0].starSize}}" score="{{stars[0].score}}" starIdx="{{stars[0].starIdx}}" gradable="{{stars[0].gradable}}"></star>
  <star bind:getscoreII="getscoreII" starSize="{{stars[1].starSize}}" score="{{stars[1].score}}" starIdx="{{stars[1].starIdx}}"></star>
  <star bind:getscoreIII="getscoreIII" starSize="{{stars[2].starSize}}" score="{{stars[2].score}}" starIdx="{{stars[2].starIdx}}"></star>
</view>

自定義事件 bind:getscoreI、bind:getscoreII、bind:getscoreIII。與組件中的 triggerEvent 對應,是我們在本頁面需要監聽的對應事件。


需要說一下的是,在讀官方文檔時,他是這么介紹模板數據綁定的:

然后我在使用時傻傻的在每個屬性值前面都加了前綴 “prop-”,這么根本就拿不到值。;);)


 

那么在引用頁面中,就只需要傳一些對應的數據和定義一些對應事件了。 stars:渲染的數據數組對象,getscoreI...這幾個事件。

Page({
  /**
   * 頁面的初始數據
   */
  data: {
    stars: [
      {
        starSize: 'large',
        score: 5,
        starIdx: 'I',
        gradable: false
      },
      {
        starSize: 'normal',
        score: 1,
        starIdx: 'II'
      },
      {
        starSize: 'small',
        score: 4,
        starIdx: 'III'
      }
    ]
  },
  getscoreII(e) {
    console.log(e)
  },
  getscoreIII(e) {
    console.log(e)
  }
})

說明:stars 中第一個數據對象中的gradable為false,即這個渲染結果是只讀的,不可點擊。所以 getscoreI 事件就不用定義了。

以上是在工作中的小小嘗試和總結,如果有錯誤的地方或者是更優質的編寫方法,歡迎指正分享。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM