Vue中子组件修改父组件的值(使用v-model优化,所有自定义组件可用v-model)
效果图展示 此组件有需要的同学可以直接复制使用子组件 timerPickLimit.vue<!--@name: 24 * 7时间选择器@description: 主要作用于设备禁止登录时间选择@Method: 使用v-model改进 等价<timer-pick-limit :value="formData.loginLimit" @input="val => forData.lo
·
零、先思考
大家可以想想element里的组件像
<el-input />
数据绑定是怎么做的,怎么绑定v-model就可以改变父组件的值呢?
一、食用前甜品
v-model是input+value的语法糖。怎么说?其实
<your-component v-model='yourData'>
等价于
<your-component :value='yourData' @input='val => yourData = val'>
所以别人在父组件用你封装好的话,父组件就不用再定义一个子传父的方法val => yourData = val,太麻烦了,然后子组件$emit(‘input’,…)…
v-model直接tm给你合并了,这样,你封装好的组件给别人用就方便多了,提高组件封装性
二、献上效果图展示 此组件有需要的同学可以直接复制使用
三、子组件 timerPickLimit.vue
<!--
@name: 24 * 7时间选择器
@description: 主要作用于设备禁止登录时间选择
@Method: 使用v-model改进 等价<timer-pick-limit :value="formData.loginLimit" @input="val => forData.loginLimit = val"/>
<timer-pick-limit v-model="formData.loginLimit" />
@author: winsonZheng
@time: 2021/2/23
-->
<template>
<div class="field">
<div id="time" class="cell-selector-wrap sub-form">
<table class="cell-selector">
<thead>
<tr>
<th></th>
<th v-for="item in 24" :key="item">{{ item }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in week" :key="item">
<th>{{ item }}</th>
<td v-for="(_item,_index) in value[index]" :key="_index">
<div :style="{backgroundColor:_item===1?pickColor:'#fff'}" @click="changePickStatus($event,index,_index)"></div>
</td>
</tr>
</tbody>
</table>
<div class="caption">
<div class="caption-item"><span class="checked"></span>允许</div>
<div class="caption-item"><span class="normal"></span>禁止</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import {Component, Prop} from 'vue-property-decorator';
import Vue from 'vue'
import _ from 'lodash'
interface FormData {
loginLimit: Array<Array<number>>
// PS:数据结构,长这样
//loginLimit: [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]
}
@Component
export default class extends Vue {
@Prop()
value: FormData //此处一定是value,v-model默认
private formDataCopy = {}
private pickColor = 'rgb(86, 161, 232)';
private week = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
//TODO 日期选择模块
private changePickStatus(e, index, _index) {
this.formDataCopy = _.cloneDeep(this.value)
if (this.formDataCopy[index][_index] === 1) {
this.formDataCopy[index][_index] = 0;
//此处emit input , v-model默认值
this.$emit('input', this.formDataCopy)
e.target.style.backgroundColor = '#fff'
} else {
this.formDataCopy[index][_index] = 1;
this.$emit('input', this.formDataCopy)
e.target.style.backgroundColor = this.pickColor
}
}
}
</script>
<style lang="scss" scoped>
.text-area {
p {
line-height: 1.5;
color: #999999;
margin: 10px 0 0 0;
text-align: justify;
}
}
.cell-selector {
tbody tr {
th {
width: 50px;
}
td {
width: 30px;
}
div {
width: 100%;
height: 33px;
}
div.on {
background-color: #56a1e8;
}
}
}
.caption {
display: flex;
margin-top: 10px;
.caption-item {
width: 30px;
height: 30px;
background: #56a1e8;
color: #fff;
margin-right: 20px;
padding: 2px 10px;
}
> :last-child {
margin-right: 0;
background: #fff;
color: #1a1a1a;
border: 1px solid #DCDFE6
}
}
</style>
四、父组件 index.vue 引用子组件
<timer-pick-limit v-model="formData.loginLimit" />
使用v-model改进 等价
<timer-pick-limit :value="formData.loginLimit" @input="val => forData.loginLimit = val"/>
更多推荐
已为社区贡献2条内容
所有评论(0)