【vue其他相关】怎么理解v-model,怎么自定义组件中改写它?

怎么理解

对于普通的input标签来说,大概就这样的原理

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

这些都是vue底层在生成render函数的时候做好的事情,例如select会对应的去调整为value与change事件;checkbox也会去调整为checked与为change事件


自定义组件中改写v-model

什么情况下需要自己改写v-model的逻辑呢?

  • 基本的v-model已经不能满足我们的业务需求了
  • 用最普通的传值形式太麻了

咱们看用最普通的传值形式有多麻烦

普通传值形式的缺陷

vue2举例,通过prop和emit传值去做双向变化的效果。

子组件

<template>
  <input :value="value" @input="$emit('input', $event.target.value)" />
</template>

<script>
export default {
  props: { 
    value: String
  },
};
</script>

父级使用:

<my-component :value="val" @input="val = arguments[0]"> // 通过arguments默认入参集合去接收

可以看到不仅麻烦,还有其他问题:

  1. 可读性比较差,别人要通过看你组件的代码才能理解到:value是个双向绑定。
  2. 当绑定值是个对象时,这种方法满足不了。

vue2改写方法

<!-- 基础输入框 -->
<template>
  <el-input v-model="input"></el-input>
</template>

<script>
export default ({
    name: 'PzInput',
    model: {
        prop: 'inputProp', // 表明v-model传进来的变量,由props的指定变量接收
        event: 'input' // 表明子组件可以通过input这个方法可修改外部v-model变量,这样就可实现双向修改绑定
    },
    props: {
        // 外层v-model的接收
        inputProp: {
            type: String,
            default: ''
        }
    },
    data() {
        return {
            input: ''
        }
    }
    watch: {
        // 把选择的结果暴露出v-model
        input: {
            handler() {
                this.$emit('input', this.input) // 暴露出v-model
            }
        },
        // 监听外部v-model传进来的
        inputProp: {
            handler(val) {
                this.input = val // 如果表单点了重置按钮
            },
            immediate: true
        }
    }
})
</script>

看到没,其实原理就是:

  • 告诉vue,重新指定了值和修改事件
  • 再监听输入的值并更新内部的最新值,以及抛出修改的最新值

如果是要双向绑定对象,那我再举个表单组件的例子:

// 组件中
model: {
	prop: 'formData', // 表明v-model.trim传进来的变量,由props的指定变量接收
	event: 'input'
},
props: {
	formData: { // 传入已有数据
	    type: Object,
	    default() {
	        return {}
	    }
	},
},
data() {
	return {
		form: {}
	}
},
watch: {
	// 把选择的结果暴露出v-model.trim
	form: {
	    handler() {
	        this.$emit('input', this.form) // 暴露出v-model.trim
	    },
	    deep: true
	},
	// 监听外部v-model.trim传进来的,填入到data中的form,这样可以防止数据是异步获取从而获取不到的问题
	formData: {
	    handler() {
	        this.form = this.formData
	    },
	    immediate: true,
	    deep: true
	},
}

父组件:

<my-component v-model="formData"></my-component > 

虽然子组件代码量多了,但是父组件的可读性是比较好的。

vue3改写方法

这里偷个懒嘻嘻~

看文档里那个【多个 v-model 绑定】的方法就行了,等我以后有实践了再来补充。

附上文档链接:https://cn.vuejs.org/guide/components/v-model.html#multiple-v-model-bindings

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值