SoFunction
Updated on 2025-04-10

Detailed explanation of how vue3 defineModel implements two-way binding

Preface

In Vue 3.4,v-modelThe two-way binding mechanism has been further optimized. With the introduction of Vue 3.3defineModelMacros, developers can implement bidirectional data binding within components more concisely. This article will explain in detailv-modelBasic usage, custom attribute names, multiple model bindings, anddefineModelpractical application.

Basic usage: v-model and defineModel

In Vue 3,v-modelThe component will be bound by defaultmodelValueattributes and passupdate:modelValueEvents implement two-way data transfer between parent and child components.

Traditional writing using v-model

Parent component

<template>
  <ChildComponent v-model="value" />
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './';

const value = ref('Hello Vue 3');
</script>

Subcomponents (traditional writing)

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

<script setup>
defineProps(['modelValue']);
const emit = defineEmits(['update:modelValue']);
</script>

Simplified writing using defineModel

Starting with Vue 3.3, subcomponents can be useddefineModelThe macro simplifies the above code.

Subcomponents

<template>
  <input type="text" v-model="model" />
</template>

<script setup>
const model = defineModel();
</script>

illustrate

  • defineModel: No manual definition requiredpropsandemits, automatic processingmodelValueandupdate:modelValue
  • Parent component'sv-modelWill be automatically bound tomodelvariable.

Custom v-model property name

Except for the defaultmodelValue, Vue 3 supports customizationv-modelattribute name. existdefineModelYou can also pass parameters in the property name of the bound.

Example

Parent component

<template>
  <ChildComponent v-model:title="titleValue" />
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './';

const titleValue = ref('Default Title');
</script>

Subcomponents

<template>
  <input type="text" v-model="title" />
</template>

<script setup>
const title = defineModel('title');
</script>

illustrate

  • Custom attribute name:passdefineModel('title'),Willv-model:titleBind totitlevariable.
  • In parent componentv-model:titleIt will be mapped automatically astitlevariable.

Equivalent to:

<ChildComponent :title="titleValue" @update:title="titleValue = $event" />

Multiple v-model bindings

In the same component, multiple can be boundv-modelproperty,defineModelSupports multiple bindings to handle different data models separately.

Example

Parent component

<template>
  <ChildComponent v-model:title="titleValue" v-model:content="contentValue" />
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './';

const titleValue = ref('My Title');
const contentValue = ref('This is content');
</script>

Subcomponents

<template>
  <div>
    <input type="text" v-model="title" placeholder="Title" />
    <textarea v-model="content" placeholder="Content"></textarea>
  </div>
</template>

<script setup>
const title = defineModel('title');
const content = defineModel('content');
</script>

illustrate

  • EachdefineModelAll can define an independent binding property.
  • Parent component passesv-model:titleandv-model:contentBind different attributes respectively.

Combining v-model with extra properties

In the component,v-modelCan be used simultaneously with other attributes. For example, you can add extra props such as placeholders to the input box.

Example

Parent component

<template>
  <ChildComponent v-model="value" placeholder="Please enter" />
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './';

const value = ref('');
</script>

Subcomponents

&lt;template&gt;
  &lt;input type="text" v-model="model" :placeholder="placeholder" /&gt;
&lt;/template&gt;

&lt;script setup&gt;
const model = defineModel();
defineProps({
  placeholder: String, // Receive extra attributes});
&lt;/script&gt;

illustrate

  • v-modelBoundedmodel, realize two-way data binding.
  • placeholderIt's ordinaryprops, can provide additional features.

Summarize

New features of v-model

  • Default binding modelValue and update:modelValue event, simplify data binding between parent and child components.
  • Supports custom attribute names,likev-model:title, flexibly bind multiple data.
  • Support multiple v-model, bind multiple properties in the same component.
  • defineModel MacroProvides a simpler writing method, automatically handling props and emits.
  • It can be used in combination with ordinary properties to enhance the scalability of components.

Benefits of using defineModel

  • The code is more concise and reduces duplicate code in templates and scripts.
  • Improve maintainability and avoid manual managementpropsandemits
  • Provides flexible two-way binding methods, supporting custom property names and multiple models.

By reasonable usedefineModelandv-model, Vue 3.4 provides a more modern and elegant two-way binding solution for components.

This is the article about how vue3 defineModel achieves two-way binding. For more related contents of vue3 defineModel, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!