vue中的v-model刨根问底

简介: 关于v-model用过vue的应该都知道,用着那是相当的丝滑,但很多人可能并没有深究过其原理,而且随着vue版本的更新,也有些新的用法被大家遗漏,所以就有了这一篇对v-model的刨根问底

vue中的v-model刨根问底

关于v-model用过vue的应该都知道,用着那是相当的丝滑,但很多人可能并没有深究过其原理,而且随着vue版本的更新,也有些新的用法被大家遗漏,所以就有了这一篇对v-model的刨根问底。

v-model的前世今生

v-model是vue中的一个指令,可以在表单控件或者组件上创建双向绑定。

实际上它只是一个语法糖,vue会自动在元素或者组件上添加value属性和input事件

<!-- vue表单控件写法 -->
<input v-model="val" />
<!-- 等价于 -->
<input :value="val" @input="($event) => val = $event.target.value" />


<!-- vue组件写法 -->
<MyComponent v-model="val" />
<!-- 等价于 -->
<MyComponent :value="val" @input="(e) => val = e" />

在input之类的表单控件上使用大家都很熟悉,但很多人可能会遗漏掉v-model在自定义组件上的使用。

在子组件中,通过props中的value来接收父组件中传的值,同时可以通过 $emit('input', e) 来同步更改父组件中的值。

可能也就是上面这个约定的value和input事件限制了大家在组件上的使用,在实际开发中value和input这两个名字可能并不能很好的表达我们的语义(vue后面的版本已经帮我们解决掉这个问题了)。

在组件中使用v-model通过props接收值和$emit传值,同我们自己在父组件上绑定一个属性和$emit传值可以少一步在父组件中监听@input的操作,所以在组件使用v-model也是很丝滑的。

vue 2.2.0版本新增的model组件选项

默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,但很多时候我们并不想用这两个名字,在vue 2.2.0版本就新增了model组件选项,允许一个自定义组件在使用 v-model 时定制 prop 和 event:

// my-child
<script>
export default {
   
  model: {
   
    prop: 'city', // 对应父组件中绑定的属性(即子组件中接收的props)
    event: 'change'// 对应父组件中监听的事件(即子组件中的$emit)
  },
  props: {
   
    city: {
   
      type: String,
      default: '深圳'
    }
  }
}
</script>
<my-child :city="curCity" @change="(value) => curCity = value" />

v-model在开发中的一些应用

  • 最常用的表单控件双向绑定
  • 自定义组件数据传值双向绑定
  • 在iview之类的UI框架中组件二次封装,如根据业务二次封装弹窗 Modal 组件,可以直接用v-model来控制显隐(注意iview的Modal组件是一开始就渲染在父组件中的,通过display:none隐藏了,所以不能用Modal的created生命周期来做数据初始化,要自己监听value的变化来做相应的初始化逻辑)

v-model的亲戚sync和update

vue从1.0版本就提供了.sync 绑定修饰符,组件 prop 默认是单向绑定的,加上 .sync 后会把子组件的 prop 属性同步回父组件。

但是vue 2.0里为了避免对父组件产生反向影响,子组件需要显式地传递一个事件而不是依赖于隐式地双向绑定,所以次修饰符被无情地移除了。

这个世界就是这么奇妙,不知是不是大家一致反馈双向绑定太丝滑了,vue 2.3.0+ 又把 .sync 以编译时语法糖的形式新增回去了:

// my-child
<script>
export default {
   
  props: {
   
    city: {
   
      type: String,
      default: '深圳'
    }
  },
  methods: {
   
    changeCity() {
   
      this.$emit('update:city', '东莞')
    }
  }
}
</script>
<!-- .sync 修饰符写法 -->
<my-child :city.sync="curCity" />
<!-- 等价于 -->
<my-child :city="curCity" @update:city="(value) => curCity = value" />

天下大势,合久必分,分久必合,在最新的 vue 3.0 版本中,.sync 修饰符又被无情地移除了,且听下面部分更加精彩的分析。

vue 3 中的v-model

对于.sync 修饰符再次被移除,江湖众说纷纭,实际上也没那么玄乎,仅仅是它的功能都被亲戚v-model全盘收编了,它也就跟35岁的程序员一样被光荣劝退了。

在 Vue 2.0 发布后,开发者使用 v-model 指令时必须使用名为 value 的 prop。如果开发者出于不同的目的需要使用其他的 prop,他们就不得不使用 v-bind.sync。此外,由于v-model 和 value 之间的这种硬编码关系的原因,产生了如何处理原生元素和自定义元素的问题。
在 Vue 2.2 中,我们引入了 model 组件选项,允许组件自定义用于 v-model 的 prop 和事件。但是,这仍然只允许在组件上使用一个 v-model。
在 Vue 3 中,双向数据绑定的 API 已经标准化,以减少开发者在使用 v-model 指令时的混淆,并且更加灵活。

1、vue 3 中单独区分出了组件v-model

组件上的 v-model 使用 modelValue 作为 prop 和 update:modelValue 作为事件:

<!-- 组件v-model写法 -->
<my-child v-model="city" />

<!-- vue 1 和 vue 2 中等同于 -->
<my-child :value="curCity" @input="(value) => curCity = value" />

<!-- vue 3 中等同于 -->
<my-child :model-value="curCity" @update:model-value="(value) => curCity = value" />
<my-child :modelValue="curCity" @update:modelValue="curCity = $event" />

2、vue 3 中组件上可以绑定多个v-model

v-model可以接收参数,并且可以绑定多个值(这个王炸就直接干掉了.sync),向下面这样:

<my-child v-model:city="curCity" v-model:country="curCountry" />

<!-- 等价于 -->
<my-child
  :city="curCity"
  :country="curCountry"
  @update:city="curCity = $event"
  @update:country="curCountry = $event"
/>

在子组件中通过 $emit('update:city', e)、$emit('update:country', e)来更改父组件中的值

vue 3 中新增了一个emits选项**:和现有的 props 选项类似,这个选项可以用来定义一个组件可以向其父组件触发的事件。props作为传入,正好可以用emits来对应作为传出,并且也合props一样支持传出参数的校验,vue官方建议我们在组件中所有的emit事件都能在组件的emits选项中声明。

相关文章
|
9月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
774 2
|
8月前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
639 137
|
人工智能 JavaScript 算法
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
1210 0
|
JavaScript UED
用组件懒加载优化Vue应用性能
用组件懒加载优化Vue应用性能
|
11月前
|
人工智能 JSON JavaScript
VTJ.PRO 首发 MasterGo 设计智能识别引擎,秒级生成 Vue 代码
VTJ.PRO发布「AI MasterGo设计稿识别引擎」,成为全球首个支持解析MasterGo原生JSON文件并自动生成Vue组件的AI工具。通过双引擎架构,实现设计到代码全流程自动化,效率提升300%,助力企业降本增效,引领“设计即生产”新时代。
790 1
|
JavaScript 前端开发 开发者
Vue 自定义进度条组件封装及使用方法详解
这是一篇关于自定义进度条组件的使用指南和开发文档。文章详细介绍了如何在Vue项目中引入、注册并使用该组件,包括基础与高级示例。组件支持分段配置(如颜色、文本)、动画效果及超出进度提示等功能。同时提供了完整的代码实现,支持全局注册,并提出了优化建议,如主题支持、响应式设计等,帮助开发者更灵活地集成和定制进度条组件。资源链接已提供,适合前端开发者参考学习。
764 17
|
11月前
|
JavaScript 安全
在 Vue 中,如何在回调函数中正确使用 this?
在 Vue 中,如何在回调函数中正确使用 this?
550 0
|
JavaScript 前端开发 UED
Vue 表情包输入组件实现代码及详细开发流程解析
这是一篇关于 Vue 表情包输入组件的使用方法与封装指南的文章。通过安装依赖、全局注册和局部使用,可以快速集成表情包功能到 Vue 项目中。文章还详细介绍了组件的封装实现、高级配置(如自定义表情列表、主题定制、动画效果和懒加载)以及完整集成示例。开发者可根据需求扩展功能,例如 GIF 搜索或自定义表情上传,提升用户体验。资源链接提供进一步学习材料。
827 1
|
存储 JavaScript 前端开发
如何高效实现 vue 文件批量下载及相关操作技巧
在Vue项目中,实现文件批量下载是常见需求。例如文档管理系统或图片库应用中,用户可能需要一次性下载多个文件。本文介绍了三种技术方案:1) 使用`file-saver`和`jszip`插件在前端打包文件为ZIP并下载;2) 借助后端接口完成文件压缩与传输;3) 使用`StreamSaver`解决大文件下载问题。同时,通过在线教育平台的实例详细说明了前后端的具体实现步骤,帮助开发者根据项目需求选择合适方案。
1068 0
|
JavaScript 前端开发 UED
Vue 项目中如何自定义实用的进度条组件
本文介绍了如何使用Vue.js创建一个灵活多样的自定义进度条组件。该组件可接受进度段数据数组作为输入,动态渲染进度段,支持动画效果和内容展示。当进度超出总长时,超出部分将以红色填充。文章详细描述了组件的设计目标、实现步骤(包括props定义、宽度计算、模板渲染、动画处理及超出部分的显示),并提供了使用示例。通过此组件,开发者可根据项目需求灵活展示进度情况,优化用户体验。资源地址:[https://pan.quark.cn/s/35324205c62b](https://pan.quark.cn/s/35324205c62b)。
588 0

热门文章

最新文章