VUE—数据响应原理真的是双向绑定吗?

news/2024/7/10 2:42:21 标签: vue

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

在Vue中体现出双向绑定作用的方式有两种,在分析之前我们先介绍这两种使用方式有什么区别。

1)v-model 属性

2).sync 修饰符

v-model

2.2.0+ 新增

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value 特性用于不同的目的。model 选项可以用来避免这样的冲突:

ChildBox.vue

<template>
  <input type="checkbox"
         :checked="checked"
         @change="$emit('change', $event.target.checked)"/>
</template>

<script>
export default {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  }
}
</script>

Index.vue

<template>
  <div>
    <ChildBox v-model="val"/>
    <!-- 解析后 -->
    <ChildBox :value="val"
              @change="data => (val = data)"/>
  </div>
</template>

分析一下上面的代码。ChildBox.vue文件对checkbox做了简单的封装,提供了checked参数。Index.vue文件为父组件,引用了ChildBox作为自己的子组件,这里需要注意一下。val值的绑定使用的v-model而并不是v-bind:checkbox。一开始我们有说到双向绑定方式有两种一种是v-model,另一种是.sync(这个后面讲)。如果使用v-model,子组件的props应该设置value值,而向上传递应该为$emit(‘input’)才对。所以这里还有一个重点,model的作用。

model

2.2.0 新增

允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,但是一些输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突。

.sync 修饰符

2.3.0+ 新增

在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以修改父组件,且在父组件和子组件都没有明显的改动来源。

这也是为什么我们推荐以 update:myPropName 的模式触发事件取而代之。举个例子,在一个包含 title prop 的假设的组件中,我们可以用以下方法表达对其赋新值的意图:

ChildBox.vue

<template>
  <input type="checkbox"
         :checked="checked"
         @change="$emit('update:checked', $event.target.checked)"/>
</template>

<script>
export default {
  props: {
    checked: Boolean
  }
}
</script>

Index.vue

<template>
  <div>
    <ChildBox :checked.sync="val"/>
    <!-- 解析后 -->
    <ChildBox :checked="val"
              @update:checked="data => (val = data)"/>
  </div>
</template>

分析一下上面的代码有什么变化,父组件v-model:checked.sync替换掉。子组件因不适用v-model,所以不需要model配置。change函数改为$emit'update:checkde',$event.target.checked)。

v-model源码分析

借助ustbhuangyi Vue.js技术揭秘。这里只做总结比对,详细分析过程可查看链接。

以下面代码为例:

let vm = new Vue({
  el: '#app',
  template: '<div>'
  + '<input v-model="message" placeholder="edit me">' +
  '<p>Message is: {{ message }}</p>' +
  '</div>',
  data() {
    return {
      message: ''
    }
  }
})

在 input 元素上设置了 v-model 属性,绑定了 message,当我们在 input 上输入内容时,message 也会同时发生变化。

源码generate函数:

function generate (
  ast,
  options
) {
  var state = new CodegenState(options);
  var code = ast ? genElement(ast, state) : '_c("div")';
  return {
    render: ("with(this){return " + code + "}"),
    staticRenderFns: state.staticRenderFns
  }
}

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

with(this) {
  return _c('div',[_c('input',{
    directives:[{
      name:"model",
      rawName:"v-model",
      value:(message),
      expression:"message"
    }],
    attrs:{"placeholder":"edit me"},
    domProps:{"value":(message)},
    on:{"input":function($event){
      if($event.target.composing)
        return;
      message=$event.target.value
    }}}),_c('p',[_v("Message is: "+_s(message))])
    ])
}

最终转化为:

<input
  v-bind:value="message"
  v-on:input="message=$event.target.value">

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

ustbhuangyi 在Vue.js 技术揭秘中也详细的介绍v-model在组件中的实现原理,这里就不过多的陈述了。

总结

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

最后有一个问题 v-model.sync 都可以实现数据双向绑定的效果,那到底用哪种更合理呢?欢迎回复阐述你的观点。

最后

为了帮助大家让学习变得轻松、高效,给大家免费分享一大批资料,帮助大家在成为全栈工程师,乃至架构师的路上披荆斩棘。在这里给大家推荐一个前端全栈学习交流圈:866109386.欢迎大家进群交流讨论,学习交流,共同进步。

当真正开始学习的时候难免不知道从哪入手,导致效率低下影响继续学习的信心。

但最重要的是不知道哪些技术需要重点掌握,学习时频繁踩坑,最终浪费大量时间,所以有有效资源还是很有必要的。

最后祝福所有遇到瓶疾且不知道怎么办的前端程序员们,祝福大家在往后的工作与面试中一切顺利。


http://www.niftyadmin.cn/n/1300746.html

相关文章

Vue渲染过程浅析

Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML。但是模板毕竟是模板&#xff0c;不是真实的dom节点。从模板到真实dom节点还需要经过一些步骤 把模板编译为render函数实例进行挂载, 根据根节点render函数的调用&#xff0c;递归的生成虚拟dom对比虚拟dom&#xff0c…

vue基础之v-bind属性、class和style用法分析

一、属性 属性: v-bind:src"" width/height/title… 简写: :src"" 推荐 效果能出来&#xff0c;但是会报一个404错误 效果可以出来&#xff0c;不会发404请求 window.onloadfunction(){new Vue({el:#box,data:{url:https://www.baidu.com/img/bd_log…

如何优化我们的代码(vue项目)

前言 作为一个前端&#xff0c;可能绝大多数的时间都是在写的业务代码&#xff0c;时间一长&#xff0c;大家会觉得乏味、没意思等等&#xff0c;但是其实就算只是写业务代码&#xff0c;我们也依然能够找到有兴趣的点&#xff0c;说的简单一点就是代码优化&#xff0c;不仅仅…

你不知道的浏览器渲染原理

前言 浏览器的内核是指支持浏览器运行的最核心的程序&#xff0c;分为两个部分的&#xff0c;一是渲染引擎&#xff0c;另一个是 JS 引擎。渲染引擎在不同的浏览器中也不是都相同的。目前市面上常见的浏览器内核可以分为这四种&#xff1a;Trident&#xff08;IE&#xff09;、…

用 Node.js 写一个多人游戏服务器引擎

英文原文&#xff1a;https://www.smashingmagazine.com/2018/12/multiplayer-text-adventure-engine-node-js/ 摘要 听说过文字冒险游戏吗&#xff1f; 如果你的年龄足够大的话&#xff08;就像我一样&#xff09;&#xff0c;那么你可能听说过、甚至玩过“back in the day”…

vue基础之事件简写、事件对象、冒泡、默认行为、键盘事件实例分析

v-on:click/mouseover......简写的:click"" 推荐事件对象:click"show($event)"事件冒泡:阻止冒泡: a). ev.cancelBubbletrue;b). click.stop 推荐默认行为(默认事件):阻止默认行为:a). ev.preventDefault();b). contextmenu.prevent 推荐键盘…

Vue.js特性Scoped Slots的浅析

什么是scoped slots A scoped slot is a special type of slot that functions as a reusable template (that can be passed data to) instead of already-rendered-elements. 上面是官方的定义。 作用域插槽&#xff08;Scoped Slots&#xff09;是vue.js中一个非常有用的特性…

页面性能优化之原生JS实现图片懒加载

在项目开发中&#xff0c;我们往往会遇到一个页面需要加载很多图片的情况。我们可以一次性加载全部的图片&#xff0c;但是考虑到用户有可能只浏览部分图片。所以我们需要对图片加载进行优化&#xff0c;只加载浏览器窗口内的图片&#xff0c;当用户滚动时&#xff0c;再加载更…