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

設計需求以下,根據使用功能塊的不一樣,有三種大小的評分設計。json

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

那麼徹底能夠把上述的不一樣做爲properties傳入自定義組件,來實現不一樣的需求功能。app

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

第一步在star.json中咱們須要這麼配置:flex

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

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

而後咱們在star.wxml中編寫組件的基本機構和須要綁定的屬性,值和事件:spa

<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 爲數據對象、3d

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

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 事件就不用定義了。

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

相關文章
相關標籤/搜索