Better

Ethan的博客,欢迎访问交流

mini-angular的实现

本人和 angularjs 渊源很深,在 2015 年参加实习时,公司要求使用 angularjs,那时候是 angularjs 最火的时候,那时我就做了入门学习,在正式参加工作后,使用 ionic 开发混合 app,那时候对于对以移动端很感兴趣,就一头扎进 angularjs,对 angularjs 提供的能力,感觉很神奇,于是决定解开他的神秘面纱!

概括

旨在理解 angularjs 中的核心概念

  • 指令系统
  • 模块注册
  • 依赖注入
  • 双向绑定
  • 作用域分离
  • 脏检测机制

我们主要学习 DOMCompiler、Scope、Provider 对象。

Provider

主要任务有:

  • 提供注册 directive、controller、service 的方法
  • 提供 get 方法得到特定模块
  • 通过 _providers 对象保存注册的模块
  • 通过 _cache 对象保存模块的结果

DOMCompiler

看到这个对象,是让我最醒悟的地方,之前一直不解,为什么能识别我的指令,并且发挥他的作用。

  • bootstrap 方法:很简单,启动项目,调用 compile 函数扫描整个 dom
  • compile 方法
    • 扫描整个 dom 结构,如果节点的属性可以在 _privider 的指令部分找到,则说明这是我们定义的指令
    • 根据配置,判断是否需要创建子作用于,执行 link 函数

Scope

属性

  • $$watchers:监听数组
  • $$children:子元素
  • $parent:父元素
  • $id:唯一标识

函数

  • $new:新建 Scope,并继承当前 scope
  • $destroy:销毁当前 Scope
  • $watch:新增 $$watchers 数组元素,元素属性有
    • exp:被监测表达试
    • fn:发生改变待执行的函数
    • last:保存上一次的值,用于比较
  • $digest:脏检测核心
    • 默认 dirty 为 false,遍历 $$watchers 数组,比较 current 和 last 值,如果不同,设置 dirty 为 true,同时修改 last 值和执行函数 fn
    • 调用子作用域名 $$children 的 $digest 函数
  • $eval:执行,支持数组和字符串

常用指令

直接用代码说话吧

Provider.directive('ngl-bind', function () {
    return {
        scope: false,
        link: function (el, scope, exp) {
            el.innerHTML = scope.$eval(exp);
            scope.$watch(exp, function (val) {
                el.innerHTML = val;
            });
        }
    }
})

Provider.directive('ngl-model', function () {
    return {
        link: function (el, scope, exp) {
            el.onkeyup = function () {
                scope[exp] = el.value;
                scope.$digest();
            };
            scope.$watch(exp, function (val) {
                el.value = val;
            });
        }
    };
});

Provider.directive('ngl-controller', function () {
    return {
        scope: true,// 每个controller生成一个新的scope对象
        link: function (el, scope, exp) {
            var ctrl = Provider.get(exp + Provider.CONTROLLERS_SUFFIX);
            Provider.invoke(ctrl, { $scope: scope });
        }
    };
});

Provider.directive('ngl-click', function () {
    return {
        scope: false,
        link: function (el, scope, exp) {
            el.onclick = function () {
                scope.$eval(exp);
                scope.$digest();
            };
        }
    };
});

资料



留言