您的位置:首页 > 产品设计 > UI/UE

vue双向数据绑定原理探究(附demo)

2017-05-08 10:24 941 查看
昨天被导师叫去研究了一下vue的双向数据绑定原理。。。本来以为原理的东西都非常高深,没想到vue的双向绑定真的很好理解啊。。。自己动手写了一个。

传送门

双向绑定的思想

双向数据绑定的思想就是数据层与UI层的同步,数据再两者之间的任一者发生变化时都会同步更新到另一者。

双向绑定的一些方法

目前,前端实现数据双向数据绑定的方法大致有以下三种:

1.发布者-订阅者模式(backbone.js)

思路:使用自定义的data属性在HTML代码中指明绑定。所有绑定起来的JavaScript对象以及DOM元素都将“订阅”一个发布者对象。任何时候如果JavaScript对象或者一个HTML输入字段被侦测到发生了变化,我们将代理事件到发布者-订阅者模式,这会反过来将变化广播并传播到所有绑定的对象和元素。

2.赃值检测(angular.js)

思路:通过轮询的方式检测数据变动。才特定的事件触发时进入赃值检测。

大致如下:

•   DOM事件,譬如用户输入文本,点击按钮等。( ng-click )

•   XHR响应事件 ( $http )

•   浏览器Location变更事件 ( $location )

•   Timer事件( $timeout , $interval )

•   执行 $digest() 或 $apply()

3.数据劫持(vue.js)

思路:使用Object.defineProperty对数据对象做属性get和set的监听,当有数据读取和赋值操作时则调用节点的指令,这样使用最通用的=等号赋值就可以触发了。

wue双向数据绑定小demo思路

①  构造一个Wue对象,定义该对象的属性el、data,创建对象的时候传相应数据,并执行init()方法。

1
2
3
4
5
var
 
Wue=
function
(params){

    
this
.el=document.querySelector(params.el);

    
this
.data=params.data;

    
this
.init();

};

②  Init方法中执行bindText和bindModel方法,这两个方法分别是解析dom中绑定了w-model、w-text指令的html,并作相应处理。

1
2
3
4
init:
function
(){

            
this
.bindText();

            
this
.bindModel();

       
}

③  bindText方法,把带有w-text指令的元素放进一个数组中,如:w-text=’demo’,然后令其innerHTML的值等于传进来的data[demo]。

1
2
3
4
5
6
7
8
9
bindText:
function
(){

          
var
 
textDOMs=
this
.el.querySelectorAll(
'[w-text]'
),

          
bindText;

          
for
(
var
 
i=0;i<textDOMs.length;i++){

             
bindText=textDOMs[i].getAttribute(
'w-text'
);

             
textDOMs[i].innerHTML=
this
.data[bindText];

          
}

        
}

④  bindModel方法,把带有w-model指令的元素(一般为form相关元素)放进一个数组中,如:w-model=’demo’,为每一个元素绑定keyup事件(兼容浏览器写法)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
bindModel:
function
(){

  
var
 
modelDOMs=
this
.el.querySelectorAll(
'[w-model]'
),

  
bindModel;

  
var
 
_that=
this
;

  
for
(
var
 
i=0;i<modelDOMs.length;i++){

    
bindModel=modelDOMs[i].getAttribute(
'w-model'
);

    
modelDOMs[i].value=
this
.data[bindModel]||
''
;

    
//数据劫持

    
this
.defineObj(
this
.data,bindModel);

    
if
(document.addEventListener){

        
modelDOMs[i].addEventListener(
'keyup'
,
function
(event) {

            
console.log(
'test'
);

            
e=event||window.event;

            
_that.data[bindModel]=e.target.value;

        
},
false
);

    
}
else
{

        
modelDOMs[i].attachEvent(
'onkeyup'
,
function
(event){

            
e=event||window.event;

            
_that.data[bindModel]=e.target.value;  

        
},
false
);

    
}

  

}

⑤  使用Object.defineProperty,定义set和get方法,并在set方法中调用bindText方法。这是利用了一旦w-model的值在input中被改变,会自动执行set方法,所以只有在这个方法中调用更新w-text的方法即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
defineObj:
function
(obj,prop,value){

          
var
 
val=value||
''
;

          
var
 
_that=
this
;

          
try
{

            
Object.defineProperty(obj,prop,{

               
get:
function
(){

                
return
 
val;

               
},

               
set:
function
(newVal){

                
val=newVal;

                
_that.bindText();

               
}

            
})

          
}
catch
 
(err){

            
console.log(
'Browser not support!'
)

          

        
}

⑥使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
html:<br><h3>双向数据绑定demo</h3>

<div id=
"wrap"
>

    
<input type=
"text"
 
w-model=
'demo'
>

    
<h5 w-text=
'demo'
></h5>

</div><br>js:

    
<script src=
'../js/wue.js'
></script>

    
<script>

      
new
 
Wue({

        
el:
'#wrap'
,

        
data:{

            
demo:
'winty'

        
}

      
})

    
</script>

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: