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组件库中,没有找到实际项目中需要的组件,可以自己尝试封装组件。