首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Vue技术揭秘-v-model

v-model

很多同学在理解 Vue 的时候都把 Vue 的数据响应原理理解为双向绑定,但实际上这是不准确的,我们之前提到的数据响应,都是通过数据的改变去驱动 DOM 视图的变化,而双向绑定除了数据驱动 DOM 外, DOM 的变化反过来影响数据,是一个双向关系,在 Vue 中,我们可以通过 来实现双向绑定。

即可以作用在普通表单元素上,又可以作用在组件上,它其实是一个语法糖,接下来我们就来分析 的实现原理。

表单元素

为了更加直观,我们还是结合示例来分析:

这是一个非常简单 demo,我们在 元素上设置了 属性,绑定了 ,当我们在 上输入了内容, 也会同步变化。接下来我们就来分析 Vue 是如何实现这一效果的,其实非常简单。

也是先从编译阶段分析,首先是 阶段, 被当做普通的指令解析到 中,然后在 阶段,执行 的时候,会执行 ,它的定义在 中:

方法就是遍历 ,然后获取每一个指令对应的方法 ,这个指令方法实际上是在实例化 的时候通过 传入的,这个 就是编译相关的配置,它在不同的平台下配置不同,在 环境下的定义在 下:

定义在 中:

那么对于 而言,对应的 函数是在 中定义的 函数:

也就是说我们执行 就是在执行 函数,它会根据 AST 元素节点的不同情况去执行不同的逻辑,对于我们这个 case 而言,它会命中 的逻辑,稍后我们也会介绍组件的处理,其它分支同学们可以自行去看。我们来看一下 的实现:

函数先处理了 ,它的不同主要影响的是 和 的值,对于我们的例子, 为 , 为 。然后去执行 去生成代码,它的定义在 中:

该方法首先对 对应的 做了解析,它处理了非常多的情况,对我们的例子, 就是 ,所以返回的 为 ,然后我们就得到 ,也就是 。然后我们又命中了 为 true 的逻辑,所以最终的 为 。 生成完后,又执行了 2 句非常关键的代码:

这实际上就是 实现 的精髓,通过修改 AST 元素,给 添加一个 ,相当于我们在 上动态绑定了 ,又给 添加了事件处理,相当于在 上绑定了 事件,其实转换成模板如下:

其实就是动态绑定了 的 指向了 变量,并且在触发 事件的时候去动态把 设置为目标值,这样实际上就完成了数据双向绑定了,所以说 实际上就是语法糖。

再回到 ,它接下来的逻辑就是根据指令生成一些 的代码:

对我们的例子而言,最终生成的 代码如下:

关于事件的处理我们之前的章节已经分析过了,所以对于 的 而言,完全就是语法糖,并且对于其它表单元素套路都是一样,区别在于生成的事件代码会略有不同。 除了作用在表单元素上,新版的 Vue 还把这一语法糖用在了组件上,接下来我们来分析它的实现。

组件

为了更加直观,我们也是通过一个例子分析:

可以看到,父组件引用 子组件的地方使用了 关联了数据 ;而子组件定义了一个 的 ,并且在 事件的回调函数中,通过 派发了一个事件,为了让 生效,这两点是必须的。接着我们从源码角度分析实现原理,还是从编译阶段说起,对于父组件而言,在编译阶段会解析 指令,依然会执行 函数中的 函数,接着执行 中定义的 函数,并命中如下逻辑:

函数定义在 中:

的逻辑很简单,对我们的例子而言,生成的 的值为:

那么在 之后, 函数中有一段逻辑如下:

那么父组件最终生成的 代码如下:

然后在创建子组件 阶段,会执行 函数,它的定义在 中:

其中会对 的情况做处理,执行 方法:

逻辑很简单,给 添加 ,并且给 添加 ,对我们的例子而言,扩展结果如下:

其实就相当于我们在这样编写父组件:

子组件传递的 绑定到当前父组件的 ,同时监听自定义 事件,当子组件派发 事件的时候,父组件会在事件回调函数中修改 的值,同时 也会发生变化,子组件的 值被更新。这就是典型的 Vue 的父子组件通讯模式,父组件通过 把数据传递到子组件,子组件修改了数据后把改变通过 事件的方式通知父组件,所以说组件上的 也是一种语法糖。另外我们注意到组件 的实现,子组件的 以及派发的 事件名是可配的,可以看到 中对这部分的处理:

也就是说可以在定义子组件的时候通过 选项配置子组件接收的 名以及派发的事件名,举个例子:

子组件修改了接收的 名以及派发的事件名,然而这一切父组件作为调用方是不用关心的,这样做的好处是我们可以把 这个 作为其它的用途。

总结

那么至此, 的实现就分析完了,我们了解到它是 Vue 双向绑定的真正实现,但本质上就是一种语法糖,它即可以支持原生表单元素,也可以支持自定义组件。在组件的实现中,我们是可以配置子组件接收的 名称,以及派发的事件名称。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230130A011LV00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券