组件上的 v-model

💥💥💥

环境为:Vue3

1. 原生元素上的 v-model

<p>{{ msg }}</p>
<input v-model="msg" />

<!-- 上面的代码其实等价于下面这段 (编译器会对 v-model 进行展开): -->
<input :value="msg" @input="msg = $event.target.value" />

2. 组件上的 v-model

2.1 组件v-model的展开

<template>
  <p>{{ msg }}</p>
  <!-- 组件上的v-model -->
  <CustomeInput v-model="msg"></CustomeInput>
</template>
<script>
import CustomeInput from './components/CustomeInput.vue';
export default {
  name: 'App',
  components: {
    CustomeInput
  },
  data() {
    return {
      msg: '我是付常涛'
    };
  }
};
</script>

v-model展开如下:

<CustomInput
  :modelValue="msg"
  @update:modelValue="newValue => msg = newValue"
/>

✨✨✨

v-model="msg",默认将属性modelValue当做 props 传进组件,并接收组件内名为update:modelValue的自定义事件。

2.2 组件内部

通过点击按钮,可以发现App组件和CustomeInput组件中的msg/modelValue发生了改变。

<template>
  <p>
    <strong>{{ modelValue }}</strong>
  </p>
  <p><button @click="update">更改msg</button></p>
</template>

<script>
export default {
  // props 接收
  props: ['modelValue'],
  // 注册自定义事件
  emits: ['update:modelValue'],
  methods: {
    update() {
      this.$emit('update:modelValue', 'fct');
    }
  }
};
</script>

2.3 在自定义组件内与父组件的 msg 保持同步

在自定义组件中使用input,实现组件内输入的内容动态绑定App组件的msg

2.3.1 v-model 手动展开

<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>
<script>
export default {
  props: ['modelValue'],
  emits: ['update:modelValue']
}
</script>

2.3.2 v-model + 计算属性

<template>
 <input v-model="modelValueComputed" />
</template>
<script>
export default {
  props: ['modelValue'],
  emits: ['update:modelValue'],
  computed: {
    modelValueComputed: {
      get() {
        return this.modelValue;
      },
      set(value) {
        this.$emit('update:modelValue', value);
      }
    }
  }
}
</script>

3. 组件上多个 v-model

当组件上有一个v-model时,都是使用 modelValue 作为 prop,并以 update:modelValue 作为对应的事件。

当一个组件上有多个v-model时如何区分传入组件的prop?

v-model其实有参数:

v-model='msg'其实等于v-model:modelValue='msg'

组件上的多个v-model:

// App.vue
<h2>{{ msg }}</h2>
<h2>{{ title }}</h2>
<MyComponent v-model='msg' v-model:title="title" />

子组件中不仅需要声明modelValueprop 还得声明titleprop。并通过触发 update:title 事件更新父组件值。

<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
  <input
    :value="title"
    @input="$emit('update:title', $event.target.value)"
  />
</template>
<script>
export default {
  props: ['title', 'modelValue'],
  emits: ['update:title', 'update:modelValue']
}
</script>
posted @ 2022-10-14 16:03  青柠i  阅读(26)  评论(0编辑  收藏  举报