APICloud AVM框架 封装日历组件

AVM(Application-View-Model)前端组件化开发模式基于标准Web Components组件化思想,提供包含虚拟DOM和Runtime的编程框架avm.js以及多端统一编译工具,完全兼容Web Components标准,同时兼容Vue和React语法糖编写代码,编译工具将Vue和React相关语法糖编译转换为avm.js代码。

基于标准 Web Components 组件化思想,兼容 Vue / React 语法特性,通过一次编码,分别编译为 App、小程序代码,实现多端开发。
 

组件功能介绍

日历组件,可切换月份,选择日期;用于实现常用的日期选择,日历展示功能。

组件示例

组件开发

组件文件

easy-calendar.stml

<template>
	<view class="easy_calendar-wrapper">
		<view class="easy_calendar-toolbar">
			<text class="easy_calendar-prev" onclick="prevMonth">〈</text>
			<text class="easy_calendar-current">{{ currentDateStr }}</text>
			<text class="easy_calendar-next" onclick="nextMonth">〉</text>
		</view>
		<view class="easy_calendar-week">
			<text class="easy_calendar-week-item" v-for="item of weekList" :key="item">{{ item }}</text>
		</view>
		<view class="easy_calendar-inner">
			<text class="easy_calendar-item" v-for="(item, index) of calendarList" :key="index" :class="this.changestyle(item.disable,item.value)"
			onclick="selDate" :data-val="item.value" :data-status="item.disable" :data-num="item.date">{{ item.date }}</text>
		</view>
	</view>
</template>
<script>
	export default {
		name: 'easy-calendar',
		installed(){
			this.setCurrent();
			this.calendarCreator();
		},
		data() {
			return{
				current:{},	
				weekList:['周日','周一','周二','周三','周四','周五','周六'],
				shareDate: new Date(),
				calendarList: [],
				seldate:'点击选择日期',
				selweek:'待定'
			}
		},
		computed: {
			// 显示当前时间
			currentDateStr() {
				let { year, month } = this.current;
				return `${year}年${this.pad(month + 1)}月`;
			}
		},
		methods: {
			selDate (e){
				// console.log(JSON.stringify(e.currentTarget.dataset.val));
				let status = e.currentTarget.dataset.status;
				let num = e.currentTarget.dataset.num;
				if(status){
					this.data.seldate = e.currentTarget.dataset.val;
					this.getWeek();
					if(num>7){
						this.prevMonth();
					}
					else{
						this.nextMonth();
					}
				}
				else{
					this.data.seldate = e.currentTarget.dataset.val;
					this.getWeek();
					//重新加载一次日历 改变样式
					this.calendarCreator();
				}
				this.fire('clickDate', this.data.seldate);
			},
			changestyle(status,date){
				if(status){
					return 'easy_calendar-item-disabled';
				}
				else{
					if(date == this.data.seldate){
						return 'easy_calendar-item-checked';
					}
					else{
						return 'easy_calendar-item';
					}
				}
			},
			// 判断当前月有多少天
			getDaysByMonth(year, month) {
				// console.log("本月多少天:"+new Date(year, month + 1, 0).getDate());
				return new Date(year, month + 1, 0).getDate();
			},
			getFirstDayByMonths(year, month) {
				// console.log("本月第一天周几:"+new Date(year, month, 1).getDay());
				return new Date(year, month, 1).getDay();
			},
			getLastDayByMonth(year, month) {
				// console.log("本月最后一天周几:"+new Date(year, month + 1, 0).getDay());
				return new Date(year, month + 1, 0).getDay();
			},
			// 对小于 10 的数字,前面补 0
			pad(str) {
				return str < 10 ? `0${str}` : str;
			},
			// 点击上一月
			prevMonth() {
				this.current.month--;
				// 因为 month的变化 会超出 0-11 的范围, 所以需要重新计算
				this.correctCurrent();
				// 生成新日期
				this.calendarCreator();
			},
			// 点击下一月
			nextMonth() {
				this.current.month++;
				// 因为 month的变化 会超出 0-11 的范围, 所以需要重新计算
				this.correctCurrent();
				// 生成新日期
				this.calendarCreator();
			},
			// 格式化时间,与主逻辑无关
			stringify(year, month, date) {
				let str = [year, this.pad(month + 1), this.pad(date)].join('-');
				return str;
			},
			// 设置或初始化 current
			setCurrent(d = new Date()) {
				let year = d.getFullYear();
				let month = d.getMonth();
				let date = d.getDate();
				this.current = {
						year,
						month,
						date
				}
			},
			// 修正 current
			correctCurrent() {
				let { year, month, date } = this.data.current;

				let maxDate = this.getDaysByMonth(year, month);
				// 预防其他月跳转到2月,2月最多只有29天,没有30-31
				date = Math.min(maxDate, date);

				let instance = new Date(year, month, date);
				this.setCurrent(instance);
			},
			// 生成日期
			calendarCreator() {
				// 一天有多少毫秒
				const oneDayMS = 24 * 60 * 60 * 1000;

				let list = [];
				let { year, month } = this.data.current;

				// 当前月份第一天是星期几, 0-6
				let firstDay = this.getFirstDayByMonths(year, month);
				// 填充多少天                         
				let prefixDaysLen = firstDay === 0 ? 7 : firstDay;
				// 毫秒数
				let begin = new Date(year, month, 1).getTime() - oneDayMS * prefixDaysLen;

				// 当前月份最后一天是星期几, 0-6
				let lastDay = this.getLastDayByMonth(year, month);
				// 填充多少天, 和星期的排放顺序有关
				let suffixDaysLen = lastDay === 0 ? 6 : 6 - lastDay;
				// 毫秒数
				let end = new Date(year, month + 1, 0).getTime() + oneDayMS * suffixDaysLen;

				while (begin <= end) {
						// 享元模式,避免重复 new Date
						this.data.shareDate.setTime(begin);
						let year = this.data.shareDate.getFullYear();
						let curMonth = this.data.shareDate.getMonth();
						let date = this.data.shareDate.getDate();
						list.push({
								year: year,
								month: curMonth,
								date: date,
								disable: curMonth !== month,
								value: this.stringify(year, curMonth, date)
						});
						begin += oneDayMS;
				}
				this.data.calendarList = list;			
				// console.log(JSON.stringify(this.data.calendarList));
			},
			//获取选中日期的周几
			getWeek(){
				let index =new Date(this.data.seldate).getDay();
				let weekArr = ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五','星期六'];
				let week = weekArr[index];
				this.data.selweek = week;
			}
		}
	}
</script>
<style>
	.easy_calendar-wrapper {
		margin: 10px 10px 0 10px;
		background-color:#016dd9;
		border-top-left-radius: 10px;
		border-top-right-radius: 10px;
		max-height: 400px;
	}

	.easy_calendar-toolbar {
		padding: 10px 10px;
		flex-flow: row nowrap;
		justify-content: space-between;
		align-items: center;		
		border-bottom: 1px solid #fff;
	}
	.easy_calendar-prev{
		flex: 1;
		text-align: center;
		color: #fff;
	}
	.easy_calendar-current {
		flex: 1;
		text-align: center;
		color: #fff;
	}
	.easy_calendar-next{
		flex: 1;
		text-align: center;
		color: #fff;
	}

	.easy_calendar-week {
		padding: 5px 10px;
		flex-flow: row nowrap;
		justify-content: space-around;
		align-items: center;
	}
	.easy_calendar-week-item { 
		padding: 5px;
		font-weight: bolder;
		font-size: 12px;
		color: #fff;
	}
	.easy_calendar-inner{
		padding: 10px 10px;
		flex-flow: row wrap;
		justify-content: space-around;
		align-items: center;
	}
	.easy_calendar-item {
		width:14%;
		font-weight: bolder;
		text-align: center;
		font-size: 15px;
		color: #fff;
		padding: 5px;
		background-color: #016dd9;
	}
	.easy_calendar-item-disabled {
		width:14%;
		font-weight: bolder;
		text-align: center;
		font-size: 15px;
		color: #999;
	}
	.easy_calendar-item-checked {
		width:14%;
		font-weight: bolder;
		text-align: center;
		font-size: 15px;
		color: #000000;
		background-color: #ffffff;
		border-radius: 5px;
	}
</style>

组件使用说明

本组件是基于AVM.js开发的多端组件,通常同时适配Android、iOS、小程序、H5 , 具体支持情况还要看每个组件的说明文档。

首先需要登录开发平台,http://www.apicloud.com。 通过控制平台右上方的模块Store进入,然后选择AVM组件。

 

 找到对应模块进入

 也可通过搜索栏,通过组件名称关键字进行检索。

  进入模块详情,点击立即下载下载完整的组件安装包。  

 组件压缩包的文件目录如下

 也可通过查看模块文档 来了解模块的具体参数,引用的原生模块,注意事项等。 

具体在项目中的使用步骤是,第一步将压缩文件中的easy-calendar.stml文件拷贝到项目的components目录,通过阅读readme.md 文档和查看demo示例文件 demo-easy-calendar.stml在需要开发的stml文件中,引入组件文件,完成页面的开发。

demo-easy-cakendar.stml

<template>
    <view class="page">
		<safe-area></safe-area>
		<easy-calendar onclickDate="getSelDate"></easy-calendar>
    </view>
</template>
<script>
	import '../../components/easy-calendar.stml'
	export default {
		name: 'demo-easy-calendar',
		apiready(){

		},
		data() {
			return{
				today:''
			}
		},
		methods: {
			getSelDate(e){
				// console.log(JSON.stringify(e));
				this.data.today = e.detail;
				api.toast({
					msg:'选择日期:'+this.data.today
				})
			},
		}
	}
</script>
<style>
    .page {
        height: 100%;
    }
</style>

如果在AVM组件库中,没有找到实际项目中需要的组件,可以自己尝试封装组件。

这是组件化开发的在线文档地址

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

白鱼赤乌

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

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

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

打赏作者

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

抵扣说明:

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

余额充值