菜单
×
   ❮   
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 Intro Vue Directives Vue v-bind Vue v-if Vue v-show Vue v-for Vue Events Vue v-on Vue Methods Vue Event Modifiers Vue Forms Vue v-model Vue CSS Binding Vue Computed Properties Vue Watchers Vue Templates

Scaling Up

Vue 为什么、如何以及设置 Vue 第一个 SFC 页面 Vue 组件 Vue Props Vue v-for 组件 Vue $emit() Vue Fallthrough Attributes Vue Scoped Styling Vue Local Components Vue Slots Vue v-slot Vue Scoped Slots Vue Dynamic Components Vue Teleport Vue HTTP Request Vue Template Refs Vue Lifecycle Hooks Vue Provide/Inject Vue Routing Vue Form Inputs Vue Animations Vue Animations with v-for Vue Build Vue Composition API

Vue Reference

Vue Built-in Attributes Vue Built-in Components Vue Built-in Elements Vue Component Instance Vue Directives Vue Instance Options Vue Lifecycle Hooks

Vue 示例

Vue Examples Vue Exercises Vue Quiz Vue Server Vue Certificate

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 检测到父实例属性发生变化时,新值将作为 prop 发送到组件。
  • 当 Vue 检测到子组件发生变化时,新值将作为一个 emit 事件向上发送到父组件。

v-model 用于组件时,默认 prop 名称是 'modelValue',默认 emit 事件名称是 'update:modelValue'。(参见 示例 2示例 3。)

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

与默认的 'modelValue' 和 'update:modelValue' 不同的 prop 和 emit 名称,可以使用 v-model: 进行设置。(参见示例 5

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


修饰符

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

在组件内部使用 v-model 配合计算值,其中包含 get()set() 函数。

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 将默认 prop 名称 '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 Components

Vue 教程:Vue Props

Vue 教程:Vue $emit() Method

Vue 教程:Vue Computed Properties

Vue Reference: Vue $emit() Method

Vue Reference: Vue $props Object

JavaScript Tutorial: JavaScript Object Accessors


×

联系销售

如果您想将 W3Schools 服务用于教育机构、团队或企业,请发送电子邮件给我们
sales@w3schools.com

报告错误

如果您想报告错误,或想提出建议,请发送电子邮件给我们
help@w3schools.com

W3Schools 经过优化,旨在方便学习和培训。示例可能经过简化,以提高阅读和学习体验。教程、参考资料和示例会不断审查,以避免错误,但我们无法保证所有内容的完全正确性。使用 W3Schools 即表示您已阅读并接受我们的使用条款Cookie 和隐私政策

版权所有 1999-2024 Refsnes Data。保留所有权利。W3Schools 由 W3.CSS 提供支持