微信小程序 原生时间选择器 月份范围 几月至几月 封装组件 父子组件

本文档详细介绍了如何在微信小程序中实现一个时间选择器组件,包括年份从1900年开始、月份显示当前年1月到12月,以及根据所选月份动态更新可选的结束月份。同时,该组件还支持封装为子组件供其他页面复用,并提供了相应的事件绑定和数据传递方法。
摘要由CSDN通过智能技术生成

效果如图所示 

需求分析:默认显示当前年份1月到1月 选择月份上面的文字随之变化 

        年份-获取1900年到现在 

        月份-第一列月份12个月所以选择   第二个月份随着第一个选择而变化 大于第一个选择的月份 

 页面布局.wxml

<view class="revenue">
    <image src="../../assets/images/revenue.png" class="bannerBg"></image>
    <view class="topContent">
        <view class="text">       
            <text class="selectTime">{{year}}年{{month}}月至{{toMonth}}月</text>
        </view>
    </view>
    <view class="timeSelect" bindtap="changeSure">
        <image class="calendar" src="../../assets/icons/calendar.png"></image>
        <text class="timeText"> 日期 </text>
        <image class="triangle" src="../../assets/icons/triangle.png"></image>
    </view>
    <picker-view class="fixedSelect" indicator-style="height: 50px;" style="width: 100%; height: 300px;display: {{sure}};" value="{{value}}" bindchange="bindChange">
        <view class="teoSure">
            <text class="close" bindtap="sureSelect" data-sure="false">取消</text>
            <text class="close sure" bindtap="sureSelect" data-sure="true">确定</text>
        </view>
        <picker-view-column>
            <view wx:for="{{years}}" wx:key="this" style="line-height: 50px; text-align: center;">{{item}}年</view>
        </picker-view-column>
        <picker-view-column>
            <view wx:for="{{months}}" wx:key="this" style="line-height: 50px; text-align: center;">{{item}}月 至</view>
        </picker-view-column>
        <picker-view-column>
            <view wx:for="{{toMonths}}" wx:key="this" style="line-height: 50px; text-align: center;">{{item}}月</view>
        </picker-view-column>
    </picker-view>
</view>

样式.wxss

/* 右上角样式 */
.timeSelect {
    height: 52rpx;
    background-color: #fff;
    border-radius: 30rpx;
    display: flex;
    align-items: center;
    padding: 0 20rpx;
    position: absolute;
    top: 15rpx;
    right: 40rpx;
}

.timeSelect .calendar {
    width: 26rpx;
    height: 26rpx;
}

.timeSelect .triangle {
    width: 14rpx;
    height: 10rpx;
}

.timeSelect .timeText {
    margin: 0 10rpx;
    font-size: 24rpx;
}
/* 日期选择样式 */
.fixedSelect {
    background-color: #fff;
    position: fixed;
    bottom: 0;
    left: 0;
    height: 350rpx;
    border-top: 2px solid #e9e9ea;
}

.fixedSelect .teoSure {
    position: absolute;
    top: 0;
    z-index: 111;
    line-height: 60rpx;
    display: flex;
    width: 100%;
    justify-content: space-between;
    background-color: #eee;
}

.fixedSelect .teoSure .close {
    padding: 10rpx 20rpx;
}

.fixedSelect .teoSure .sure {
    color: #4566ff;
}

js代码.js

const date = new Date()
const years = []
const months = []
for (let i = 1900; i <= date.getFullYear(); i++) {
    years.push(i)
}
for (let i = 1; i <= 12; i++) {
    months.push(i)
}
Page({
    /**
     * 页面的初始数据
     */
    data: {
        years,// 年份数组
        year: date.getFullYear(),//年份
        months, //月份数组
        month: 1, //几月
        toMonth: 1,// 到几月
        value: [9999, 0, 0],// 获取年月份
        toMonths: [] // 月份数组  到几月份
        sure: "none",// 控制显示时间列表
    },
    // 日期选择器
    changeSure() {
        this.setData({
            sure: 'block'
        })
    },
    // 取消选择 确定选择
    sureSelect(e) {
        this.setData({
            sure: 'none'
        })
        console.log(this.data);
    },

    // 日期改变
    bindChange(e) {
        const val = e.detail.value
        // 不能提前或者在后面赋值 有问题
        this.setData({
            // val 上面定义了 接收的是e里面的值 为数组 
            year: this.data.years[val[0]],
            month: this.data.months[val[1]],
        })
        if (this.data.toMonths.length != 13 - this.data.month) {
            // 定义一个新数组 用来存放第二个月份列表
            const toMonths = []
            for (let i = this.data.month; i <= 12; i++) {
                toMonths.push(i)
            }
            this.setData({
                // 简写方式
                toMonths,
            })
        }
        // 顺序不能改变 变了就会出问题
        this.setData({
            toMonth: this.data.toMonths[val[2]],
        })
    },
})

效果图 

也可以封装成组件使用

子组件

        新建components文件夹 用来存放组件

       新建文件夹 timeScope ,选中鼠标右击  选择新建Component 输入timeScope 即可快捷创建组件

timeScope         .wxml  这里面控制显示隐藏放在了父组件里面

<picker-view class="fixedSelect" indicator-style="height: 50px;" style="width: 100%; height: 300px" value="{{value}}" bindchange="bindChange">
    <view class="teoSure">
        <text class="close" bindtap="sureSelect" data-sure="false">取消</text>
        <text class="close sure" bindtap="sureSelect" data-sure="true">确定</text>
    </view>
    <picker-view-column>
        <view wx:for="{{years}}" wx:key="this" style="line-height: 50px; text-align: center;">{{item}}年</view>
    </picker-view-column>
    <picker-view-column>
        <view wx:for="{{months}}" wx:key="this" style="line-height: 50px; text-align: center;">{{item}}月 至</view>
    </picker-view-column>
    <picker-view-column>
        <view wx:for="{{toMonths}}" wx:key="this" style="line-height: 50px; text-align: center;">{{item}}月</view>
    </picker-view-column>
</picker-view>

 timeScope.wxss  没什么变化 复制过来就行

/* components/timeScope/timeScope.wxss */
/* 日期选择样式 */
.fixedSelect {
    background-color: #fff;
    position: fixed;
    bottom: 0;
    left: 0;
    height: 350rpx;
    border-top: 2px solid #e9e9ea;
}

.fixedSelect .teoSure {
    position: absolute;
    top: 0;
    z-index: 111;
    line-height: 60rpx;
    display: flex;
    width: 100%;
    justify-content: space-between;
    background-color: #eee;
}

.fixedSelect .teoSure .close {
    padding: 10rpx 20rpx;
}

.fixedSelect .teoSure .sure {
    color: #4566ff;
}

timeScope.js   子组件 像父组件传值 利用this.triggerEvent("父组件方法","需要传的值")

// components/timeScope/timeScope.js
const date = new Date()  // 获取时间
const years = []  // 定义年份
const months = []  // 月份 开始月份
for (let i = 1900; i <= date.getFullYear(); i++) {
    years.push(i)   // 年份是从1900年开始 
}
for (let i = 1; i <= 12; i++) {
    months.push(i)  // 月份 12个月 可以直接写死
}
// const months = [1,2,3,4,5,6,7,8,9,10,11,12]  
Component({
    /**
     * 组件的属性列表
     */
    properties: {
        // 用于接父组件传过来的值 这里没有用到
    },

    /**
     * 组件的初始数据
     */
    data: {
        years,// 年份数组
        year: date.getFullYear(),//年份  这里也可以直接写死 years[years.length-1] 取最近一年
        months, //月份数组
        month: 1, //几月
        sure: "none",// 控制显示时间列表
        toMonth: 1,// 到几月
        value: [9999, 0, 0],// 获取年月份
        toMonths: [] // 月份数组  到几月份 这里是活的 选择前面月份 进行变化
    },

    /**
     * 组件的方法列表
     */
    methods: {
        // 取消选择 确定选择
        sureSelect(e) {
            // 定义 变量/常量 反正也不会改变 
            let obj = {
                sure: "none",
                year: this.data.year,
                month: this.data.month,
                toMonth: this.data.toMonth
            }
            // 子组件 像父组件传值 利用this.triggerEvent("父组件方法","需要传的值")
            // 这里因为判断语句里面只有一段 省略了花括号 
            if (e.target.dataset.sure === "false") this.triggerEvent('changeSure', { sure: "none" })
            // 同样 这里也是
            else this.triggerEvent('changeSure', obj)
        },
        // 日期改变 这里上面解释了 这里就不详细写了
        bindChange(e) {
            const val = e.detail.value
            this.setData({
                year: this.data.years[val[0]],
                month: this.data.months[val[1]],
            })
            if (this.data.toMonths.length != 13 - this.data.month) {
                const toMonths = []
                for (let i = this.data.month; i <= 12; i++) {
                    toMonths.push(i)
                }
                this.setData({
                    toMonths,
                })
            }
            this.setData({
                toMonth: this.data.toMonths[val[2]],
            })
        },
    }
})

timeScope,json  这里没有变化 就是创建完就是这样子的

{
    "component": true,
    "usingComponents": {}
}

以上东西是子组件里面的 ------------------------------------------------

父组件 

父组件.wxml   

<timeScope style="display: {{sure}};" bindchangeSure="changeSure" />

父组件.json  不要忘记在json中引入!!!!!

{
    "usingComponents": {
        "timeScope": "../../components/timeScope/timeScope"
    },
    "navigationBarTitleText": ""
}

父组件.js

const date = new Date() // 父组件里面的年份留着 因为要获取最新一年
const years = []
for (let i = 1900; i <= date.getFullYear(); i++) {
    years.push(i)
}

Page({

    /**
     * 页面的初始数据
     */
    data: {
        year: date.getFullYear(),//年份
        month: 1, //几月
        toMonth: 1,// 到几月
        sure: "none",// 控制显示时间列表 
    },

    // 日期选择器
    changeSure(e) {
        // console.log(e);
        // 因为这里的方法和原本的方法用法一致 都是控制时间列表显示隐藏的 所以就没有新写一个方法
        // 就直接利用 e.type进行判断即可 
        if (e.type === "tap") this.setData({ sure: 'block' })
        else this.setData(e.detail)
        // console.log(this.data);  // 可以看看有没有赋值成功  
    },
})

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫和老许

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值