Menu
×
   ❮   
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS R TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI GO KOTLIN SASS VUE DSA GEN AI SCIPY AWS CYBERSECURITY DATA SCIENCE
     ❯   

Vue 教程

Vue 主页 Vue 简介 Vue 指令 Vue v-bind Vue v-if Vue v-show Vue v-for Vue 事件 Vue v-on Vue 方法 Vue 事件修饰符 Vue 表单 Vue v-model Vue CSS 绑定 Vue 计算属性 Vue 侦听器 Vue 模板

扩展 应用

Vue 为什么,如何以及设置 Vue 第一个 SFC 页面 Vue 组件 Vue 属性 Vue v-for 组件 Vue $emit() Vue 透传属性 Vue 作用域样式 Vue 局部组件 Vue 插槽 Vue v-slot Vue 作用域插槽 Vue 动态组件 Vue 传送门 Vue HTTP 请求 Vue 模板引用 Vue 生命周期钩子 Vue Provide/Inject Vue 路由 Vue 表单输入 Vue 动画 Vue 带有 v-for 的动画 Vue 构建 Vue 组合式 API

Vue 参考

Vue 内置属性 Vue 内置组件 Vue 内置元素 Vue 组件实例 Vue 指令 Vue 实例选项 Vue 生命周期钩子

Vue 示例

Vue 示例 Vue 练习 Vue 问答 Vue 服务器 Vue 证书

Vue v-model 指令


示例

使用 v-model 指令在 <input> 元素和数据属性之间创建双向绑定。

<template>
  <h1>v-model Example</h1>
  <p>Write something, and see the 'inputValue' data property update automatically.</p>
  <input type="text" v-model="inputValue"> 
  <p>inputValue property: "{{ inputValue }}"</p>
</template>
运行示例 »

在下面查看更多示例。


定义和用法

v-model 指令用于在表单输入元素之间或在 Vue 实例属性和组件之间创建双向绑定。


使用 v-model 的表单输入元素

可以使用 v-model 的表单输入元素是 <input><select><textarea>

双向绑定 在表单输入元素上使用 v-model 的工作原理如下

  • 当 Vue 检测到输入值发生变化时,它将相应地更新对应的数据属性。(HTML -> JavaScript)
  • 当 Vue 检测到 Vue 实例属性发生变化时,它将相应地更新对应输入值。(JavaScript -> HTML)

(参见上面的示例,以及下面的示例 1)。


使用 v-model 的组件

当在组件上使用 v-model 时,必须使用 propsemits 正确设置组件接口才能实现双向绑定。

双向绑定 在组件上使用 v-model 的工作原理如下

  • 当 Vue 检测到父实例属性发生变化时,新值将作为属性发送到组件。
  • 当 Vue 检测到子组件发生变化时,新值将作为发射事件发送到父组件。

当在组件上使用 v-model 时,默认属性名称为 'modelValue',默认发射事件名称为 'update:modelValue'。(参见 示例 2示例 3)。

当在组件上使用 v-model 时,我们可以使用具有 get()set() 方法的计算属性,而不是使用 Vue 实例数据属性。(参见示例 4)

可以使用 v-model: 设置与默认 'modelValue' 和 'update:modelValue' 不同的属性和发射事件名称。(参见示例 5)

要将多个值连接到组件作为双向绑定,我们必须使用自己的 v-model 定义每个值。(参见示例 6)


修饰符

修饰符 细节
.lazy Vue 使用 change 事件而不是 input 事件来同步。这意味着用户必须先修改输入,然后将焦点从输入元素移开,才能更新实例属性值。(参见示例 7)
.number 将输入类型转换为数字。使用 <input type="number"> 时会自动完成此操作。
.trim 移除输入开始和结束处的空格。(参见示例 8)
自定义 要为 v-model 创建自定义修饰符,我们首先需要定义一个名为 'modelModifiers' 的属性来存储新修饰符。修饰符功能写在方法中。如果设置了修饰符,则在将值发射回父组件之前,相应的代码会在方法中运行。(参见示例 9)


更多示例

示例 1

使用滑块 (<input type="range">) 来更改 'inputValue' 属性值。 <input type="text"> 元素会自动更新,因为它使用 v-model 绑定到 'inputValue' 属性。

<template>
  <h1>v-model Example</h1>
  <p>Drag the slider to change the 'inputValue' data property, and see the input text field update automatically because of the two-way binding from v-model.</p>
  <input type="range" min="-50" max="50" v-on:input="sliderChange" value="4">
  <p>inputValue property: "{{ inputValue }}"</p>
  <input type="text" v-model="inputValue"> 
</template>

<script>
export default {
  data() {
    return {
      inputValue: null
    };
  },
  methods: {
    sliderChange(evt) {
      this.inputValue = evt.target.value
    }
  }
}
</script>
运行示例 »

示例 2

在组件上使用 v-model,并使用 propsemits,以便 <input> 元素中的更改会更新父级的 'text' 属性。

App.vue:

<template>
  <h2>Example v-model Directive</h2>
  <p>App.vue 'text' property: "{{ text }}"</p>
  <comp-one v-model="text"/>
</template>

<script>
export default {
  data() {
    return {
      text: 'Say Cheese'
    }
  }
}
</script>

CompOne.vue:

<template>
  <div>
    <h3>Component</h3>
    <p>Write something in the text input field below to see that changes here are emitted from the component, and the parent 'text' property gets updated by the use of v-model.</p>
    <input
      :value="modelValue"
      @input="$emit('update:modelValue', $event.target.value)"
    />
  </div>
</template>

<script>
  export default {
    props: ['modelValue'],
    emits: ['update:modelValue']
  }
</script>

<style scoped>
div {
  border: solid black 1px;
  padding: 10px;
  margin: 20px 0;
  max-width: 500px;
}
</style>
运行示例 »

示例 3

在组件上使用 v-model 来更清楚地演示双向绑定。组件可以更新父级的 'text' 属性,并且当父级的 'text' 属性发生变化时,组件会得到更新。

App.vue:

<template>
  <h2>Example v-model Directive</h2>
  <p>App.vue 'text' property: "<pre>{{ text }}</pre>"</p>
  <button v-on:click="this.text = 'Hello!'">text='Hello!'</button>
  <comp-one v-model="text"/>
</template>

<script>
export default {
  data() {
    return {
      text: 'Say Cheese'
    }
  }
}
</script>

<style>
pre {
  display: inline;
  background-color: yellow;
}
</style>

CompOne.vue:

<template>
  <div>
    <h3>Component</h3>
    <p>Two-way binding on component with v-model:</p>
    <ol>
      <li>The component can update the 'text' property (using text field).</li>
      <li>The component gets updated when the 'text' property is changed (using button).</li>
    </ol>
    <input
      :value="modelValue"
      @input="$emit('update:modelValue', $event.target.value)"
    />
  </div>
</template>

<script>
  export default {
    props: ['modelValue'],
    emits: ['update:modelValue']
  }
</script>

<style scoped>
div {
  border: solid black 1px;
  padding: 10px;
  margin: 20px 0;
  max-width: 600px;
}
</style>
运行示例 »

示例 4

在组件内使用 get()set() 函数与计算值一起使用 v-model

CompOne.vue:

<template>
  <div>
    <h3>Component</h3>
    <p>Two-way binding on component with v-model:</p>
    <ol>
      <li>The component can update the 'text' property (using text field).</li>
      <li>The component gets updated when the 'text' property is changed (using button).</li>
    </ol>
    <input v-model="inpVal"/>
  </div>
</template>

<script>
  export default {
    props: ['modelValue'],
    emits: ['update:modelValue'],
    computed: {
      inpVal: {
        get() {
          return this.modelValue;
        },
        set(inpVal) {
          this.$emit('update:modelValue',inpVal)
        }
      }
    }
  }
</script>

<style scoped>
div {
  border: solid black 1px;
  padding: 10px;
  margin: 20px 0;
  max-width: 600px;
}
</style>
运行示例 »

示例 5

在组件上使用 v-model:message 将默认属性名称 'modelValue' 重命名为 'message'。

App.vue:

<template>
  <h2>Example v-model Directive</h2>
  <p>App.vue 'text' property: "<pre>{{ text }}</pre>"</p>
  <button v-on:click="this.text = 'Hello!'">text='Hello!'</button>
  <comp-one v-model:message="text"/>
</template>

<script>
export default {
  data() {
    return {
      text: 'Say Cheese'
    }
  }
}
</script>

<style>
pre {
  display: inline;
  background-color: yellow;
}
</style>

CompOne.vue:

<template>
  <div>
    <h3>Component</h3>
    <p>Two-way binding on component with v-model:</p>
    <ol>
      <li>The component can update the 'text' property (using text field).</li>
      <li>The component gets updated when the 'text' property is changed (using button).</li>
    </ol>
    <input
      :value="message"
      @input="$emit('update:message', $event.target.value)"
    />
  </div>
</template>

<script>
  export default {
    props: ['message'],
    emits: ['update:message']
  }
</script>

<style scoped>
div {
  border: solid black 1px;
  padding: 10px;
  margin: 20px 0;
  max-width: 600px;
}
</style>
运行示例 »

示例 6

在组件上两次使用 v-model 来创建两个值的双向绑定。

App.vue:

<template>
  <h2>Example v-model Directive</h2>
  <p>Name: "<pre>{{ name }}</pre>"</p>
  <p>Height: <pre>{{ height }}</pre> cm</p>
  <comp-one 
    v-model:name="name"
    v-model:height="height"
  />
</template>

<script>
export default {
  data() {
    return {
      name: 'Olaf',
      height: 120
    }
  }
}
</script>

<style>
pre {
  display: inline;
  background-color: yellow;
}
</style>

CompOne.vue:

<template>
  <div>
    <h3>Component</h3>
    <p>Two inputs are bound to the component with v-model through props and emits.</p>
    <p>
      <label>
        Name: 
        <input
          type="text"
          :value="name"
          @input="$emit('update:name', $event.target.value)"
        />
      </label>
    </p>
    <p>
      <label>
        Height:
        <input
          type="range"
          :value="height"
          @input="$emit('update:height', $event.target.value)"
          min="50"
          max="200"
        />
        {{ this.$props.height }} cm
      </label>
    </p>
  </div>
</template>

<script>
  export default {
    props: ['name','height'],
    emits: ['update:name','update:height']
  }
</script>

<style scoped>
div {
  border: solid black 1px;
  padding: 10px;
  margin: 20px 0;
  max-width: 300px;
}
</style>
运行示例 »

示例 7

使用 .lazy,以便用户必须先修改输入元素,然后将焦点从输入元素移开,才能使用 v-model 更新属性。

<template>
  <h1>v-model Example</h1>
  <p>Using the '.lazy' modifier, you must first write something, then click somewhere else, or use the tab key to switch focus away from the input element, before the property get updated.</p>
  <input type="text" v-model.lazy="inputValue"> 
  <p>inputValue property: "{{ inputValue }}"</p>
</template>

<script>
export default {
  data() {
    return {
      inputValue: null
    };
  }
}
</script>
运行示例 »

示例 8

使用 .lazy,以便用户必须先修改输入元素,然后将焦点从输入元素移开,才能使用 v-model 更新属性。

<template>
  <h1>v-model Example</h1>
  <p>Using the '.trim' modifier will remove any white spaces at the start and end of the input.</p>
  <p>Add white spaces at the start and end in the input fields below to see the difference with or with out '.trim'.</p>
  <p>No '.trim': <input type="text" v-model="inputVal1"> "<pre>{{ inputVal1 }}</pre>"</p> 
  <p>With '.trim': <input type="text" v-model.trim="inputVal2"> "<pre>{{ inputVal2 }}</pre>"</p>
  
</template>

<script>
export default {
  data() {
    return {
      inputVal1: 'Hello',
      inputVal2: 'Hi'
    };
  }
}
</script>

<style>
pre {
  display: inline;
  background-color: lightgreen;

}
</style>
运行示例 »

示例 9

使用自定义 .allCapital 修饰符,如果设置了 .allCapital 修饰符,则将输入中的所有字符转换为大写。

App.vue:

<template>
  <h2>Example v-model Directive</h2>
  <p>App.vue 'text' property: "{{ text }}"</p>
  <comp-one v-model.allCapital="text"/>
</template>

<script>
export default {
  data() {
    return {
      text: ''
    }
  }
}
</script>

CompOne.vue:

<template>
  <div>
    <h3>Component</h3>
    <p>Write something in the text input field below. Click somewhere else or use the tab key to shift focus away from the input element to see the effect of the custom 'allCapital' modifier.</p>
    <input 
      :value="modelValue" 
      @change="this.emitVal" 
    />
  </div>
</template>

<script>
export default {
  props: {
    modelValue: String,
    modelModifiers: {
      // modelModifiers is an empty object initially.
      // Modifiers set on the component will be stored here.
      default: () => ({}) 
    }
  },
  emits: ['update:modelValue'],
  methods: {
    emitVal(e) {
      let value = e.target.value
      if (this.modelModifiers.allCapital) {
        value = value.toUpperCase()
      }
      this.$emit('update:modelValue', value)
    }
  }
}
</script>

<style scoped>
div {
  border: solid black 1px;
  padding: 10px;
  margin: 20px 0;
  max-width: 500px;
}
</style>
运行示例 »

相关页面

Vue 教程:Vue 组件

Vue 教程:Vue 属性

Vue 教程:Vue $emit() 方法

Vue 教程:Vue 计算属性

Vue 参考:Vue $emit() 方法

Vue 参考:Vue $props 对象

JavaScript 教程:JavaScript 对象访问器


×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
[email protected]

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
[email protected]

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 1999-2024 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.