Vue: 深入理解 v

您所在的位置:网站首页 组件绑定v-model Vue: 深入理解 v

Vue: 深入理解 v

2024-07-10 07:50| 来源: 网络整理| 查看: 265

Vue: 深入理解 v-model 工作原理

文章目录 Vue: 深入理解 v-model 工作原理动态绑定 v-model基础使用v-model 绑定自定义组件(推荐)不使用 v-model 捕获组件 value 值使用 input 事件绑定 valuevalue 与 input 事件联动 小结其他资源参考连接完整代码示例

动态绑定 v-model

用过 vue 的人应该都知道 v-model 的用法,官方文档也告诉我们应该用 v-model 来绑定 input、textarea 等标签的值。

然而当我们想要对 input 等输入控件进行封装的时候,就有必要学会如何在自定义组件上使用 v-model 来实现输入控件的绑定(也就是 React 官方文档中提到的 受控组件 的概念)

基础使用

首先我们先来看第一种,教程文档中教我们的用法

/src/components/BasicVModel.vue Basic v-model Usage export default { name: 'BasicVModel', data() { return { input: '', }; }, methods: { onInput(e) { console.log(`onInput: e.target.value=${e.target.value}`, e); }, onChange(e) { console.log(`onChange: e.target.value=${e.target.value}`, e); }, }, watch: { input(input) { console.log(`[watch] input = ${input}`); }, }, }; 运行截图

我们从输出截图可以看到,输入的过程中会不断触发 Input 事件,然后是 Vue 的 watch 钩子观测到 input 的修改后触发回调;最后在输入 Enter 或是取消 标签的焦点之后才会触发 change 事件

从官方文档我们也能看到,实际上 Vue 利用的是 Input 事件,因此后续将不再讨论 Change 事件的产生

v-model 绑定自定义组件(推荐)

接下来我们要来介绍如何在自定义组件上使用 v-model,首先先给大家推荐标准做法

/src/components/CustomComponent.vue

首先我们的外部组件使用了一个自定义的 CustomComponentInput 组件,然后使用 v-model="input" 将数据绑定到自定义组件上

v-model on Custom Component import CustomComponentInput from './CustomComponentInput.vue'; export default { components: { CustomComponentInput }, data() { return { input: 'Hello', }; }, methods: { onInput(input) { console.log(`onInput: input = ${input}`); }, }, watch: { input(input) { console.log(`[watch] input = ${input}`); }, }, mounted() { console.log(`[mounted] input = ${this.input}`); }, };

接下来我们要怎么定义子组件来满足上述 v-model 的用法呢?

/src/components/CustomComponentInput.vue export default { name: 'CustomComponentInput', props: ['value'], };

根据官方文档的描述,v-model 将主动利用组件的 prop: value 以及 Input 事件来满足 v-model 的绑定,而对于 Input 事件可以利用 Vue.prototype.$emit 来传递并对外抛出 Input 事件,同时我们的参数设置为 $event.target.value 来满足外面组件对于 value 的取值正确

运行截图

观察上面运行截图可以看到,当我们在子组件正确的绑定 value 与 Input 事件时,外部组件就能正确的获取实时的 input 值(这里我们的外部组件将数据绑定在 input 数据字段上)

不使用 v-model 捕获组件 value 值

到这里其实就已经足够大家开发使用了,下面我们透过自定义联动 value 值的方式来尝试理解 Vue 的 v-model 进行双向绑定的逻辑

使用 input 事件

如果我们选择不使用 v-model 来绑定自定义组件数据的话,实际上我们还是可以透过 Input 事件获取数据修改的状态

/src/components/UnbindCustomComponent.vue Unbind Custom Component import CustomComponentInput from './CustomComponentInput.vue'; export default { components: { CustomComponentInput }, methods: { onInput(input) { console.log(`onInput: input = ${input}`); console.log(`value = ${this.$refs.input_ref.value}`); }, }, }; 运行截图

从上图能看到,Input 事件接到的 input 是正确的,然而使用 $refs 获取的组件 value 字段却是 undefined。实际上这是因为我们的输入框实际上将输入的字符串绑定在内部的 标签的 value 上,因此我们直接取组件的 value 当然是没东西的

绑定 value

那这时候如果我们在外部组件加一个 value 并使用 v-bind 绑定到子组件可不可行呢?

/src/components/UnbindCustomComponent.vue Unbind Custom Component import CustomComponentInput from './CustomComponentInput.vue'; export default { components: { CustomComponentInput }, data() { return { input: 'Init value', }; }, methods: { onInput(input) { console.group('onInput'); console.log(`onInput: input = ${input}`); console.log(`this.input = ${this.input}`); console.log(`value = ${this.$refs.input_ref.value}`); console.groupEnd(); }, }, }; 运行截图

这时候我们可以看到,一开始组件的 value 确实与 input 字段相同,但是经过一些输入修改之后,组件的 value 属性依旧还是原本的值,并没有实现 v-model 的双向绑定效果。

这是因为这时候仅仅只是将 input 字段绑定到组件的 value 属性,但是却还是与内部的 标签是脱节的,也就是说是两份完全独立的数据字段

value 与 input 事件联动

这时候其实我们只需要在 Input 事件的回调,将新的数据值同步到 input 字段就可以了

/src/components/UnbindCustomComponent.vue import CustomComponentInput from './CustomComponentInput.vue'; export default { // ... methods: { onInput(input) { // 同步到 input 字段上 this.input = input; console.group('onInput'); console.log(`onInput: input = ${input}`); console.log(`this.input = ${this.input}`); console.log(`value = ${this.$refs.input_ref.value}`); this.$nextTick(() => { console.log(`[$nextTick] value = ${this.$refs.input_ref.value}`); console.groupEnd(); }); }, }, }; 运行截图

这时候我们就能看到,外部组件的 input 字段与自定义 Input 组件的 value 确实是与当前输入字符串同步了。

然而最后还有一个遗留问题是,由于我们利用 $refs 取出组件的 value 属性值,但是 onInput 回调却是发生在组件响应式更新之前,也就是说如上图 value 总会是"慢一拍"的感觉,这时候我们就可以利用 Vue.prototype.$nextTick,在 Vue 组件的下一跳中再去取组件的 value 就可以了

小结

本篇是作者在写 Vue 的时候遇到的疑问之一,由于作者相较之下更熟悉 React 的运行机制,回头来看 Vue 却是能够慢慢发觉更多内部机制运行规律,对于响应式的把握也更高一些。

其他资源 参考连接 TitleLink自定义组件的 v-model - Vue 官方https://cn.vuejs.org/v2/guide/components-custom-events.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%84%E4%BB%B6%E7%9A%84-v-model 完整代码示例

https://github.com/superfreeeee/Blog-code/tree/main/front_end/vue/vue_vmodel_deep_dive



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3