您现在的位置是:首页 >其他 >vue 3 第二十八章:组件十二(组件的v-model、多v-model)网站首页其他

vue 3 第二十八章:组件十二(组件的v-model、多v-model)

剑九 六千里 2024-07-05 00:01:02
简介vue 3 第二十八章:组件十二(组件的v-model、多v-model)


在 Vue 3 中, v-model 指令的使用更加灵活,可以绑定任意属性和事件。例如,我们可以使用 v-model:checked 指令来绑定单选框或复选框的 checked 属性,使用 v-model:my-prop 来绑定自定义组件的 my-prop 属性。

1. 基本使用

同时,Vue3 中的组合式 API 也为自定义组件的 v-model 提供了更好的支持。我们可以使用 modelValueupdate:modelValue 两个参数来定义组件的 v-model,例如:

// MyComponent.vue
<template>
  <div>
    <input :value="props.modelValue" @input="updateValue" />
    <span>子组件:{{ props.modelValue }}</span>
  </div>
</template>

<script setup lang="ts">
const props = defineProps({
  modelValue: String,
});

let emit = defineEmits(["update:modelValue"]);
const updateValue = (event: any) => {
  emit("update:modelValue", event.target.value);
};
</script>

在上面的例子中,我们使用 modelValue 属性来接收父组件传递的值,并在输入框的 input 事件中使用 update:modelValue 事件来更新父组件的值。在父组件中,我们可以使用 v-model 指令来绑定这个自定义组件:

// parent.vue
<template>
  <div>
    <my-component v-model="data"></my-component>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import MyComponent from "./components/MyComponent.vue";
const data = ref("hello word");
</script>

需要注意的是,使用 v-model 指令绑定自定义组件时,组件需要定义 modelValueupdate:modelValue 两个属性。另外,v-model 指令在绑定自定义组件时,会自动将组件的 modelValue 属性作为 value 属性绑定,因此,在自定义组件的模板中,需要使用 value 属性来绑定输入框的值。

2. 使用conputed实现

另一种在组件内实现v-model的方式是使用一个可写的,同时具有gettersettercomputed属性。get 方法需返回 modelValue prop,而 set 方法需触发相应的事件

// MyComponent.vue
<template>
  <div>
    <input v-model="value" />
    <span>子组件:{{ props.modelValue }}</span>
  </div>
</template>

<script setup lang="ts">
import { computed } from "vue";

const props = defineProps({ modelValue: String });

let emit = defineEmits(["update:modelValue"]);
const value = computed({
  get() {
    return props.modelValue;
  },
  set(value) {
    emit("update:modelValue", value);
  },
});
</script>

3. v-model 的参数

默认情况下,v-model在组件上都是使用modelValue作为 prop,并以update:modelValue作为对应的事件。我们可以通过给v-model指定一个参数来更改这些名字:

// parent.vue
<template>
  <div>
    <my-component v-model:test="data"></my-component>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import MyComponent from "./components/MyComponent.vue";
const data = ref("hello word");
</script>

子组件接收 test(就是之前的modelValue) 值,通过update:test更新父组件传递的数据:

// MyComponent.vue
<template>
  <div>
    <input :value="props.test" @input="updateValue" />
    <span>子组件:{{ props.test }}</span>
  </div>
</template>

<script setup lang="ts">
const props = defineProps({ test: String });

let emit = defineEmits(["update:test"]);

// 3.使用自定义参数
const updateValue = (event: any) => {
  emit("update:test", event.target.value);
};
</script>

4. 多 v-model 的使用

通过v-model可以传递参数的特性,我们可同时使用多个 v-model,示例如下:

// parent.vue
<template>
  <div>
    <my-component v-model:hello="hello" v-model:word="word"></my-component>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import MyComponent from "./components/MyComponent.vue";
const hello = ref("hello");
const word = ref("word");
</script>

父组件使用多个 v-model,子组件可以接收多个参数并修改

// MyComponent.vue
<template>
  <div>
    <input :value="props.hello" @input="updateHello" />
    <span>子组件:{{ props.hello }}</span>
    <br />
    <input :value="props.word" @input="updateWord" />
    <span>子组件:{{ props.word }}</span>
  </div>
</template>

<script setup lang="ts">
const props = defineProps({ hello: String, word: String });

let emit = defineEmits(["update:hello", "update:word"]);

// 4.使用多v-model
const updateHello = (event: any) => {
  emit("update:hello", event.target.value);
};
const updateWord = (event: any) => {
  emit("update:word", event.target.value);
};
</script>

5. v-model 修饰符

vue 官方提供了一些修饰符(如trim、number等等),但有时候我们可能需要一些特殊的功能,那么就可以使用自定义的修饰符来解决问题,如下:

<my-component v-model.mySplit="data"></my-component>

父组件传递的修饰符,可以在子组件中通过modelModifiers访问到:

// MyComponent.vue
<template>
  <div>
    <input :value="props.modelValue" @input="updateModelValue" />
    <span>子组件:{{ props.modelValue }}</span>
  </div>
</template>

<script setup lang="ts">
const props = defineProps({
  modelValue: String,
  modelModifiers: { default: () => {} },
});
// console.log(props.modelModifiers); // {mySplit: true}
let emit = defineEmits(["update:modelValue"]);

// 5.使用v-model修饰符
const updateModelValue = (event: any) => {
  emit("update:modelValue", event.target.value);
};
</script>

在子组件中通过modelModifiers访问到传递的修饰符,那么我们就可以在用户每次输入时将输入内容变成数组:

// parent.vue
<template>
  <div>
    <my-component
      v-model.mySplit="data"
      v-model:title.mySplit="title"
    ></my-component>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import MyComponent from "./components/MyComponent.vue";
const data = ref<string>("");
const title = ref<string>("");
</script>



// MyComponent.vue
<template>
  <div>
    <input type="text" :value="props.modelValue" @input="updateModelValue" />
    <span>子组件:{{ props.modelValue }}</span>
    <hr />
    <input type="text" :value="props.title" @input="updateTitle" />
    <span>子组件:{{ props.title }}</span>
  </div>
</template>

<script setup lang="ts">
type Props = {
  modelValue?: string;
  modelModifiers?: { mySplit: boolean };
  title?: string;
  titleModifiers?: { mySplit: boolean };
};

const props = defineProps<Props>();
let emit = defineEmits(["update:modelValue", "update:title"]);

// 5.使用v-model修饰符
const updateModelValue = (event: any) => {
  let value = event.target.value;
  console.log(value, "value");
  if (props.modelModifiers?.mySplit) {
    value = value.split("");
  }
  emit("update:modelValue", value);
};
const updateTitle = (event: any) => {
  let value = event.target.value;
  if (props.titleModifiers?.mySplit) {
    value = value.split("");
  }
  emit("update:title", value);
};
</script>

注意:未给v-model传递参数,默认使用 modelModifiers , 如果传递了参数,那就用 参数 +Modifiers

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。