angularJs scope的简单模拟

必要: JS MVC中, 模块间的数据不能相互影响, 只有这样才能有效的保证模块的复用性.

预期效果: angularJs很好的展现了这一点,它的效果类似于JS词法作用域:

  在一个函数中,内嵌函数可以访问外部函数的变量,而外部函数不能访问内部函数的变量 

思路: 1 给每个controller绑定一个scope对象,scope存该模块的属性

   2 如果controller有父controller,则为scope对象增加一个$parent属性指向父controller的scope对象

   3 增加一个代理函数, 把函数和方法绑定作用域

 

代码: 

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

<div ctrl="parent">
    父作用域:
    <input type="button" click="pfn()" value="自己的方法">
    <input type="button" click="cfn()" value="调用子方法">
    </hr>
    <div ctrl="child">
        子作用域:
        <input type="button" click="cfn()" value="自己的方法">
        <input type="button" click="pfn()" value="调用父方法">
    </div>
</div>

<script>
    var angular = (function(){
        var agl = {};
        agl.compile = function(){
            //初始化controller
            $("[ctrl]").each(function(){
                var ctrl = $(this).attr("ctrl");
                if(!window[ctrl])
                    throw new Error("不存在"+ctrl+"的函数");
                var scope = newScope(ctrl);
                //绑定函数
                $("[click]",this).each(function(){
                    var fname = $(this).attr("click").replace("(","").replace(")","");
                    $(this).unbind().click(execInScope(fname,scope));
                });
            });
        }
        
        function newScope(ctrl){
            var ctrlFn = window[ctrl];
            var scope = ctrlFn.$scope = {};
            //为scope对象增加属性
            ctrlFn(scope);
            inScopeChain(ctrl,scope);
            return scope;
        }

        //判断是否有parent,有则存入$parent属性中
        function inScopeChain(_self,scope,last){
            var p;
            if(last) p = last.parent();
            else     p = $('[ctrl='+_self+']').parent();
            if(p){
                var ps = p.attr("ctrl");
                if(ps){
                    scope.$parent = window[ps].$scope;
                    return;
                }
                //判断是否到达根节点
                if(p[0] != $("body")[0])
                    arguments.callee.call(null,_self,scope,p);
            }
            return;
        }

        //绑定作用域中的函数
        function execInScope(fname,scope){
            var fn = scope[fname];
            //如果本作用域没就到父作用域去找
            while(!fn && scope.$parent){
                fn = scope.$parent[fname];
            }
            if(fn)
                return fn;
            else
                return function(){alert("该作用域没有该方法");}
        }

        //dom加载完毕,开始编译
        window.onload = agl.compile;

        return agl;
    }())


    function parent($scope){
        $scope.pfn = function(){
            alert("父方法");
        }
    }
    
    function child($scope){
        $scope.cfn = function(){
            alert("子方法");
        }
    }
</script>

 

posted @ 2013-10-27 21:52  _SharpCode  阅读(1009)  评论(0编辑  收藏  举报