设计需求以下,根据使用功能块的不一样,有三种大小的评分设计。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 事件就不用定义了。
以上是在工做中的小小尝试和总结,若是有错误的地方或者是更优质的编写方法,欢迎指正分享。