angularjs

angularjs 数据双向绑定简洁源码实现

2017-04-18  本文已影响18人  盛佳人
hello.html
<html>
<head>
<title>我的第一个 HTML 页面</title>
</head>
<body>
    <input ng-model="name" />
    <span>{{name}}</span>
    <script type="text/javascript" src="hello.js"></script>
</body>
</html>

hello.js

var Scope = function( ) {
    this.$$watchers = [];   
};

Scope.prototype.$watch = function( watchExp, listener ) {
    this.$$watchers.push( {
        watchExp: watchExp,
        listener: listener || function() {}
    } );
};

Scope.prototype.$digest = function( ) {
    var dirty;
    do {
            dirty = false;

            for( var i = 0; i < this.$$watchers.length; i++ ) {
                var newValue = this.$$watchers[i].watchExp(),
                    oldValue = this.$$watchers[i].last;

                if( oldValue !== newValue ) {
                    this.$$watchers[i].listener(newValue, oldValue);

                    dirty = true;

                    this.$$watchers[i].last = newValue;
                }
            }
    } while(dirty);
};

//angularjs从这里开始
var $scope = new Scope();

//初始化的时候,我定义了一个name,我希望他显示在页面上
$scope.name = '简书';
//所以在页面上我写了一个<span>{{name}}</span>,<input ng-model="name"/>,我会找到{{name}},或者ng-model="name"等然后用$scope.name的值替换他们
var modelList1 = [];//ng-model
var modelList2 = [];//{{}}
var spanList = document.querySelectorAll('span');
for(var i =0;i<spanList.length;i++) {
    if(spanList[i].innerHTML === '{{name}}') {
        spanList[i].innerHTML = $scope.name;
        modelList2.push(spanList[i]);
        //console.log(spanList[i].innerHTML);
    }
}
//input
var inputList = document.querySelectorAll('input');
for(var i =0;i<inputList.length;i++) {
    
    if(inputList[i].attributes["ng-model"].value === 'name') {
        //初始化
        inputList[i].value = $scope.name;
        modelList1.push(inputList[i]);
        
        //ng-model绑定事件
        inputList[i].onkeyup = (function(i) {
            return function() {
                $scope.name =  inputList[i].value;//视图到模型
                $scope.$digest();//模型到视图
            }
        })(i);
        
        //加个$watch事件,并加入到$$watchers队列中
        $scope.$watch(function(){
            return $scope.name;
        }, (function(i) {
            return function( newValue, oldValue ) {
                //console.log('新值 ' + newValue);
                //console.log('旧值 ' + oldValue);
                //ng-model
                for(var j=0;j<modelList1.length;j++) {
                    modelList1[j].value = $scope.name;
                }
                //{{}}
                for(var j=0;j<modelList2.length;j++) {
                    modelList2[j].innerHTML = $scope.name;
                }
        }
        })(i) );
        
        
    }
}
//以上是初始化阶段,数据已经反应到视图上了,angularjs对应的应该是$compile+$rootScope+相关指令加事件和替换 进行编译然后渲染


//接下来是数据的双向绑定阶段
//我觉得应该是ng-model指令绑定的onkeydown起作用的,它起到监听赋值的操作。然后立即调用$digest()->$$watchers来实现模型到视图的数据变化


setTimeout(function(){
    updateScopeValue();
},3000);
var updateScopeValue = function updateScopeValue( ) {
    $scope.name = '我是自动三秒后变化的值';
    $scope.$digest();
};
上一篇下一篇

猜你喜欢

热点阅读