Vue单向绑定与双向绑定解析

在讲绑定之前我们要理解MVVM框架,这对我们理解单向以及双向绑定有很大的帮助.

一 MVVM框架

  1. M : model(模型) 数据保存

  2. V : view(视图) 用户界面

  3. VM : ViewModel 把Model和View关联起来,ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。

    所有的通信模式是双向的.

在这里插入图片描述

1.1 MVVM框架的互动模式

  1. 用户向 View 发送指令(DOM 事件,改变URL,输入表单等)由viewmodel这个观察者感知变化,然后通知 Model 发生相应改变.

  2. 当 Model(数据) 发生改变,ViewModel 也能感知到变化,使 View 作出相应更新,用户看到的界面更新。

总结: 上面的过程就是我们所熟知的双向绑定,在前端页面中,把Model用纯JavaScript对象表示,View负责显示,两者做到了最大限度的分离。

这样开发者就可以只关注Model的变化,让MVVM框架去自动更新DOM的状态,从而把开发者从操作DOM的繁琐步骤中解脱出来!

1.2 实例体会MVVM框架

上面的话,可能让你有些费解,那么我们来看一个例子:

例子: 改变p标签里的文本内容

①原生的操作方式

<!-- html部分 -->
<p id="pTxt"></p> 

// JS部分
var PTxt = document.getElementById('pTxt');
PTxt.textContent = '我是原生操作DOM';

我们发现在原生的里面即需要我们提供数据,又需要我们去操作DOM元素,那么在MVVM框架(Vue)里呢.

② MVVM操作方式

<!-- html部分 view -->
<p id="pTxt"> {{ pTxt }}</p>  

// JS部分 viewmodel
var vm = new Vue({
 el : '#pTxt',
 	//model
   data : {
       pTxt : '我是MVVM的框架方式'
   }
})

在MVVM框架里,我们不关心DOM的结构与操作,而是关心数据如何存储。这里没有操作DOM也达到了效果,只要我们修改了数据,那么view(界面)就会得到相应的改变.而操作DOM的过程都是MVVM这个框架帮助我们去完成了.所以我们就可以只关注数据了.

二 单向数据绑定

MVVM框架自动把Model的变化映射到DOM结构上,那么Model和View进行数据传递的方式又是怎样的呢?

单向绑定:把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新。( Model —> View )

2.1 插值表达式的形式

插值表达式 {{Model中的变量名称}} 写在两个标签之间的

<div id="app">
    <p> {{ firstname }}</p> 
    <p> {{ lastname }}</p> 
</div>

var vm = new Vue({

           el : '#app',
           data : {
                firstname : 'alex',
                lastname : 'li'
           }
       })

数据是在data中定义好了之后传递过去的.model —> view
在这里插入图片描述

2.1.1 使用插值表达式的注意点

Vue实例需要长时间编译的时候,会出现闪烁现象(页面出现 “{{ 内容 }}” )。比如:引入vue.js在页面底部引入,当浏览器解析的时候回从上到下解析时,会先显示插值表达式的原样,当解析完之后,才会用model中的数据去替换插值表达式里的内容。

<p>{{message}}</p>
<p v-text="message"></p>

<script src="/vue.js"></script>

第一种解决办法:使用v-cloak配合css

//html内容
<div id="app" v-cloak>
  {{msg}}
</div>

//css内容
[v-cloak] {
 display: none;
}

第二种解决办法:使用指令v-text、v-html

<p v-text="message"></p>
<p v-html="message2"></p>

因为即便是Vue实例需要长时间编译,可是我的标签里面没有文本内容,是后面编译完成后再渲染上去的,所以并不会出现闪烁的现象。

2.2 v-bind指令

绑定属性的方法,这样我们即可动态的改变属性值

v-bind:属性名 = " 值1 "

//简写

:属性名 = "值1"

v-bind指令能够支持数据的单向绑定,只需要在该属性前面加上v-bind:指令,这样Vue在解析的时候会识别出该指令,就会将该将其属性的值跟Vue实例的Model进行绑定。这样我们就可以通过Model来动态的操作该属性从而实现DOM的联动更新。( Model —> View )

<!-- view视图 -->
<div id="vm">
	   <!-- v-bind全写的形式 -->
       <p v-bind:class="classed">Hello, {{name}}!</p>
	   <!-- v-bind简写的形式 -->
	   <!-- <p :class="classed">Hello, {{name}}!</p> -->
 </div>

// viewmodel
var vm = new Vue({
   el: '#vm',
   	// model
     data: {
         name: 'DroidMind',
         classed: 'red'
     }
 });

在这里插入图片描述

2.2.1 什么时候用v-bind

什么时候用:
如果我们需要把我们的属性值,当成一个变量来使用,那么就是用v-bind.常见的在渲染的时候,属性是一个变量,此时就可以用v-bind绑定.

//其中的src路径就是通过数据渲染得到的
<img :src="goodsDetail.imglist[0].original_path">

2.2.2 v-bind使用时的注意点

这里说一下v-bind绑定属性值的一个特性:一般情况下,使用v-bind给元素特性(attribute)传递值时,Vue会将""中的内容当做一个表达式。

比如:

<div attr="message">hello</div>

上面这样,div元素的attr特性值就是message。
而这样

<div v-bind:attr="message">hello</div>

这里的message应该是Vue实例的data的一个属性,这样div元素的attr特性值就是message这个属性的值。

之所以说是一般情况,是因为class和style特性并不是这样。用v-bind:class和class传入正常的类名,效果是一样的,因为对于这两个特性,Vue采用了合并而不是替换的原则。(请查阅官网Class与style绑定)

三 双向绑定

双向数据绑定非常简单,就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新。但是当用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定。

3.1 v-model指令
v-model主要是用在表单元素中,实现了双向绑定。
当用户填写表单时,View的状态就被更新了,如果此时Model的数据也会随着输入的数据动态的更新,那就相当于我们把Model和View做了双向绑定。

<!-- view视图 -->
<form id="vm" action="#">
     <p><input v-model="email"></p>
     <p><input v-model="name"></p>
 </form>

// viewmodel
var vm = new Vue({
   el: '#vm',
   // model
    data: {
        email: '',
        name: ''
    }
});

在这里插入图片描述

这里的数据与视图之间的关系是:

  1. 刚开始viewmodel模块这个观察者将model中初始化数据email和name交给view渲染展现到界面上.
  2. 当用户在输入框里输入内容,view发生变化此时viewmodel这个观察者察觉到变化,将输入框里的内容返回给model中的数据email和name,此时model中的数据email和name一致是实时更新的.

3.2 双向数据绑定的原理

这里有篇文章很好点击这里 ,本文只做一些简单的梳理.

vue.js的双向数据绑定:则是采用数据劫持结合发布者-订阅者模式的方式来实现,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

其中的关键点:

  1. 监听到data中属性的改变
  2. 模型值变化之后,正确更新到视图
  3. 发布者订阅模式【了解】

3.2.1 监听到data中属性的改变(Observer)

利用Obeject.defineProperty()来监听属性变动,具体的做法是通过set函数与get函来实现监听,比如:

var person = {}      
         var _name = ""

         Object.defineProperty(person,'name',{
            //设置person的name属性时触发
            set: function(newVal){
                console.log(newVal);     
                _name = newVal
            },
            //获取person的name属性时触发
            get: function(){
                return _name
            }
 })

在这里插入图片描述
我们可以在控制台来设置获取person对象,确实也可以监听到对象的获取和修改,而vue底层也是这样来实现的,将需要观察的data对象里的属性都加上getter和setter,就能监听到了数据变化.

3.2.2 模型值变化之后,正确更新到视图(Compile)

通过上面的步骤我们已经可以监听数据的变化,现在要考虑的事情是如何将数据变化的值更新到视图上.

这里面的步骤是:将变化后的数据替换掉模板里的变量,达到更新视图的目的.同时对dom节点绑定相应的更新函数
在这里插入图片描述

3.2.3 桥梁(Watch)

我们粗糙的理解Observer只是只能做到监听数据的变化,Compile只能更新视图,如何将变化的数据传给Compile,以便其能更新视图呢?方法就是watch.
在这里插入图片描述

最经典的理解:

而我所理解的双向数据绑定无非就是在单向绑定的基础上给可输入元素(input、textare等)添加了change(input)事件,来动态修改model和 view

四 MVC设计模式

MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发。但是所有的通信都是单向的.

  1. Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
  2. View(视图) - 视图代表模型包含的数据的可视化。
  3. Controller(控制器) - 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。

在这里插入图片描述

4.2 互动模式

4.2.1 View 接受指令,传递给 Controller
在这里插入图片描述
这里的用户直接修改界面,让view接收指令,比如表单输入将数据传递给控制器(controller),通过控制器再来要求model来改变view的视图.

4.2.2 通过controller接受指令
在这里插入图片描述

本文参考资料:

[1] 阮一峰 《MVC,MVP 和 MVVM 的图示》 http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html
[2] 廖雪峰 《MVVM,单向绑定,双向绑定》
https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/00147574857851718682c42639f466a934ad9d4f485d1f2000

猜你喜欢

转载自blog.csdn.net/weixin_42839080/article/details/83444562