微信小程序自定义日期选择器
短信预约 -IT技能 免费直播动态提醒
日期选择器是我们在写项目的过程中经常遇到的,有需要标题的选择器,也有不需要标题的选择器
今天给大家带来一个自定义的时间选择器,废话不多说,直接上代码
第一步:先创建一个picker的文件夹
第二步 :在wxml中写布局样式
<!--picker/picker.wxml-->
<view class="full-box {{isOpen?'cur':''}}">
<!--<view class="modal" bindtap="tapModal"></view>-->
<view class="picker">
<view class="picker-header">
<view bindtap="cancle" >
<text>{{cancelText}}</text>
</view>
<text style="font-weight: bold;">{{titleText}}</text>
<view bindtap="sure">
<text style="color:aqua;">{{sureText}}</text>
</view>
</view>
<picker-view
value="{{value}}"
class="picker-content"
bindpickstart="_bindpickstart"
bindchange="_bindChange"
bindpickend="_bindpickend"
indicator-style="{{indicatorStyle}}"
mask-style="{{maskStyle}}"
>
<picker-view-column wx:for="{{columnsData}}" wx:key="{{index}}">
<view wx:for="{{item}}" wx:for-item="itemIn" class="picker-line" wx:key="{{index}}">
<text class="line1">{{isUseKeywordOfShow?itemIn[keyWordsOfShow]:itemIn}}</text>
</view>
</picker-view-column>
</picker-view>
</view>
</view>
第三步:wxss中添加样式
.full-box{
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
z-index: 9999;
opacity: 0;
background:rgba(0,0,0,.4);
transition:all .4s ease-in-out 0;
pointer-events:none;
}
.full-box.cur{
opacity:1;
pointer-events:auto
}
.modal{
position: absolute;
width: 100%;
height: 50%;
bottom:-50%;
left: 0;
background: transparent;
transition:all .4s ease-in-out 0;
}
.picker{
position: absolute;
width: 100%;
height: 235px;
bottom: -235px;
left: 0;
background: #fff;
display: flex;
flex-direction: column;
transition:all .4s ease-in-out 0;
}
.cur .picker{
bottom:0;
}
.cur .modal{
bottom:50%;
}
.picker-line{
display: flex;
justify-content: center;
align-items: center;
}
.picker-header {
height: 20%;
box-sizing: border-box;
padding: 0 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #eeeeee;
}
.picker-header view {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.picker-header view text{
font-size: 36rpx;
}
.picker-content {
flex-grow: 1;
}
.line1{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
lines:1
}
第四步:在js中写组件的属性
// picker/picker.js
import { isPlainObject } from './tool'
Component({
properties: {
scrollType: {
type: String,
value: 'normal'// "link": scroll间联动 "normal": scroll相互独立
},
listData: {
type: Array,
value: [],
observer: function(newVal) {
if (newVal.length === 0 || this._compareDate()) return
this._setTempData()
const tempArr = [...new Array(newVal.length).keys()].map(() => 0)
this.data.lastValue = this.data.tempValue = tempArr
this._setDefault()
// let {defaultPickData} = this.properties;
// if(newVal.length === 0) return;
//
// this._setDefault(newVal, defaultPickData)
}
},
defaultPickData: {
type: Array,
value: [],
observer: function(newVal) {
if (newVal.length === 0 || this._compareDate()) return
this._setTempData()
this._setDefault()
}
},
keyWordsOfShow: {
type: String,
value: 'name'
},
isShowPicker: {
type: Boolean,
value: false,
observer: function(newVal) {
if (newVal) {
this._openPicker()
} else {
this._closePicker()
}
}
},
titleText: {// 标题文案
type: String,
value: '请选择到馆日期'
},
cancelText: {// 取消按钮文案
type: String,
value: '取消'
},
sureText: {// 确定按钮文案
type: String,
value: '确定'
},
},
data: {
columnsData: [],
value: [],
backData: [],
height: 0,
isOpen: false,
isUseKeywordOfShow: false,
scrollEnd: true, // 滚动是否结束
lastValue: [], // 上次各个colum的选择索引
tempValue: [],
isFirstOpen: true,
onlyKey: '',
defaultPickDataTemp: '',
listDataTemp: ''
},
methods: {
tapModal() {
this.properties.isShowPicker = false
this._closePicker()
},
cancle() {
this.triggerEvent('cancle')
this._closePicker()
},
sure() {
const { scrollEnd, tempValue } = this.data
if (!scrollEnd) return
const backData = this._getBackDataFromValue(tempValue)
this.setData({
backData
})
this.triggerEvent('sure', {
choosedData: backData,
choosedIndexArr: tempValue
})
this._closePicker()
},
_bindChange(e) {
const { scrollType } = this.properties
const { lastValue } = this.data
let val = e.detail.value
switch (scrollType) {
case 'normal':
this.data.tempValue = val.concat()
this.data.tempValue = val.concat()
break
case 'link':
// let column_02 = this._getColumnData(this.properties.listData[val[0]].children);
// let column_03 = this._getColumnData(this.properties.listData[val[0]].children[val[1]].children);
var tempArray = []
if (val.length > 1) {
val.slice(0, val.length - 1).reduce((t, c, i) => {
const v = t[c].children
tempArray.push(this._getColumnData(v))
return v
}, this.properties.listData)
}
// let columnsData = [this.data.columnsData[0],column_02,column_03];
var columnsData = [this.data.columnsData[0], ...tempArray]
// 设置value关联
var compareIndex = this._getScrollCompareIndex(lastValue, val)
if (compareIndex > -1) {
let tempI = 1
while (val[compareIndex + tempI] !== undefined) {
val[compareIndex + tempI] = 0
tempI++
}
}
val = this._validate(val)
this.data.lastValue = val.concat()
this.data.tempValue = val.concat()
this.setData({
columnsData
// value: val
})
}
},
_validate(val) {
const { columnsData } = this.data
columnsData.forEach((v, i) => {
if (columnsData[i].length - 1 < val[i]) {
val[i] = columnsData[i].length - 1
}
})
this.setData({
value: val
})
return val
},
_bindpickend() {
this.data.scrollEnd = true
},
_bindpickstart() {
this.data.scrollEnd = false
},
_openPicker() {
if (!this.data.isFirstOpen) {
if (this.properties.listData.length !== 0) {
this._setDefault(this._computedBackData(this.data.backData))
}
}
this.data.isFirstOpen = false
this.setData({
isOpen: true
})
},
_closePicker() {
this.setData({
isOpen: false
})
},
_getColumnData(arr) {
return arr.map((v) => this._fomateObj(v))
},
_fomateObj(o) {
const tempO = {}
for (const k in o) {
k !== 'children' && (tempO[k] = o[k])
}
return tempO
},
_getScrollCompareIndex(arr1, arr2) {
let tempIndex = -1
for (let i = 0, len = arr1.length; i < len; i++) {
if (arr1[i] !== arr2[i]) {
tempIndex = i
break
}
}
return tempIndex
},
// 根据id获取索引
_getIndexByIdOfObject(listData, idArr, key, arr) {
if (!Array.isArray(listData)) return
for (let i = 0, len = listData.length; i < len; i++) {
if (listData[i][key] === idArr[arr.length][key]) {
arr.push(i)
return this._getIndexByIdOfObject(listData[i].children, idArr, key, arr)
}
}
},
_setDefault(inBackData) {
const { scrollType } = this.properties
let { listData, defaultPickData } = this.properties
const { lastValue } = this.data
if (inBackData) {
defaultPickData = inBackData
}
let backData = []
switch (scrollType) {
case 'normal':
if (isPlainObject(listData[0][0])) {
this.setData({
isUseKeywordOfShow: true
})
}
if (Array.isArray(defaultPickData) && defaultPickData.length > 0) {
backData = listData.map((v, i) => v[defaultPickData[i]])
this.data.tempValue = defaultPickData
this.data.lastValue = defaultPickData
} else {
backData = listData.map((v) => v[0])
}
this.setData({
columnsData: listData,
backData: backData,
value: defaultPickData
})
break
case 'link':
// let column_01 = this._getColumnData(newVal);
// let column_02 = this._getColumnData(newVal[0].children);
// let column_03 = this._getColumnData(newVal[0].children[0].children);
// let columnsData = [column_01,column_02,column_03];
var columnsData = []
// 如果默认值
if (Array.isArray(defaultPickData) && defaultPickData.length > 0 && defaultPickData.every((v, i) => isPlainObject(v))) {
const key = this.data.onlyKey = Object.keys(defaultPickData[0])[0]
const arr = []
this._getIndexByIdOfObject(listData, defaultPickData, key, arr)
defaultPickData = arr
let tempI = 0
do {
lastValue.push(defaultPickData[tempI])
columnsData.push(this._getColumnData(listData))
listData = listData[defaultPickData[tempI]].children
tempI++
} while (listData)
backData = columnsData.map((v, i) => v[defaultPickData[i]])
// 如果没有默认值
} else {
this.data.onlyKey = this.properties.keyWordsOfShow || 'name'
do {
lastValue.push(0)
columnsData.push(this._getColumnData(listData))
listData = listData[0].children
} while (listData)
backData = columnsData.map((v) => v[0])
}
this.data.tempValue = defaultPickData
this.data.lastValue = defaultPickData
this.setData({
isUseKeywordOfShow: true,
columnsData,
backData
})
setTimeout(() => {
this.setData({
value: defaultPickData
})
}, 0)
break
}
},
_computedBackData(backData) {
const { scrollType, listData } = this.properties
const { onlyKey } = this.data
if (scrollType === 'normal') {
return backData.map((v, i) => listData[i].findIndex((vv, ii) => this._compareObj(v, vv)))
} else {
const t = backData.map((v, i) => {
const o = {}
o[onlyKey] = v[onlyKey]
return o
})
return t
}
},
_compareObj(o1, o2) {
const { keyWordsOfShow } = this.properties
if (typeof o1 !== 'object') {
return o1 === o2
} else {
return o1[keyWordsOfShow] === o2[keyWordsOfShow]
}
},
_getBackDataFromValue(val) {
let tempArr = []
if (val.length > 0) {
tempArr = this.data.columnsData.reduce((t, v, i) => {
return t.concat(v[val[i]])
}, [])
} else {
tempArr = this.data.columnsData.map((v, i) => v[0])
}
return tempArr
},
_compareDate() { // 完全相等返回true
const { defaultPickDataTemp, listDataTemp } = this.data
const { defaultPickData, listData } = this.properties
return defaultPickDataTemp === defaultPickData && listDataTemp === listData
},
_setTempData() {
const { defaultPickData, listData } = this.properties
this.data.defaultPickDataTemp = defaultPickData
this.data.listDataTemp = listData
}
}
})
第五步:创建一个tool.js文件
function _typeof(obj) {
return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}
function isString(obj) { //是否字符串
return _typeof(obj) === 'string'
}
function isPlainObject(obj) {
return _typeof(obj) === 'object';
}
module.exports = {
isString,
isPlainObject
}
第六步:在所需的页面的json中进行引用
{
"usingComponents": {
"picker": "../../picker/picker"
}
}
第七步:在所需的页面的wxml中写入布局
<button bindtap="showPicker_11">时间的五列联动picker</button>
<view>选择数据:{{picker_11_data}}</view>
<view>选择索引:{{picker_11_index}}</view>
<picker isShowPicker="{{isShow_11}}" keyWordsOfShow="name" bindsure="sureCallBack_11" bindcancle="cancleCallBack_11" scrollType="link" listData="{{listData_11}}"></picker>
第八步:在所需的页面的js中调用我们的自定义选择器
// pages/index/index.js
import { times } from './time.js';
Page({
data: {
isShow_11: false,
listData_11:times,
picker_11_data:[],
},
onLoad () {
setTimeout(() => {
this.setData({
defaultPickData_08:[
{code:'110000'},{code:'110100'},{code:'110101'}
]
})
},3000)
},
showPicker_11: function () {
this.setData({
isShow_11: true,
})
},
sureCallBack_11 (e) {
let data = e.detail
console.log("data",data);
this.setData({
isShow_11: false,
picker_11_data: JSON.stringify(e.detail.choosedData),
picker_11_index:JSON.stringify(e.detail.choosedIndexArr)
})
},
cancleCallBack_11 () {
this.setData({
isShow_11: false
})
},
})
第九步:创建一个time.js的文件
const times =[ {
name:'2021年',
id:1,
children:[
{
name:'1月',
id:11,
children:[
{
name:'1日',
id:111,
children:[
{
name:'1时',
id:1111,
children:[
{
name:'1分',
id:11111,
},
{
name:'2分',
id:11112,
},
]
},
]
},
{
name:'2日',
id:112,
children:[
{
name:'1时',
id:1121,
children:[
{
name:'1分',
id:11111,
},
{
name:'2分',
id:11112,
},
]
},
{
name:'2时',
id:1121,
},
]
},
{
name:'3日',
id:113,
children:[
{
name:'小',
id:1131,
},
{
name:'大',
id:1132
},
]
}
]
},
{
name:'2月',
id:12,
children:[
{
name:'1日',
id:121,
children:[
{
name:'1时',
id:1121,
children:[
{
name:'1分',
id:11111,
},
{
name:'2分',
id:11112,
},
]
},
{
name:'2时',
id:1121,
},
]
},
{
name:'2日',
id:122,
children:[
{
name:'1时',
id:1121,
children:[
{
name:'1分',
id:11111,
},
{
name:'2分',
id:11112,
},
]
},
{
name:'2时',
id:1121,
},
]
},
{
name:'3日',
id:123,
children:[
{
name:'1时',
id:1121,
children:[
{
name:'1分',
id:11111,
},
{
name:'2分',
id:11112,
},
]
},
{
name:'2时',
id:1121,
},
]
}
]
}
]
},
{
name:'2022年',
id:1,
children:[
{
name:'1月',
id:11,
children:[
{
name:'1日',
id:111,
children:[
{
name:'1时',
id:1111,
children:[
{
name:'1分',
id:11111,
},
{
name:'2分',
id:11112,
},
]
},
]
},
{
name:'2日',
id:112,
children:[
{
name:'1时',
id:1121,
children:[
{
name:'1分',
id:11111,
},
{
name:'2分',
id:11112,
},
]
},
{
name:'2时',
id:1121,
},
]
},
{
name:'3日',
id:113,
children:[
{
name:'小',
id:1131,
},
{
name:'大',
id:1132
},
]
}
]
},
{
name:'2月',
id:12,
children:[
{
name:'1日',
id:121,
children:[
{
name:'1时',
id:1121,
children:[
{
name:'1分',
id:11111,
},
{
name:'2分',
id:11112,
},
]
},
{
name:'2时',
id:1121,
},
]
},
{
name:'2日',
id:122,
children:[
{
name:'1时',
id:1121,
children:[
{
name:'1分',
id:11111,
},
{
name:'2分',
id:11112,
},
]
},
{
name:'2时',
id:1121,
},
]
},
{
name:'3日',
id:123,
children:[
{
name:'1时',
id:1121,
children:[
{
name:'1分',
id:11111,
},
{
name:'2分',
id:11112,
},
]
},
{
name:'2时',
id:1121,
},
]
}
]
}
]
},]
module.exports = {
times,
}
完成上述步骤后,一个自定义的日期选择器就完成了
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341