自定义组件(日期选择)实现v-model

自定义组件实现v-model

v-model的本质:

<input v-model="variable" />
//  等价于
<input :value="variable" @input="variable = $event.target.value" />

相信大家都会倾向于第一种写法,这个是封装好的组件,如果是我们自己写的组件,v-model有没有效果呢?很明显,直接写是没有效果的,不下点功夫怎么会有回报,我们用写好的组件方便是因为有些事别人替我们做了。要想方便以后使用,那现在就要多下功夫,不但要知其然,还要知其所以然。
父组件中

<hTimePicker v-model='dataPickerShow' :sTime="9" :dayNum='7' :sDay='0' :cTime="20" interval="5"  @changeTime="changeTime"></hTimePicker>

dataPickerShow是我们要双向绑定的变量,changeTime是子组件向父组件传参的方法名,这里父组件用来监听子组件的事件,并获取传递过来的参数。其它参数是父组件传递给子组件的参数。这里可以看到,我们的父组件的写法是不是跟第二种形式很像,这样写就更明显了

<hTimePicker :show='dataPickerShow' :sTime="9" :dayNum='7' :sDay='0' 
:cTime="20" interval="5" @changeStatus="changeStatus" @changeTime="changeTime">
</hTimePicker>

:show–:value @input=“variable = $event.target.value”–@changeStatus=“changeStatus”
关键在于如何让v-model生效

子组件中

 model: {
	      prop: 'value',//参数名
	      event: 'input',//事件名
	    },
	props: {
		value: {
			type: [Boolean],
			default: false
		},
	}

这样,value参数的值就会同步父组件v-model的值,子组件传的参数改变的同时要触发event,就是类似@input="v-model的值 = e v e n t . t a r g e t . v a l u e " 的 效 果 , 我 们 这 里 可 以 用 event.target.value"的效果,我们这里可以用 event.target.value"emit来触发,结合watch方法就是这样

watch:{
		value(newVal,oldVal){
			console.log('value',newVal,oldVal)
			this.popShow=this.value
		},
		popShow(newVal,oldVal){
			console.log('popShow',newVal,oldVal)
			this.$emit('input', newVal);
		}
	},

这里我有引入了一个变量,它是子组件的,注意尽量不要为了省事用同一个变量,组件的数据流是单向的,默认不允许子组件修改父组件的值。这样,父组件传参导致子组件的参数变化,触发事件,父组件监听到该事件并将此作为v-model的值,形成一个闭环,就实现了双向绑定。
这里需要注意,我的参数名是value,事件是input,和input的一样,那可不可以自定义呢?目前我验证的h5中是可以的,小程序中必须是input value。
在父组件中通过监听input事件可以获取到子组件传的参数
父组件:

<hTimePicker v-model='dataPickerShow' :sTime="9" :dayNum='7' :sDay='0' 
:cTime="20" interval="5"  @changeTime="changeTime" @input="changeStatus">
</hTimePicker>

测试没有input不写@input="changeStatus"也可实现,不同平台可能会有差异。
全部代码如下:基于uview

<template>
	<view>
		<view class="changeTime" @click="dataPickerShow=true">
		  点击选择时间{{dataPickerShow}}
		</view>
		<hTimePicker v-model='dataPickerShow' :sTime="9" :dayNum='7' :sDay='0' :cTime="20" interval="5"  @changeTime="changeTime" >
		 
		</hTimePicker>
	</view>
</template>

<script>
	import hTimePicker from "@/components/h-timePicker/h-timePicker.vue";
	export default {
		components: { hTimePicker },
		data() {
			return {
				dataPickerShow:false
			}
		},
		methods: {
			changeStatus(status){
				console.log(status)
				this.dataPickerShow=status
			},
			changeTime(time,e){
				console.log(time.slice(0,16),e)
				// this.dataPickerShow=status
			}
		}
	}
</script>

<style>

</style>

子组件:

<!-- v-model -->
<template>
	<view>
		
		<u-picker v-model="popShow" class="time-picker" mode="multiSelector" @confirm="bindStartMultiPickerChange" @columnchange="bindMultiPickerColumnChange" :default-selector="multiIndex" :range="multiArray">
			
		</u-picker>
	</view>
</template>

<script>
export default {
	//小程序中事件只能用input
	// model: {
	//      prop: 'value',
	//      event: 'input'
	//    },
	 model: {
	      prop: 'value',
	      event: 'input'
	    },
	props: {
		value: {
			//开始小时
			type: [Boolean],
			default: false
		},
		sTime: {
			//开始小时
			type: [Number, String],
			default: '0'
		},
		cTime: {
			//结束小时
			type: [Number, String],
			default: '23'
		},
		timeNum: {
			//延迟小时
			type: [Number, String],
			default: '1'
		},
		interval: {
			//分钟间隔
			type: [Number, String],
			default: '1'
		},
		sDay: {
			//开始天数
			type: [Number, String],
			default: '0'
		},
		dayNum: {
			//预约天数
			type: [Number, String],
			default: '7'
		}
	},
	data() {
		return {
			popShow:this.value,
			sDayNum: 0,
			multiArray: [['今天', '明天', '3-2', '3-3', '3-4', '3-5'], [0, 1, 2, 3, 4, 5, 6], [0, 10, 20]],
			multiIndex: [0, 0, 0],
			multiSelector: ''
		};
	},
	beforeMount() {
		this.pickerTap();
	},
	mounted() {
		// this.popShow=this.value
		console.log('组件调用',this.value)
	},
	watch:{
		value(newVal,oldVal){
			console.log('value',newVal,oldVal)
			this.popShow=this.value
		},
		popShow(newVal,oldVal){
			console.log('popShow',newVal,oldVal)
			this.$emit('input', newVal);
		}
	},
	methods: {
		timeFormat: function(num) {
			if (num < 10 && (num + '').length == 1) {
				return '0' + num;
			}
			return num;
		},
		pickerTap: function() {
			let date = new Date();
			let monthDay = [];
			let hours = [];
			let minute = [];
			this.sDayNum = this.sDay;

			// 时
			let date1 = new Date(date);
			let sT = +this.sTime;
			let eT = +this.cTime;

			if (sT <= eT) {
				let h = date1.getHours() < sT ? sT : date1.getHours();
				h = h + parseInt(this.timeNum);
				if (h > eT || this.sDayNum > 0) {
					this.sDayNum = this.sDayNum <= 0 ? parseInt(this.sDay) + 1 : parseInt(this.sDay);
					for (let i = sT; i <= eT; i++) {
						hours.push(this.timeFormat(i) + '时');
					}
				} else {
					for (let i = h; i <= eT; i++) {
						hours.push(this.timeFormat(i) + '时');
					}
				}
			} else {
				let h = date1.getHours() < sT ? sT : date1.getHours();
				h = h + parseInt(this.timeNum);
				if ((h > eT && h < sT) || h > 23 || this.sDayNum > 0) {
					this.sDayNum = this.sDayNum <= 0 ? parseInt(this.sDay) + 1 : parseInt(this.sDay);
					for (let i = 0; i <= 23; i++) {
						if (i < sT && i > eT) {
						} else {
							hours.push(this.timeFormat(i) + '时');
						}
					}
				} else {
					for (let i = h; i <= 23; i++) {
						if (i < sT && i > eT) {
						} else {
							hours.push(this.timeFormat(i) + '时');
						}
					}
				}
			}

			// 月-日
			for (let i = +this.sDayNum; i <= parseInt(this.sDayNum) + parseInt(this.dayNum); i++) {
				let date1 = new Date(date);
				date1.setDate(date.getDate() + i);
				let md = date1.getFullYear() + '-' + this.timeFormat(date1.getMonth() + 1) + '-' + this.timeFormat(date1.getDate());
				monthDay.push(md);
			}

			let inter = +this.interval < 60 ? +this.interval : 59;
			// 分
			for (let i = 0; i < 60; i += inter) {
				minute.push(i < 10 ? '0' + i + '分' : i + '分');
			}

			let data = {
				multiArray: this.multiArray,
				multiIndex: this.multiIndex
			};

			console.log(hours)
			data.multiArray[0] = monthDay;
			data.multiArray[1] = hours;
			data.multiArray[2] = minute;
			console.log(data.multiArray)
			this.multiArray = data.multiArray;
			this.multiIndex = data.multiIndex;
		},
		bindMultiPickerColumnChange(e) {
			console.log(e)
			this.multiIndex.splice(e.column,1,e.index)
			let hours = [];
			if (e.column == 0 && e.index == 0 && +this.sDayNum == 0) {
				let date = new Date();
				// 时
				let date1 = new Date(date);
				let sT = +this.sTime;
				let eT = +this.cTime;

				if (sT <= eT) {
					let h = date1.getHours() < sT ? sT : date1.getHours();
					h = h + parseInt(this.timeNum);
					if (h > eT || this.sDayNum > 0) {
						this.sDayNum = this.sDayNum <= 0 ? parseInt(this.sDay) + 1 : parseInt(this.sDay);
						for (let i = sT; i <= eT; i++) {
							hours.push(this.timeFormat(i) + '时');
						}
					} else {
						for (let i = h; i <= eT; i++) {
							hours.push(this.timeFormat(i) + '时');
						}
					}
				} else {
					let h = date1.getHours() < sT ? sT : date1.getHours();
					h = h + parseInt(this.timeNum);
					if ((h > eT && h < sT) || h > 23 || this.sDayNum > 0) {
						this.sDayNum = this.sDayNum <= 0 ? parseInt(this.sDay) + 1 : parseInt(this.sDay);
						for (let i = 0; i <= 23; i++) {
							if (i < sT && i > eT) {
							} else {
								hours.push(this.timeFormat(i) + '时');
							}
						}
					} else {
						for (let i = h; i <= 23; i++) {
							if (i < sT && i > eT) {
							} else {
								hours.push(this.timeFormat(i) + '时');
							}
						}
					}
				}
				this.multiArray.splice(1,1,hours)
				
				
			} else if (e.column == 0 && e.index != 0) {
				let sT = +this.sTime;
				let eT = +this.cTime;

				if (sT <= eT) {
					for (let i = sT; i <= eT; i++) {
						hours.push(this.timeFormat(i) + '时');
					}
				} else {
					for (let i = 0; i <= 23; i++) {
						if (i < sT && i > eT) {
						} else {
							hours.push(this.timeFormat(i) + '时');
						}
					}
				}
				this.multiArray.splice(1,1,hours)
				
			}
		},
		bindStartMultiPickerChange(e) {
			console.log(e);
			this.multiIndex = e;
			let da = this.multiArray;
			let di = e;

			let caseDate = da[0][di[0]] + ' ' + da[1][di[1]].replace('时', ':') + this.timeFormat(da[2][di[2]].replace('分', '')) + ':00';

			let appointTime = new Date(caseDate.replace(/-/g,'/')).getTime() / 1000;
			if (appointTime < new Date().getTime() / 1000) {
				uni.valueToast({
					title: '不能选择过去时间',
					icon: 'none'
				});
				return false;
			}
			this.$emit('changeTime', caseDate, appointTime * 1000);
		}
	}
};
</script>

<style lang="scss"></style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值