目录
前言:
回忆基本的原生用法:
原生input的封装:
自定义v-model参数:
对el-input的二次封装:
多个v-model进行绑定:
v-model修饰符:
v-model自定义参数与自定义修饰符的结合:
前言:
提起v-model,想必都不陌生,作为vue的经典语法,帮助我们在编写项目的时候,省了很多很多的事情,本文着重记录v-model在组件上的绑定使用!
回忆基本的原生用法:
使用原生的input,我们一般这么写:
<input type="text" v-model="name">
此种写法相当于以下写法:
<input type="text" :value="name" @input="e=> name = e.target.value">
<input type="text" :value="name" @input="name = $event.target.value">
而当我们在一个组件上使用v-model的写法时,实际写法时长这个样子:
<custom-input :model-value="name" @update:modelValue="newValue=>name = newValue"></custom-input>
请注意model-value与@update:modelValue并不是我规定的,而是vue规定的!
于是乎,我们如果想写成这样使用,那就需要将组件内部的input value值与modelValue进行绑定。
当原生的input时间触发时,利用@update:modelValue将新值携带出去!
<custom-input v-model="name"></custom-input>
原生input的封装:
<template>
<div>modelValue: <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"></div>
</template>
<script setup>
import { defineProps, defineEmits } from "vue"
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>
或者另一种写法:
<template>
<div>modelValue: <input v-model="value"></div>
</template>
<script setup>
import {defineProps,defineEmits,computed} from "vue"
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
const value = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
</script>
两种写法都可,这样我们就可以引入我们的自定义的组件,采用如此写法
<template>
<custom-input v-model="name"></custom-input>
<div>name:{{name}}</div>
</template>
<script setup>
import {ref} from "vue";
import CustomInput from "./components/custom-input/index.vue";
const name = ref('')
</script>
自定义v-model参数:
在默认的情况下,组件的都是使用modelValue作为自己的prop,使用update:modelValue作为对应的更新事件,有时候我们需要去改动一哈!
基本规则就是,自定义的prop:xxx, 对应的更新事件:update:xxx, 组件上就变成了v-model:xxx的写法,下面以value举例
<template>
<div>自定义v-model的参数,例:value: <input :value="value" @input="$emit('update:value', $event.target.value)"></div>
</template>
<script setup>
import {defineProps,defineEmits} from "vue"
const props = defineProps(['value'])
const emit = defineEmits(['update:value'])
</script>
那么我们在组件上使用就变成了这样子:
<custom-input v-model:value="name"></custom-input>
所以,当我们使用element-plus中的el-input组件时,会发现是这样的写法
当使用Naive UI或者Ant Design Vue中的input组件时,会发现是这样写法
总得来说,就是element-plus用了默认的,而另外两个对其进行了自定义参数,而且参数是value!
至于另外一种使用computed的写法,依照最基础的版本,进行编辑即可!
对el-input的二次封装:
在正常写项目的时候,一般都会选择一个适用项目的ui框架,不管是element-plus或者naive等等,我们不可能说自己去写一个原生的input组件进行封装,除非你的input长得特别奇特。。。大部分情况下,我们对ui组件库的组件进行二次封装即可,更多的可能是业务上的封装。
这里以el-input举例,上面说到,el-input其实是用的默认的参数modelValue,我们通过阅读el-input文档也可以看出来---el-input;
故,当我们在对el-input进行二次封装的时候,需要这么写:
<template>
<div>
modelValue:
<el-input :model-value="modelValue" @input="$emit('update:modelValue',$event)" />
</div>
</template>
<script setup>
import {defineProps,defineEmits} from "vue"
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>
如果你是用的Naive UI组件库,那么在你对n-input组件进行二次封装的时候,就需要使用value,update:value了,其他的组件库也是如此!
多个v-model进行绑定:
当我们在自定义的组件中写了多个输入框或者是其他之类的表单式组件,那就必须在组件上使用多个v-model,这个时候默认的modelValue已经不够我们使用了,所以我们必须要进行自定义v-model参数。很简单,写一起就ok!
<template>
<div>
modelValue:
<el-input :model-value="modelValue" @input="$emit('update:modelValue',$event)" />
</div>
<div>
自定义v-model的参数,例:value:
<el-input :model-value="value" @input="$emit('update:value',$event)" />
</div>
</template>
<script setup>
import {defineProps,defineEmits} from "vue"
const props = defineProps(['modelValue', 'value'])
const emit = defineEmits(['update:modelValue', 'update:value'])
</script>
<template>
<custom-el-input v-model="name" v-model:value="desc"></custom-el-input>
<div>name:{{name}}</div>
<div>desc:{{desc}}</div>
</template>
<script setup>
import CustomElInput from "./components/custom-el-input/index.vue"
import {ref} from "vue";
const name = ref('')
const desc = ref('')
</script>
v-model修饰符:
关于v-model的修饰符,知道有一些内置的修饰符,例如.trim,.number之类的。有时候,我们需要自定义修饰符,看下面的例子!
有个需求:要求当你在输入框中输入 “千珏” 二字的时候,就变成 *** 。此修饰符,我决定命名为.replace,写出来的效果是这个样子的!
<custom-el-input v-model.replace="name"></custom-el-input>
那么组件内部该如何去写?
首先我们需要在props里面写上默认的modelValue,其次我们还需要添加上modelModifiers,这个也是默认的,和modelValue都是配套的,注意modelModifiers的默认值是一个空对象!
<template>
<div>modelValue:
<el-input :model-value="modelValue" @input="input" />
</div>
</template>
<script setup>
import {defineProps,defineEmits} from "vue";
const props = defineProps({
modelValue: String,
modelModifiers: {default: () => ({})}
})
const emit = defineEmits(['update:modelValue'])
/* 将 千珏 关键字代替为 *** 字 */
const input = (value) => {
console.log(props);
}
</script>
打印props可以看到如下内容,
当我们在组件上使用 v-model.replace时,在此处replace为true,那我们就可以愉快的进行下一步了,这里我使用了lodash的_replace方法:lodash的_replace
/* 将 千珏 关键字代替为 *** 字 */
const input = (value) => {
const replace = props.modelModifiers.replace
const keyWord = '千珏'
const replaceWord = '***'
if (replace) {
value = _replace(value, keyWord, replaceWord)
}
emit('update:modelValue', value)
}
页面展示就会长这个样子:***就是千珏了,嘿嘿!
v-model自定义参数与自定义修饰符的结合:
需求又来了:当我们输入小写字母时,自动变为对应的大写字母。
对于此种情况,modelValue与modelModifiers当然就不能再用了。此时的规则就是,我们自定义一个参数xxx,而对应的modelModifiers将变成xxxModifiers,这里以value举例,props就会有两个参数,value和valueModifiers。
<template>
<div>自定义v-model的参数,例:value:
<el-input :model-value="value" @input="input" />
</div>
</template>
<script setup>
import {defineProps,defineEmits} from "vue";
import _toUpper from "lodash/toUpper"
const props = defineProps({
value: String,
valueModifiers: {
default: () => ({})
}
})
const emit = defineEmits(['update:value'])
/* 将 小写字母 转化为 大写字母 */
const input = (value) => {
const toUpper = props.valueModifiers.toUpper
if (toUpper) {
value = _toUpper(value)
}
emit('update:value', value)
}
</script>
组件使用:
<custom-el-input v-model:value.toUpper="desc"></custom-el-input>
此时,我们如何输入小写字母都会被自动转化为大写,这就成功了!