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>