【Vue2从入门到精通】详解Vue数据双向绑定原理及手动实现双向绑定

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
性能测试 PTS,5000VUM额度
函数计算FC,每月15万CU 3个月
简介: Vue是采用数据劫持结合发布者-订阅者模式的方式,通过使用ES5中的Object.defineProperty()方法来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。

在这里插入图片描述

人工智能福利文章

我们先从单向绑定切入单向绑定非常简单,就是把Model绑定到View。

什么是双向绑定呢?当我们用JavaScript代码更新Model时,View就会自动更新,在单向绑定的基础上,用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定。

✨数据双向绑定的原理

数据双向绑定的原理之前,我们先来了解一下什么是MVVM。

MVVM是一种设计思想,它是Model-View-ViewModel的缩写。它也是MVC的增强版。

  • Model是代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。
  • View是代表UI组件,它负责将数据模型转化成UI展现出来。
  • ViewModel是一个同步View和Model的对象。

ViewModel的主要职责:

  • 数据变化后更新视图
  • 视图变化后更新数据

当然,它还有两个主要部分组成

  • 监听器(Observer):对所有数据的属性进行监听
  • 解析器(Compiler):对每个元素节点的指令进行扫描跟解析,根据指令模板替换数据,以及绑定相应的更新函数

    ✨Vue数据双向绑定原理

    Vue是采用数据劫持结合发布者-订阅者模式的方式,通过使用ES5中的Object.defineProperty()方法来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。

Object.defineProperty()允许在对象上定义新的属性,以及修改或删除现有属性的特性,其中包括get、set、enumerable和configurable等。

在这里插入图片描述

✨实现数据双向绑定的步骤

  1. 创建Vue实例时,在data属性中定义需要双向绑定的数据。
  2. 在模板中使用v-model指令将输入控件绑定到数据属性上。
    在Vue内部,使用Object.defineProperty()方法将数据属性转换为getter/setter形式,从而实现数据的响应式变化。
  3. 当输入控件的值发生变化时,Vue会自动调用数据属性的setter方法,从而更新数据的值。
  4. 当数据的值发生变化时,Vue会自动更新相关的DOM元素,从而实现数据与视图的双向绑定。

示例代码如下:

html

<div id="app">
  <input v-model="message">
  <p>{
  
  { message }}</p>
</div>

javascript

var vm = new Vue({
   
   
  el: '#app',
  data: {
   
   
    message: ''
  }
});

在上面的代码中,v-model指令将输入框和message属性进行了双向绑定。当输入框的值发生变化时,message属性的setter方法会被调用,从而更新数据。当message属性的值发生变化时,相关的DOM元素也会自动更新,从而实现了数据与视图的双向绑定。

需要注意的是,Vue的双向绑定仅适用于一些特定的输入控件,如input、textarea和select等。对于自定义组件,需要手动实现数据的双向绑定。

如何手动实现数据的双向绑定呢?请继续往下看。

✨手动实现自定义组件的双向绑定的步骤

  1. 在自定义组件中,通过props属性接收父组件传递的数据,并在组件中定义一个内部变量来保存这些数据。
  2. 在组件内部使用v-model指令将输入控件绑定到内部变量上。
  3. 在组件内部监听输入控件的变化事件,并在事件处理函数中更新内部变量的值。
  4. 在组件内部通过$emit()方法触发一个自定义事件,并将内部变量作为参数传递给父组件。
  5. 在父组件中使用自定义事件的处理函数来更新父组件中的数据。

示例代码如下:

<!-- 父组件 -->
<template>
  <div>
    <my-component v-model="message"></my-component>
    <p>{
   
   {
   
    message }}</p>
  </div>
</template>

<script>
  import MyComponent from './MyComponent.vue';

  export default {
   
   
    components: {
   
   
      'my-component': MyComponent
    },
    data() {
   
   
      return {
   
   
        message: ''
      }
    }
  }
</script>

<!-- 自定义组件 -->
<template>
  <div>
    <input type="text" v-model="internalValue">
  </div>
<template>
<script>
  export default {
   
   
    props: ['value'],
    data() {
   
   
      return {
   
   
        internalValue: ''
      }
    },
    mounted() {
   
   
      this.internalValue = this.value;
    },
    watch: {
   
   
      internalValue() {
   
   
        this.$emit('input', this.internalValue);
      }
    }
  }
</script>

在上面的代码中,我们定义了一个名为value的props属性来接收父组件传递的数据,同时定义了一个名为internalValue的内部变量来保存这些数据。在组件挂载后,我们将value的值赋值给internalValue。

在组件内部使用v-model指令将输入控件绑定到internalValue上。当输入控件的值发生变化时,我们使用watch来监听internalValue的变化事件,并在事件处理函数中使用$emit()方法触发一个名为input的自定义事件,并将internalValue作为参数传递给父组件。

在父组件中,我们可以通过v-model指令将message属性与自定义组件的value属性进行双向绑定。当自定义组件的input事件被触发时,我们可以在事件处理函数中将事件的参数作为message属性的值进行更新。

示例代码如下:

<!-- 父组件 -->
<template>
  <div>
    <my-component v-model="message"></my-component>
    <p>{
   
   {
   
    message }}</p>
  </div>
</template>

<script>
  import MyComponent from './MyComponent.vue';

  export default {
   
   
    components: {
   
   
      'my-component': MyComponent
    },
    data() {
   
   
      return {
   
   
        message: ''
      }
    }
  }
</script>

<!-- 自定义组件 -->
<template>
  <div>
    <input type="text" v-model="internalValue">
  </div>
</template>

<script>
  export default {
   
   
    props: ['value'],
    data() {
   
   
      return {
   
   
        internalValue: ''
      }
    },
    mounted() {
   
   
      this.internalValue = this.value;
    },
    watch: {
   
   
      internalValue() {
   
   
        this.$emit('input', this.internalValue);
      }
    }
  }
</script>

在上面的代码中,我们定义了一个名为message的数据属性,并将它与自定义组件的value属性进行了双向绑定。


✍创作不易,求关注😄,点赞👍,收藏⭐️

同时,在自定义组件中,我们实现了数据的双向绑定,并通过$emit()方法触发了一个名为input的自定义事件来与父组件进行通信。这样就实现了自定义组件的双向绑定。

相关文章
|
27天前
|
缓存 JavaScript 搜索推荐
Vue SSR(服务端渲染)预渲染的工作原理
【10月更文挑战第23天】Vue SSR 预渲染通过一系列复杂的步骤和机制,实现了在服务器端生成静态 HTML 页面的目标。它为提升 Vue 应用的性能、SEO 效果以及用户体验提供了有力的支持。随着技术的不断发展,Vue SSR 预渲染技术也将不断完善和创新,以适应不断变化的互联网环境和用户需求。
41 9
|
1月前
|
JavaScript 前端开发 算法
对比一下Vue2 和 Vue3?—— 8个方面给你答案
本文介绍了 Vue 和 React 的起源、核心思想、表现形式、API 差异、社区差异、升级方向、响应式原理、Diff 算法、事件机制,并进行了总结。Vue 以其渐进式框架设计和简洁性著称,而 React 则强调单向数据流和灵活性。两者均支持组件化开发和虚拟 DOM,适用于不同的开发场景。
25 0
对比一下Vue2 和 Vue3?—— 8个方面给你答案
|
1月前
|
存储 JavaScript 前端开发
前端开发:Vue.js入门与实战
【10月更文挑战第9天】前端开发:Vue.js入门与实战
|
1月前
|
缓存 JavaScript 前端开发
对比一下Vue2和Vue3?
本文首发于微信公众号“前端徐徐”,详细对比了 Vue 2 和 Vue 3 在原理、生命周期、性能、编码方式、API、Diff 算法、打包构建、TS 支持等八个方面的差异,帮助读者全面了解两者的不同之处。
192 0
对比一下Vue2和Vue3?
|
29天前
|
JavaScript 前端开发 API
vue3知识点:Vue3.0中的响应式原理和 vue2.x的响应式
vue3知识点:Vue3.0中的响应式原理和 vue2.x的响应式
25 0
|
29天前
|
JavaScript 前端开发 C#
从入门到放弃,我们为何从 Blazor 回到 Vue
【10月更文挑战第29天】在前端开发中,许多开发者从尝试新技术 Blazor 最终回到熟悉的 Vue。主要原因包括:1) Blazor 学习曲线陡峭,Vue 上手容易;2) Vue 开发工具成熟,开发效率高;3) Vue 性能优异,优化简单;4) Vue 社区庞大,生态丰富;5) 项目需求和团队协作更适配 Vue。选择技术栈需综合考虑多方面因素。
|
1月前
|
JavaScript 前端开发 Java
vue2知识点:Vue封装的过度与动画
vue2知识点:Vue封装的过度与动画
14 0
|
7天前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
vue学习第四章
|
7天前
|
JavaScript 前端开发
vue学习第九章(v-model)
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript与Vue的大一学生,自学前端2年半,正向全栈进发。此篇介绍v-model在不同表单元素中的应用及修饰符的使用,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
vue学习第九章(v-model)
|
7天前
|
JavaScript 前端开发 开发者
vue学习第十章(组件开发)
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文深入讲解Vue组件的基本使用、全局与局部组件、父子组件通信及数据传递等内容,适合前端开发者学习参考。持续更新中,期待您的关注!🎉🎉🎉
vue学习第十章(组件开发)
下一篇
无影云桌面