[Vue3] 指令 v-model

默认 v-model

默认的 v-model 就是不写其他任何的东西,也就是在使用时是这样的格式 v-model="value"

子组件

要定义一个默认的 v-model(不带参数的 v-model),就必须要按照以下格式来定义。

<script setup lang="ts">
defineProps(["modelValue"]);
defineEmits(["update:modelValue"]);
</script>

<template>
  <input type="text" @input="$event => $emit('update:modelValue', ($event.target as HTMLInputElement).value)" />
</template>

定义 props 的时候,默认的 v-model 是 modelValue,v-model 本质上是一个自定义函数通知父组件更新数据,所以也需要一个 emit,而 v-model 的 emit 必须是 update:Xxxx 的格式。

父组件

<script setup lang="ts">
const state = ref("");
</script>

<template>
  {{ state }}
  <Test v-model="state" />
</template>

v-model 是利用 emit 向父组件传递数据,通知父组件的 state 更新。而默认的 v-model 所对应的子组件 prop 就是 modelValue,与之对应的也要有一个 update:modelValue 的 emit 自定义事件。

具名 v-model

默认的 v-model 相反的就是具名 v-model,顾名思义,就是给 v-model 取一个名字方便区分,也就是说可以定义很多个 v-model。

子组件

和默认 v-model 不同,具名 v-model 可以取任何一个合法的 JS 名称。

<script setup lang="ts">
defineProps(["disabled"]);
defineEmits(["update:disabled"]);
</script>

<template>
  <input type="text" @input="$event => $emit('update:disabled', ($event.target as HTMLInputElement).value)" />
</template>

其余的定义方式和上面默认 v-model 都一样。

父组件

<script setup lang="ts">
const state = ref("");
</script>

<template>
  {{ state }}
  <Test v-model:disabled="state" />
</template>

修饰符

v-model 修饰符可以很方便地处理输入时的前置工作,如输入时,给一串英文的首字母进行大写转换。这个修饰符的作用就好像是一个开关,带上修饰符就是要开启某一项功能,不带上就不开启。

子组件

子组件定义了一个 capitalize 修饰符,意思就是带了这个修饰符就要进行大小写转换,否则就不进行这一项任务。

<script setup lang="ts">
const props = defineProps({
  value: String,
  valueModifiers: {
    default: () => ({
      capitalize: false
    })
  }
});

const emits = defineEmits(["update:value"]);

function onInputChange(e: any) {
  let targetValue = e.target.value;
  // 判断修饰符有没有开启
  if (props.valueModifiers.capitalize) {
    targetValue = targetValue.charAt(0).toUpperCase() + targetValue.slice(1);
  }
  emits("update:value", targetValue);
}
</script>

<template>
  <input type="text" :value="value" @input="onInputChange" />
</template>

父组件

v-model 冒号后面的是 value,它是一个具名 v-model,绑定的子组件 props。所有的 . 都是前面 props 的修饰符,这个修饰符是一个布尔值,也就是两种状态,即开不开启某项功能。

<template>
  <Text v-model:value.capitalize="state" />
</template>

修饰符不写就是 false,写了就是 true。实例中我写了修饰符,所以我输入小写的单词,首字母会被转换。

实现效果

链式修饰符

修饰符在父组件中不止可以 . 一个,可以有多个:

<template>
  <Text v-model:value.capitalize.a.b="state" />
</template>

也就是 valueModifiers 默认返回的对象中属性有很多个:

const props = defineProps({
  value: String,
  valueModifiers: {
    default: () => ({
      capitalize: false,
      a: false,
      b: false
    })
  }
});
posted @ 2023-03-26 16:12  Himmelbleu  阅读(22)  评论(0编辑  收藏  举报