WeChat-SmallProgram:自定义select下拉选项框组件
1):创建组件所需的文件
2):自定义组件 CSS 及 JS
组件的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选项显示与否
组件的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; }
组件的 js:
// components/select.js Component({ /** * 组件的属性列表 */ properties: { propArray: { type: Array, } }, /** * 组件的初始数据 */ data: { selectShow: false, //初始option不显示 nowText: "请选择分类", //初始内容 animationData: {} //右边箭头的动画 }, /** * 组件的方法列表 */ methods: { //option的显示与否 selectToggle: function() { console.log("select-selectToggle"); 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) { console.log("select-setText"); var nowData = this.properties.propArray; //当前option的数据是引入组件的页面传过来的,所以这里获取数据只有通过this.properties var index = e.target.dataset.index; //当前点击的索引 var nowId = nowData[index].id; var nowText = nowData[index].text; //当前点击的内容 //再次执行动画,注意这里一定,一定,一定是this.animation来使用动画 this.animation.rotate(0).step(); this.setData({ selectShow: false, nowText: nowText, animationData: this.animation.export() }); var nowDate = { id: nowId, text: nowText } this.triggerEvent('myget', nowDate) }, // 初始化数据 initData(e) { console.log("select-initData"); this.setData({ selectShow: false, //初始option不显示 nowText: "请选择分类", //初始内容 animationData: {} //右边箭头的动画 }); } } })
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 中我就需要配置:
1):sub-unit-select 是你定义的组件的名称,后面的是组件所在的位置。 / 单斜杠表示根目录,是绝对路径。
2):如果出现下面这种说没找到路径的,一定是自己填写的路径不对,认真查找。
配置好后,就可以引入组件:
<sub-unit-select id="init" prop-array='{{selectArray}}' bind:myget='getDataSelect'></sub-unit-select>
1):prop-array 是我自定义的属性名,这个是和组件所在的 js 中properties中的属性是对应的。
在 properties
定义的属性中,属性名采用驼峰写法(例如:propArray);在引入组件的 wxml
中,指定属性值时则对应使用连字符写法(例如:prop-array="..."
)。
2):id="init" 也是自定义的属性 用来获取组件信息。例如我们要在引用页面 调用 组件内的方法。
onLoad: function(options) { console.log("album-details-onload"); // 获取引用组件信息 this.compData = this.selectComponent("#init") }, // 自定义事件 modalCancel(e) { console.log("album-details-modalCancel"); var _this = this; this.compData.initData(); },
3):bind:myget='getDataSelect' 获取点击的内容,即组件间的通信。效果有了,最关键的是获取选中的内容。这个怎么实现呢,这时候需要 组建间通信与事件 了。
这里myget是自定义的子组件需要触发的事件名,getDataSelect 是引入组件的页面需要获取传过来的数据的自定义的事件名。
子组件触发事件:
因为这里的select组件是点击下拉列表的内容才进行内容的更新,所以这里只需要在下拉列表里添加一个点击事件,而原来已经设置了setText事件。
所以只需要在setText函数里面写触发事件就行了。
var nowDate = {
id: nowId,
text: nowText
}
this.triggerEvent('myget', nowDate)
这里的 myget 和 bind:myget ,名称一定要对应。
nowDate是需要传回的数据,不一定要弄成对象,想传什么传什么,我这里只是演示而已。我试了一下也可以传函数。。。
最后就是传入数据了。在引入组件的js的data中,添加:
selectArray: [{ "id": "10", "text": "会计类" }, { "id": "21", "text": "工程类" }]
最终结果:
如果引入两个相同的组件,传入的数据也相同:
<sub-unit-select id="init" prop-array='{{selectArray}}' bind:myget='事件名称2'></sub-unit-select> <sub-unit-select id="init" prop-array='{{selectArray}}' bind:myget='事件名称2'></sub-unit-select>
这样的方式组件并不会相互影响,都是独立的。
对了,组件样式的规则可以查看 官方的规则
在引用组件的页面 JS 中添加函数 :
// 获取下拉框选择的数据 getDataSelect: function(e) { console.log("album-details-getDataSelect"); var _this = this; console.log(e) },
e 的内容:
传过来的值就在detail里面。
到此,一个完整的select组件就完成了。
You have to work hard to look effortless
You're going to sneak up and surprise everyone