怎样理解数据angular双向数据绑定绑定

js实现双向数据绑定 - 简书
js实现双向数据绑定
js双向绑定几种方法的介绍
几种实现双向绑定的做法
目前几种主流的mvc(vm)框架都实现了单向数据绑定,而我所理解的双向数据绑定无非就是在单向绑定的基础上给可输入元素(input、textare等)添加了change(input)事件,来动态修改model和 view,并没有多高深。所以无需太过介怀是实现的单向或双向绑定。
实现数据绑定的做法有大致如下几种:
发布者-订阅者模式(backbone.js)
脏值检查(angular.js)
数据劫持(vue.js)
发布者-订阅者模式: 一般通过sub, pub的方式实现数据和视图的绑定监听,更新数据方式通常做法是 vm.set('property', value)
,这里有篇文章讲的比较详细,有兴趣可点
这种方式现在毕竟太low了,我们更希望通过 vm.property = value
这种方式更新数据,同时自动更新视图,于是有了下面两种方式
脏值检查: angular.js 是通过脏值检测的方式比对数据是否有变更,来决定是否更新视图,最简单的方式就是通过 setInterval() 定时轮询检测数据变动,当然Google不会这么low,angular只有在指定的事件触发时进入脏值检测,大致如下:
DOM事件,譬如用户输入文本,点击按钮等。( ng-click )
XHR响应事件 ( $http )
浏览器Location变更事件 ( $location )
Timer事件( $timeout , $interval )
执行 $digest() 或 $apply()
数据劫持: vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
已经了解到vue是通过数据劫持的方式来做数据绑定的,其中最核心的方法便是通过Object.defineProperty()
来实现对属性的劫持,达到监听数据变动的目的,无疑这个方法是本文中最重要、最基础的内容之一,如果不熟悉defineProperty,猛戳整理了一下,要实现mvvm的双向绑定,就必须要实现以下几点:1、实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数3、实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图4、mvvm入口函数,整合以上三者
上述流程如图所示:
具体实现查看链接:
用原生js的defineProperty写一个双向数据绑定
var input = document.querySelector("#text");
var data = {};
Object.defineProperty(data, "name", {
configurable: true,
get: function(){
return input.value
set: function(newValue){
//this.value = newV
input.value = newV
data.name = "sss";
input.onchange = function(){
data.name = data.
但是当有两个输入框中的值想同时绑定user.name的时候怎么办呢?
&input type="text" id="text1" /&
&input type="text" id="text2" /&
var input1 = document.querySelector("#text1");
var input2 = document.querySelector("#text2");
var data = {};
Object.defineProperty(data, "name", {
configurable: true,
get: function(){
console.log(1111);
return input1.value
set: function(newValue){
console.log(222);
input1.value = newV
input2.value = newV
data.name = "sss";
input1.onchange = function(){
console.log(33333)
data.name = data.
input2.onchange = function(){
input1.value = this.
console.log(data);
当我改变input2的值的时候。input1的value会发生变化,这是必然的。但是这时候我打印data。data值竟然也更新了。input2.onchange里 并没有调用data的set啊。input1.value发生改变,也并没有触发input1的onchange啊。那 data的数据的更新,到底是怎么触发的啊?
我的github: vue双向绑定原理 MVC模式 以往的MVC模式是单向绑定,即Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新 MVVM模式 MVVM模式就是Model–View–ViewModel模式。它实现了View的...
今天是周五,今天一行代码也没有写,心血来潮想看看vue.js的实现原理和双向绑定MVVM。来吧BB那么多费话真没用,讲一点实现基础理论是必要的 我相信大家对Angular.JS的成为下一代最主流的MVC架构还记忆在心,但好景不长,angular2.0
实现数据绑定的三种方法 1.发布者-订阅者模式(backbone.js)2.脏值检查(angular.js)3.数据劫持(vue.js)所谓双向数据绑定,无非就是在单向绑定的基础上给输入元素(input、textare等)添加了change(input)事件,来动态修改mo...
在使用Vue.js自定义组件时,很多时候,我们都期望数据是双向绑定的。 Vue.js实现双向数据绑定的两种方式 1. v-model 调用组件时: 在组件内部,必须: 接受一个 value 属性 在有新的 value 时触发 input 事件 如: 2. props
本文整理于网络,原文链接 http://blog.poetries.top//front-end-interview-summary 目录 $HTML, HTTP,web综合问题 1、前端需要注意哪些SEO 2、 的title和alt有什么区别 3、HT...
文/一个苞谷 一、学业 16-25岁,正是读书的最关键的年龄段,却也是每一个女孩最美好的年华。女孩是感性动物,在遇到自己心仪的男生时,难免会晕头转向。我不反对女孩在这个年龄段恋爱,但反对女孩一头扎进去,对其他的人和事不管不顾,包括她自己。恋爱的维系要掌握一个度,半糖主义就不...
大成兄一早在群里召集去阿坝和青海,专门问我去不去。我掐指一算,没时间:“修行不够,俗务太多,抽不出身。”大成回复:“还有机会,路途不算远,但美。” 忽然想起那些对酒当歌的日子,忍不住感慨:“用你明亮的眼,为我们看风景,用你智慧的心,替我们悟人生……”大成曰:“用你美丽的文字...
加拿大健康协会上周推荐了这个杂志的健康栏目文章。这是北美最畅销的生活杂志之一,我翻译出来和大家分享: 10个方法改善您的消化系统 二十万加拿大人患有消化方面的问题。 “大多数人没有意识到,这些像腹胀、乏力、甚至皮疹症状都可能表明您的消化系统出现了问题。” 西瑞尼尔森这样说道...
作者:Lexi 知名国际学校专业从事教育工作8年+,多次被评为省、市级优秀教师;《有你真好》一书特约专栏供稿作者;青少年及亲子家庭关系进行心理辅导时间累积1000小时+;《亲密对话——HTC家庭版》版权课程中文版本联合开发人;《HTC——打破对话困境》,《亲密对话——HTC...
有人可以一份工作坚持很久,而也有些人是会时不时地更换工作。那在即将到来的2018年,我们的生肖属兔人适不适合跳槽呢? 从古到今,兔子在人们的眼里都是温文尔雅的象征来的,有不少人在看到一个活泼可爱的女孩后,往往都会用兔子相关的词汇来去形容。而不少属兔人看上去安静内敛,但实际也...关于javascript实现数据双向绑定的三种方法分享-js教程-PHP中文网QQ群微信公众号还没有收藏关于javascript实现数据双向绑定的三种方法分享本篇文章主要介绍了实现数据双向绑定的三种方式小结,前端的和数据层有时需要实现双向绑定,目前实现数据双向绑定主要有三种,有兴趣的可以了解一下。前端数据的双向绑定方法前端的视图层和数据层有时需要实现双向绑定(two-way-binding),例如mvvm框架,数据驱动视图,视图状态机等,研究了几个目前主流的数据双向绑定框架,总结了下。目前实现数据双向绑定主要有以下三种。1、手动绑定比较老的实现方式,有点像观察者模式,主要思路是通过在数据上定义get和set方法(当然还有其它方法),调用时手动调用get或set数据,改变数据后出发UI层的渲染操作;以视图驱动数据变化的场景主要应用与input、select、textarea等元素,当UI层变化时,通过监听dom的change,keypress,keyup等事件来出发事件改变数据层的数据。整个过程均通过函数调用完成。&!DOCTYPE html&
&html lang=&en&&
&meta charset=&UTF-8&&
&title&data-binding-method-set&/title&
&input q-value=&value& type=&text& id=&input&&
&p q-text=&value& id=&el&&&/p&
var elems = [document.getElementById('el'), document.getElementById('input')];
var data = {
value: 'hello!'
var command = {
text: function(str){
this.innerHTML =
value: function(str){
this.setAttribute('value', str);
var scan = function(){
* 扫描带指令的节点属性
for(var i = 0, len = elems. i & i++){
var elem = elems[i];
elem.command = [];
for(var j = 0, len1 = elem.attributes. j & len1; j++){
var attr = elem.attributes[j];
if(attr.nodeName.indexOf('q-') &= 0){
* 调用属性指令,这里可以使用数据改变检测
command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]);
elem.command.push(attr.nodeName.slice(2));
* 设置数据后扫描
function mvSet(key, value){
data[key] =
* 数据绑定监听
elems[1].addEventListener('keyup', function(e){
mvSet('value', e.target.value);
}, false);
* 改变数据更新视图
setTimeout(function(){
mvSet('value', 'fuck');
&/html&2、脏检查机制以典型的mvvm框架为代表,angular通过检查脏数据来进行UI层的操作更新。关于angular的脏检测,有几点需要了解些: - 脏检测机制并不是使用定时检测。 - 脏检测的时机是在数据发生变化时进行。 - angular对常用的dom事件,xhr事件等做了封装, 在里面触发进入angular的digest流程。 - 在digest流程里面, 会从rootscope开始遍历, 检查所有的watcher。 (关于angular的具体设计可以看其他文档,这里只讨论数据绑定),那我们看下脏检测该如何去做:主要是通过设置的数据来需找与该数据相关的所有元素,然后再比较数据变化,如果变化则进行指令操作&!DOCTYPE html&
&html lang=&en&&
&meta charset=&UTF-8&&
&title&data-binding-drity-check&/title&
&input q-event=&value& ng-bind=&value& type=&text& id=&input&&
&p q-event=&text& ng-bind=&value& id=&el&&&/p&
var elems = [document.getElementById('el'), document.getElementById('input')];
var data = {
value: 'hello!'
var command = {
text: function(str) {
this.innerHTML =
value: function(str) {
this.setAttribute('value', str);
var scan = function(elems) {
* 扫描带指令的节点属性
for (var i = 0, len = elems. i & i++) {
var elem = elems[i];
elem.command = {};
for (var j = 0, len1 = elem.attributes. j & len1; j++) {
var attr = elem.attributes[j];
if (attr.nodeName.indexOf('q-event') &= 0) {
* 调用属性指令
var dataKey = elem.getAttribute('ng-bind') ||
* 进行数据初始化
command[attr.nodeValue].call(elem, data[dataKey]);
elem.command[attr.nodeValue] = data[dataKey];
* 脏循环检测
* @param {[type]} elems [description]
* @return {[type]}
[description]
var digest = function(elems) {
* 扫描带指令的节点属性
for (var i = 0, len = elems. i & i++) {
var elem = elems[i];
for (var j = 0, len1 = elem.attributes. j & len1; j++) {
var attr = elem.attributes[j];
if (attr.nodeName.indexOf('q-event') &= 0) {
* 调用属性指令
var dataKey = elem.getAttribute('ng-bind') ||
* 进行脏数据检测,如果数据改变,则重新执行指令,否则跳过
if(elem.command[attr.nodeValue] !== data[dataKey]){
command[attr.nodeValue].call(elem, data[dataKey]);
elem.command[attr.nodeValue] = data[dataKey];
* 初始化数据
scan(elems);
* 可以理解为做数据劫持监听
function $digest(value){
var list = document.querySelectorAll('[ng-bind='+ value + ']');
digest(list);
* 输入框数据绑定监听
if(document.addEventListener){
elems[1].addEventListener('keyup', function(e) {
data.value = e.target.
$digest(e.target.getAttribute('ng-bind'));
}, false);
elems[1].attachEvent('onkeyup', function(e) {
data.value = e.target.
$digest(e.target.getAttribute('ng-bind'));
}, false);
setTimeout(function() {
data.value = 'fuck';
* 这里问啥还要执行$digest这里关键的是需要手动调用$digest方法来启动脏检测
$digest('value');
&/html&3、前端数据劫持(Hijacking)第三种方法则是avalon等框架使用的数据劫持方式。基本思路是使用Object.defineProperty对数据对象做属性get和set的监听,当有数据读取和赋值操作时则调用节点的指令,这样使用最通用的=等号赋值就可以了。具体实现如下:&!DOCTYPE html&
&html lang=&en&&
&meta charset=&UTF-8&&
&title&data-binding-hijacking&/title&
&input q-value=&value& type=&text& id=&input&&
&p q-text=&value& id=&el&&&/p&
var elems = [document.getElementById('el'), document.getElementById('input')];
var data = {
value: 'hello!'
var command = {
text: function(str) {
this.innerHTML =
value: function(str) {
this.setAttribute('value', str);
var scan = function() {
* 扫描带指令的节点属性
for (var i = 0, len = elems. i & i++) {
var elem = elems[i];
elem.command = [];
for (var j = 0, len1 = elem.attributes. j & len1; j++) {
var attr = elem.attributes[j];
if (attr.nodeName.indexOf('q-') &= 0) {
* 调用属性指令
command[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]);
elem.command.push(attr.nodeName.slice(2));
* 定义属性设置劫持
var defineGetAndSet = function(obj, propName) {
Object.defineProperty(obj, propName, {
get: function() {
set: function(newValue) {
bValue = newV
enumerable: true,
configurable: true
} catch (error) {
console.log(&browser not supported.&);
* 初始化数据
* 可以理解为做数据劫持监听
defineGetAndSet(data, 'value');
* 数据绑定监听
if(document.addEventListener){
elems[1].addEventListener('keyup', function(e) {
data.value = e.target.
}, false);
elems[1].attachEvent('onkeyup', function(e) {
data.value = e.target.
}, false);
setTimeout(function() {
data.value = 'fuck';
&/html&但值得注意的是defineProperty支持IE8以上的浏览器,这里可以使用defineGetter 和 defineSetter 来做兼容但是浏览器兼容性的原因,直接用defineProperty就可以了。至于IE8浏览器仍需要使用其它方法来做hack。如下代码可以对IE8进行hack,defineProperty支持IE8。例如使用es5-shim.js就可以了。(IE8以下浏览器忽略)4、小结首先这里的例子只是简单的实现,读者可以深入感受三种方式的异同点,复杂的框架也是通过这样的基本思路滚雪球滚大的。以上就是关于javascript实现数据双向绑定的三种方法分享的详细内容,更多请关注php中文网其它相关文章!共3篇737点赞收藏分享:.php.cn&猜你喜欢PHP中文网:独家原创,永久免费的在线,php技术学习阵地!
All Rights Reserved | 皖B2-QQ群:关注微信公众号一入前端深似海之如何实现一个双向数据绑定
#长按上图识别二维码,参与OSC源创会年终盛典#
众所周知,现在流行的一些MVVM框架,都有那么一个指令叫做双向数据绑定指令,其功能也是实现一个双向的数据绑定。所以今天我写下该篇博客,带着大家也实现一个属于自己的简易的数据双向绑定。
简单介绍一下双向数据绑定实现的是一个什么样的东西。首先有两个东西,他们分别是:
1、视图层传向数据层:V发生改变,M也发生改变
2、数据层传向视图层:M发生改变,V也发生改变
那么接下来我们也将自己书写代码实现这样两种功能,从而实现双向数据绑定。最终实现的效果如图:
修改input框里面的内容,p标签内容也实时相对应发生改变,data里面的数据也会发生改变
一、先奉献上自己完整的代码
这里我是基于jQuery进行的代码编写,其中的方法将在下面进行详细的解析
二、创建自己的绑定规则
这里关于指令,我没有做作用域的包裹,比较完善的是需要用一个controller指令讲需要展示的view视图层包裹起来的。如果有想法的小伙伴们可以在最后自行去思考,接下来先直接上html代码
这里我制定的双向指令是xq-model,内容的解析规则是{{}}。大家有自己喜欢的指令可以自行制定。
三、实现自己的绑定规则
我们现在需要做的就是一步一步去实现我们自己规定的一些绑定规则
首先我们需要做的第一步就是渲染出input中的xq-model指令指定的数据
实现inputChange方法
到这里,对于input框的渲染及data数据的双向算完成了第一个了,接下来我们需要实现的便是对于标签的渲染
实现labelChange方法
最后实现input框输入,实时修改对应的标签的值labelRender方法
最后我们调用一下实现好的VM
好了,属于我们自己的一个简单的双向数据绑定至此便算是完成了,大家也可以自己将这个进行不断的完善,自己去实现一个完整的双向数据绑定。
10 个习惯助你成为一名优秀的程序员
点击“阅读原文”查看更多精彩内容
责任编辑:
声明:本文由入驻搜狐号的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。
今日搜狐热点博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)双向绑定是新的前端框架中频繁出现的一个新词汇,也是mvvm的核心原理。angularjs五条核心信念中的数据驱动,便是由双向绑定进行完成。
那么什么是双向绑定,下面简单进行讲解。
首先我们要理解数据绑定。我们看到的网站页面中,是由数据和设计两部分组合而成。将设计转换成浏览器能理解的语言,便是html和css主要做的工作。而将数据显示在页面上,并且有一定的交互效果(比如点击等用户操作及对应的页面反应)则是js主要完成的工作。很多时候我们不可能每次更新数据便刷新页面(get请求),而是通过向后端请求相关数据,并通过无刷新加载的方式进行更新页面(post请求)。那么数据进行更新后,页面上相应的位置也能自动做出对应的修改,便是数据绑定。
在以前的开发模式中,这一步一般通过jq操作DOM结构,从而进行更新页面。但这样带来的是大量的代码和大量的操作。如果能在开始的时候,便已经确定好从后端获取的数据到页面上需要进行的操作,当数据发生改变,页面的相关内容也自动发生变化,这样便能极大地方便前端工程师的开发。在新的框架中(angualr,react,vue等),通过对数据的监视,发现变化便根据已经写好的规则进行修改页面,便实现了数据绑定。可以看出,数据绑定是M(model,数据)通过VM(model-view,数据与页面之间的变换规则)向V(view)的一个修改。
而双向绑定则是增加了一条反向的路。在用户操作页面(比如在Input中输入值)的时候,数据能及时发生变化,并且根据数据的变化,页面的另一处也做出对应的修改。有一个常见的例子就是淘宝中的购物车,在商品数量发生变化的时候,商品价格也能及时变化。这样便实现了V——M——VM——V的一个双向绑定。
具体的代码实现通常用到以下几个ng指令:
ng-model:将一个DOM节点的值与一个angular中的变量进行绑定,当DOM节点值发生修改的时候变量也会随之修改。
ng-bind:将angular中的变量显示到页面中。
{{}}:与ng-bind功能相同,区别在于页面未完全渲染完之前模板语言会直接显示在页面中,可通过在html标签中加上ng-cloak解决这一问题。
阅读(...) 评论()

我要回帖

更多关于 vue双向数据绑定 的文章

 

随机推荐