v-model的双向绑定

在表单输入元素或组件上创建双向绑定

作用

在表单输入元素或组件上创建双向绑定,即表单可以拿到vue中的数据,表单中的数据也可以传到vue中,而v-bind:value 只能是表单拿到vue的数据,vue无法拿到表单的数据

原理

一个组件上的v-model默认会利用名为value的props和名为input的事件

<vx-card-list v-model="policyNoList" ref="list">
 <vx-card-item
    v-for="(item, index) in PolicyList"
    :key="index"
    v-model="value"
    :name="item.policyNo"
    :title="item.riskName"
    :status="item.policySts"
    :info="item.info"
  ></vx-card-item>
</vx-card-list>

cardList组件

<template>
  <div class="vx-card-list">
    <slot />
  </div>
</template>
<script>
export default {
  name: "vx-card-list",
  props: {
  	//用于接受父组件中v-model绑定的值(policyNoList)
    value: {
      type: [Array, String],
      default: () => ([])
    },
  },
}
</script>

v-model相当于写两件事情

  1. v-bind:绑定响应式数据
  2. 触发oninput 事件并传递数据
<input v-model="sth" />
//  等同于
<input :value="sth" @input="sth = $event.target.value" /> //自html5开始,input每次输入都会触发input事件,所以输入时input的内容会绑定到sth中,于是sth的值就被改变;
//$event 指代当前触发的事件对象;
//$event.target 指代当前触发的事件对象的dom;
//$event.target.value 就是当前dom的value值;
//在@input方法中,value => sth;
//在:value中,sth => value;

举例

场景:父子组件响应式传递数据

父组件

<template>
	<div>
		 <common-input-box name="工单编号" :input.sync="currentBillNum"></common-input-box>
	</div>
</template>
<script>
import commonInputBox from '@/common/commonInputBox.vue';
export default{
	components:{
        commonInputBox
    },
}
</script>

子组件commonInputBox.vue

<template>
    <view class="input">
        <view :class="['input-box',{'input-box-active':titleActive}]">
            <view :class="['title',{'title-active':titleActive}]">
                <view class="name">
                    <view v-for="(item,index) in nameArr" :key="index">{{item}}</view>
                </view>
                <view class="star" v-if="isShowStar">*</view>
            </view>
            <template>
            	// input输入框
                <input :class="{'grey-bg-color':disabled}" v-if="!titleActive" :disabled=disabled :maxlength="inputLength" placeholder="请输入" v-model.trim="inputValue" @input="getValue">
                <textarea :class="{'grey-bg-color':disabled}" v-else placeholder="请输入" :disabled=disabled :maxlength="textLength" v-model.trim="inputValue" @input="getValue"></textarea>
            </template>
        </view>
    </view>
</template>
<script>
export default{
    data(){
        return{
            // 输入框的值
            inputValue:this.input
        }
    },
    props:{
        // 标题
        name:{
            type:String,
            default:''
        },
        // 控制flex主轴方向、输入框为单行还是多行(标题和输入框之间有padding)
        // true:flex主轴方向为column,输入框为多行,标题和输入框之间的padding
        // false:flex主轴方向为row,输入框为单行
        titleActive:{
            type:Boolean,
            default:false
        },
        // 是否展示*,默认为true(展示)
        isShowStar:{
            type:Boolean,
            default:true
        },
        // input输入框的最大长度
        inputLength:{
            type:Number,
            default:50
        },
        // textarea输入框的最大长度
        textLength:{
            type:Number,
            default:50
        },
        // 接受父组件传过来的值
        input:{
            type:String,
            default:''
        },
        // 禁用,默认不禁用
        disabled: {
            type: Boolean,
            default: false
        },
    },
    computed:{
        // 输入框前面文字没有达到最小宽度时保持两端对齐
        nameArr(){
            return this.name.split('')
        }
    },
    watch:{
        input:{
            handler(value){
                this.inputValue = value
            },
            immediate: true
        }
    },
    methods:{
        // 通过此方法向父组件抛出输入框的值
        getValue(){
            this.$emit('update:input',this.inputValue)
        }
    }
}
</script>

<style lang="scss" scoped>
.input-box-active{
   flex-direction: column !important;
}
.title-active{
    padding-bottom: 20rpx;
}
.input{
    padding-bottom: 28rpx;
}
.input-box{
    display: flex;
    font-family: $base-fontFamily;
    font-weight: 400;
    .title{
        display: flex;
        align-items: center;
        font-size: 30rpx;
        color: #333333;
        .name{
            white-space: nowrap;
            min-width: 116rpx;
            display: flex;
            justify-content: space-between;
        }
        .star{
           color: #FF3B3B; 
           padding: 5rpx 34rpx 0 14rpx;
        }
    }
    input,textarea{
        width: 100%;
        background: #F7F8FC;
        border-radius: 12px;
        padding: 26rpx 30rpx;
        color: #333333;
        font-size: 28rpx;
    }
    textarea{
        height: 225rpx;
        box-sizing: border-box;

    }
}
</style>


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值