Angular 之 ngStrictDi_大V的博客-CSDN博客

mikel阅读(495)

来源: Angular 之 ngStrictDi_大V的博客-CSDN博客

ngStrictDi主要是讲angular依赖注入的写法问题,如果写法不规范,可能会在加载压缩版Angular的时候导致Unknown provider的错误。

  1. var app = angular.module(‘ngAppStrictDemo’, []);
  2. 1. 不规范写法
  3. app.controller(‘BadController’, function($scope) {
  4. $scope.a = 1;
  5. $scope.b = 2;
  6. });
  7. 2.规范写法
  8. //使用了详细的注释,数组形式注入
  9. app.controller(‘GoodController1’, [‘$scope’, function($scope) {
  10. $scope.a = 1;
  11. $scope.b = 2;
  12. }]);
  13. //直接使用$inject服务,注入
  14. app.controller(‘GoodController2’, GoodController2);
  15. function GoodController2($scope) {
  16. $scope.name = ‘World’;
  17. }
  18. GoodController2.$inject = [‘$scope’];

在1.6.x之后,依赖注入的书写越来越严格,这是为了避免压缩代码后产生的unknown provider问题。尤其是小编使用了webpack打包Angular项目之后,这个问题尤为突出。

如果依赖过多,显示或者解读代码不时,推荐大家使用规范写法的第二种。

Meteor+AngularJS:超快速Web开发 - 侯振宇 - 博客园

mikel阅读(672)

来源: Meteor+AngularJS:超快速Web开发 – 侯振宇 – 博客园

   为了更好地描述Meteor和AngularJS为什么值得一谈,我先从个人角度来回顾一下这三年来WEB开发的变化:
    三年前,我已经开始尝试前后端分离,后端使用php的轻量业务逻辑框架。但当时前端还没有成熟且广泛流行的业务逻辑框架。所以在做产品开发时我仍然选用drupal等整体开发框架。开发时常常需要在JavaScript和php间切换,同时还要自己搞定数据库。此时的开发模型图是这样(红色箭头和红色块都表示工作重灾区):
    随着对用户体验的追求,我开始把业务逻辑往前端推移,于是马上遇到了前端数据与页面展示绑定的问题,业务逻辑简单时还能用JQuery搞定。越来越复杂后,开始尝试使用backbone等前框架来规范数据层和做数据与视图的绑定,用requireJS做模块化和延迟加载。同时异步处理等编程模型也都开始进入实战。后端采用RESTful接口规范。此时的开发模型图是这样:
    一年前左右,接触到knockout和AngularJS,感受到数据和视图自动绑定的美妙开发体验后,立即抛弃Backbone。此时的开发已经彻底前后分离、前端业务数据层和视图层分离。接下来又开始陆续使用coffeescript 、jade、less进一步减少代码量。用grunt做自动编译、测试、和检测文件改动自动刷新浏览器。一切都已经比较完美了,除了后端仍然要对数据持久化做不少工作,除了前端要想实时反映数据改变仍然要轮询或者用webSocket连接服务器。这时的开发模型图已经是这样了:
    只差一点就完美了,Meteor就是这一点。Meteor是一个基于nodejs、webSocket、mongoDB的整体开发框架,在它的实现中,前后端的数据模型已经几乎没有差别。
    意思就是,前端对数据模型进行任何改动,只要调用“save”方法,所有数据就自动存到服务器端的mongoDB中了——终于可以忘了主动发送请求给服务器,终于可以忘了服务器要和前端实现几乎一样的数据模型层
    而任何前端“订阅的”后端数据出现改动,前端数据模型也会马上自动得到了更新——终于可以忘了主动轮询,终于可以忘了拿到后端数据再解析成前端模型。除了前后端模型的双向自动绑定,Meteor同时还实现了数据到前端模板的自动更新。
    不过,Meteor的模板在处理视图到模型的改动时扩展性不如AngularJS。因此,将AngularJS和meteor结合是最好的选择。到这里,快速Web开发模型终于完成:
    除了模型的自动绑定与更新,meteor还提供了大量进一步加速开发的机制。如:
  • 前后端载入文件文件的自动化管理。只要将相应的文件扔到前后端相应的目录中,就会自动载入到页面,或者在后端自动运行。
  • “智能包”管理。Meteor提供了模块的机制,让第三方开发者可以写“智能包”来加强前后端的功能。如,加载了“coffeescript”智能包后。无论前后端用coffeescript写的代码都会自动编译成JavaScript后再载入。
  • 内置大量“智能包”,有进一步支持开发的包,如“less”、“underscore”、“coffeescript”,还有通用业务逻辑包。如“账户管理”,而且已经集成主流oauth账号登陆。
  • 自动检测文件改动,自动刷新浏览器。
  • 自动化部署。
    以下马上来看一个实际开发的例子,制作一个为公司录入应聘人员信息的系统。
    需求:
  • 能指派面试官,自动邮件通知。
  • 支持google邮箱登陆。
  • 体验流畅、单页应用。
    开始写业务逻辑之前,我们先开始为准备一些开发工具和环境。首先,我要求能用coffescript代替javascript,less代替css。安装完meteor之后,进入项目木文件夹。在命令行中输入如下代码
    meteor create myapp
    meteor add less
    meteor add coffeescript
    然后,我想在前端使用JQuery,和meteor提供的账户系统来支持google oauth授权。继续输入:
    meteor add  jQuery
    meteor add  account-ui
    meteor add  account-google
    最后,将angularJS整合进来:在项目文件夹中创建如下目录层级:
client中的内容会全部自动加载到页面上,具体加载顺序请参考官方文档。server中的文件会在应用启动时自动运行。public中文件将作为静态资源供外部访问。
    因为AngularJS对数据模型改动的检测是通过“dirty check”的方式(见Angular官方文档)。所以要使用插件来让Meteor数据改动能通知到AngularJS,以此触发视图变化。这个插件就是上图中的angular.meteor。
    接下来说用AngularJS的ui-route模块来管理页面路由,将应用变成单页:
    加入“使用google账号”登录的功能:
    当新增一个应聘者时,给面试官发邮件:
    这里应该注意到的是,Meteor对于数据的操作完全是标准的MongoDB语法。剩下的业务逻辑用AngularJS的视图与模型很快就可以实现了,这里不再赘述。
    最后看看系统的效果截图,添加新的应聘人信息:
    面试结果记录:
    总结整个开发过程,可以都看到的是,几乎没有后端开发,只要前端完成,应用基本上就完成了。并且一步就可以使用coffeescript、less等,不再需要自己搭建复杂的开发环境。这样的开发体验,在目前来说,几乎已经到极致了。
    当然,要进入真正产品级开发,Meteor还有一些问题要克服,如“支持多种数据库”,“如何部署到集群”,“实时数据增加了服务器负载”等。好在Meteor目前收到的关注已经特别高,并且有了大量的第三方开发者,进入产品级开发的步伐越来越快。我们完全可以期待,这块拼图成熟之后,将给整个web开发新注入一股强大动力。

Angular $injector:unpr Unknown provider 问题原因汇总_大V的博客-CSDN博客

mikel阅读(528)

来源: Angular $injector:unpr Unknown provider 问题原因汇总_大V的博客-CSDN博客

Unknown provider: tProvider <- t 对于很多Angular 1.x 的使用者来说,是非常头疼的一件事情,因为使用者根本不知道原因在哪里。

本文总结了迄今为止所有导致这一个问题的可能原因,希望大家遇到此问题时,不要慌!跟着下面内容一步步排查:

问题描述:

Unknown provider 一般是由于无法解析注入的一个依赖所导致的。原因一般有如下这几种可能:

1. 依赖没有定义

  1. angular.module(‘myApp’, [])
  2. .controller(‘MyController’, [‘myService’, function (myService) {
  3. // Do something with myService
  4. }]);

上述代码,由于之前没有定义myService这个依赖,会报错 [$injector:unpr] Unknown provider。如果发现有没定义的依赖,首先要提前定义好这个依赖。

  1. angular.module(‘myApp’, [])
  2. .service(‘myService’, function () { /* … */ })
  3. .controller(‘MyController’, [‘myService’, function (myService) {
  4. // Do something with myService
  5. }]);

2. 重新使用了angular.module

  1. angular.module(‘myModule’, [])
  2. .service(‘myCoolService’, function () { /* … */ });
  3. angular.module(‘myModule’, [])
  4. // myModule has already been created! This is not what you want!
  5. .directive(‘myDirective’, [‘myCoolService’, function (myCoolService) {
  6. // This directive definition throws unknown provider, because myCoolService
  7. // has been destroyed.
  8. }]);

上述代码中,重复使用了angular.module(‘myModule’, []),会让angular重新定义myModule这个模块,导致报错。angular.module(‘myModule’, []) 这个语法一般是再次定义module,为了避免这个问题,在定义module之后直接使用angular.module(‘myModule’)或者使用一个变量代替之即可。

  1. angular.module(‘myModule’, []);
  2. .service(‘myCoolService’, function () { /* … */ });
  3. angular.module(‘myModule’)
  4. .directive(‘myDirective’, [‘myCoolService’, function (myCoolService) {
  5. // This directive definition does not throw unknown provider.
  6. }]);
  7. 或者
  8. var app = angular.module(‘myModule’, []);
  9. app.service(‘myCoolService’, function () { /* … */ });
  10. app.directive(‘myDirective’, [‘myCoolService’, function (myCoolService) {
  11. // This directive definition does not throw unknown provider.
  12. }]);

3. 把一个controller当依赖注入到另外一个controller中

  1. angular.module(‘myModule’, [])
  2. .controller(‘MyFirstController’, function() { /* … */ })
  3. .controller(‘MySecondController’, [‘MyFirstController’, function(MyFirstController) {
  4. // This controller throws an unknown provider error because
  5. // MyFirstController cannot be injected.
  6. }]);

其实如果要实例化controller,可以使用$controller服务(后续博客会更新)

4. 把$scope注入到不是controller或者directive的组件中

  1. angular.module(‘myModule’, [])
  2. .service(‘MyController’, [‘$scope’, function($scope) {
  3. // This controller throws an unknown provider error because
  4. // a scope object cannot be injected into a service.
  5. }]);

发生这个情况,也很好排查,只要牢记,只有controller和directive才能注入$scope作为依赖。

5. 使用angular压缩版导致报错

可以使用ngStrictDi

好了,希望本文能帮助到大家,遇此问题千万别慌了神!

MongoDB had an unspecified uncaught exception. 报错_异度社区

mikel阅读(508)

来源: MongoDB had an unspecified uncaught exception. 报错_异度社区

MongoDB had an unspecified uncaught exception. 报错

MongoDB had an unspecified uncaught exception.
This can be caused by MongoDB being unable to write to a local database.
Check that you have permissions to write to .meteor/local. MongoDB does
not support filesystems like NFS that do not allow file locking.

在启动前type:

export LC_ALL="en_US.UTF-8"

meteor报错之:MongoDB had an unspecified uncaught exception._weixin_30407613的博客-CSDN博客

mikel阅读(494)

来源: meteor报错之:MongoDB had an unspecified uncaught exception._weixin_30407613的博客-CSDN博客

今天测试的时候meteor报了个错

如下:

  1. MongoDB had an unspecified uncaught exception.
  2. This can be caused by MongoDB being unable to write to a local database.
  3. Check that you have permissions to write to .meteor/local. MongoDB does
  4. not support filesystems like NFS that do not allow file locking.

纠结了好久终于知道答案了,请确保你的硬盘有大于50G的预留空间,然后不要在内存小的磁盘分区里测试,要在内存充足的磁盘测试,(如果你报了这个错误,尝试换个磁盘去测试)

转载于:https://www.cnblogs.com/millent/p/5371322.html

Angular 源码解析系列 - 掘金

mikel阅读(1069)

来源: Angular 源码解析系列 – 掘金

加载应用依赖模块以及内置的ng模块等,就像之前说的类似这样:['ng', [$provide, function($provide){...}], 'xx']
执行每个模块的_runBlocks,可以理解injector创建完后模块的初始化(通过myModule.run(...)注册的)

  function loadModules(modulesToLoad){
    var runBlocks = [], moduleFn;

    // 循环加载每个module,
    // 1. 注册每个模块上挂载的service(也就是_invokeQueue)
    // 2. 执行每个模块的自身的回调(也就是_configBlocks)
    // 3. 通过递归搜集所有(依赖)模块的_runBlocks,并返回
    forEach(modulesToLoad, function(module) {

      // 判断模块是否已经加载过
      if (loadedModules.get(module)) return;

      // 设置模块已经加载过
      loadedModules.put(module, true);

      function runInvokeQueue(queue) {
        var i, ii;
        for(i = 0, ii = queue.length; i < ii; i++) {

          var invokeArgs = queue[i],
              provider = providerInjector.get(invokeArgs[0]);

          // 通过providerInjector获取指定服务(类),传递参数并执行指定方法
          provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
        }
      }

      // 模块可以是以下三种情况:
      // 1. 字符串表示模块名(注册过的模块),如:'ng'模块
      // 2. 普通函数(也可以是隐式声明依赖的函数),如:function($provider) {...}
      // 3. 数组(即声明依赖的函数)如:[$provide, function($provide){...}
      try {
        if (isString(module)) {
          // 获取通过模块名获取模块对象
          moduleFn = angularModule(module);
          // 通过递归加载所有依赖模块,并且获取所有依赖模块(包括自身)的_runBlocks
          runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
          // 遍历_invokeQueue数组依次执行$provider服务的指定方法(如:factory,value等)
          runInvokeQueue(moduleFn._invokeQueue);
          // 遍历_configBlocks数组依次执行$injector服务的invoke方法(即依赖注入并执行回调)
          runInvokeQueue(moduleFn._configBlocks);

        // 如果module是函数或者数组(可认为是匿名模块),那么依赖注入后直接执行
        // 并将返回值保存到runBlocks(可能是函数,又将继续执行)
        } else if (isFunction(module)) {
            runBlocks.push(providerInjector.invoke(module));
        } else if (isArray(module)) {
            runBlocks.push(providerInjector.invoke(module));
        } else {
          assertArgFn(module, 'module');
        }
      } catch (e) {
        if (isArray(module)) {
          module = module[module.length - 1];
        }
        if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
          e = e.message + '\n' + e.stack;
        }
        throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
                  module, e.stack || e.message || e);
      }
    });
    return runBlocks;
  }
复制代码

到这里在注册ng模块时的回调,在runInvokeQueue(moduleFn._configBlocks);已经执行过了,也就意味着许许多多的内置模块已经存入providerCache中了,所以在后面的依赖注入中我们可以随意调用。

最后

如果不对的地方,欢迎留言指正,新浪微博 – Lovesueee

作者:小鱼二
链接:https://juejin.im/post/6844903440217276423
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Angular系列学习笔记(一)—— 聊聊angular的模块化 - 简书

mikel阅读(606)

来源: Angular系列学习笔记(一)—— 聊聊angular的模块化 – 简书

前言

近来换工作了,由于团队技术需要,不得不从vue.js迁移到angular.js,不过这也是一个学习angular的机会,顺便也将这两个框架做一些对比,为了方便其他小伙伴,将学习过程中的内容记录下来。由开始的不太习惯到现在也能够习惯angular的写法,着实在思维上有很大的改变,所以这个系列的文章会记录一下自己的学习过程,本文会由浅及深一步步去解读vue.js和angular.js的区别。由于时间关系,这篇文章断断续续耗时几周,不求什么,只希望在这个过程中将angular相关的一些特性去梳理一下,由于是系列开篇,文章并没有深入探讨源码和原理,后续会写更多个人的思考和探索。

vuejs vs angular之初相见

对于vue.js我们都需要通过创建一个Vue实例指定作用范围,对于angular只需要ng-app指令就可以。

vue.js的姿势:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
<div id="app">
    {{ message }}
    <button v-on:click="changeView">changeView</button>
</div>
<script src="//cdn.bootcss.com/vue/2.1.10/vue.js"></script>
<script type="text/javascript">
    var app = new Vue({
        el: '#app',
        data: {
            message: 'Hello world!'
        },
        methods: {
            changeView: function(){
                this.message = 'hello vuejs!';
                // 或 app.$data.message = 'hello vuejs!'
            }
        }
    })
</script>
</body>
</html>

angular的姿势:

<!DOCTYPE html>
<html ng-app="app">
<head>
    <meta charset="utf-8">
</head>
<body>
    <div ng-controller="helloCtrl">
        {{message}}
        <button ng-click="changeView()">changeView</button>
    </div>
    <script src="//cdn.bootcss.com/angular.js/1.6.0/angular.js"></script>
    <script type="application/javascript">
        var app = angular.module('app', []);
        app.controller('helloCtrl', function ($scope) {
            $scope.message = 'hello world';
            $scope.changeView = function () {
                $scope.message = 'hello angular.js!';
            }
        })
    </script>
</body>
</html>

这个例子虽然再简单不过,对于项目开发没有半点用处,但是对于理解vue.js和angular.js的区别有一定的借鉴意义,vue.js中总体的思路是实例化Vue对象,我们通过el属性指定控制的dom范围,data是数据模型,可以通过实例化后的对象app.$data访问数据,在方法中或者生命周期钩子如mounted中可以使用this获取实例上下文,vuejs中没有控制器的概念,属于典型的MVVM架构。然而我们这篇文章不是讲vue.js,因为如果你使用vue.js,那么直接看文档很好理解,无需我多言,这里我们想重点说说angular。

经常听人说vue.js语法优雅,我想应该是由于vue.js结构更加清晰吧,数据模型和操作分得更清晰,就从命名出发更简单吧,$scope是什么鬼。好吧,查了一下:scope(范围),我们姑且先从字面含义这么理解吧,但是从这例子中发现$scope多次使用,另外不能被改名,不然不能用,我们姑且认为是个神奇的玩意。angular中ng-click的指令和vue.js无大的区别,这里不多言,这里重点想谈谈模块化和angular的依赖注入。

vuejs vs angular之数据模型共享

在vue.js中是通过组件树实现模块化的,而angular通过作用域$scope实现模块化。对于vue.js中模块化的最佳实践是:

** .vue单文件组件 + 模块化标准(common.js或者es6 module) + webpack(或Browserify)。**

而其中核心部分就是组件,用官方的话说就是,组件(Component)是 Vue.js 最强大的功能之一,组件可以扩展 HTML 元素,封装可重用的代码,在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能,在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。

如何构建一个组件,组件之前数据如何共享,这是开发中必须要学习的内容。vue.js组件实例的作用域是孤立的,这意味着不能并且不应该在子组件的模板内直接引用父组件的数据,可以使用 props 把数据传给子组件。另外vue.js中提倡单向数据流:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。当子组件需要更新父组件的状态时,我们可以通过事件触发。下面是一个利用props传递数据和使用事件触发父组件状态的典型例子:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <div id="app">
        {{ message }}
        <button v-on:click="parentAtion">parentAtion</button>
        <child v-bind:param="message"  v-on:childfn="fromChild"></child>
    </div>
    
    <script type="text/x-template" id="child-tpl">
        <div>
            <span>{{param}}</span>
            <button v-on:click="childAtion">childAtion</button>
        </div>
    </script>
    
    <script src="//cdn.bootcss.com/vue/2.1.10/vue.js"></script>
    <script type="text/javascript">
        Vue.component('child', {
            template: '#child-tpl',
            props: ['param'],
            methods: {
                childAtion: function(){
                    // 触发事件
                    this.$emit('childfn', 'child component');
                }
            }
        });
        
        var app = new Vue({
            el: '#app',
            data: {
                message: 'Hello vuejs!'
            },
            methods: {
                parentAtion: function(){
                    this.message = 'parent component';
                },
                fromChild: function(msg){
                    this.message = msg;
                }
            }
        })
    </script>
</body>
</html>

每个 Vue 实例都实现了事件接口(Events interface),即:

  • 使用 $on(eventName) 监听事件
  • 使用 $emit(eventName) 触发事件

Vue的事件系统分离自浏览器的EventTarget API。尽管它们的运行类似,但是$on和 $emit 不是addEventListener和 dispatchEvent的别名。

父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。对于非父子组件通信的通信,在简单的场景下,使用一个空的 Vue 实例作为中央事件总线:

var bus = new Vue()
// 触发组件 A 中的事件
bus.$emit('id-selected', 1)
// 在组件 B 创建的钩子中监听事件
bus.$on('id-selected', function (id) {
  // ...
})

在更多复杂的情况下,你应该考虑使用专门的状态管理

对于angular 而言,ng-controller指令指定了作用范围,通过$scope对象控制作用域,$scope层层嵌套形成父子关系或者兄弟并列关系,而父子作用域是通过原型继承实现,子作用域可以访问父作用域的数据模型,反过来不行,同理如果父级作用域中的状态改变会影响子作用域,反过来子作用域中的状态改变不会影响父级作用域。

<!DOCTYPE html>
<html ng-app="app">
<head>
    <meta charset="utf-8">
</head>
<body>
    <div ng-controller="parentCtrl">
        {{message}}
        <button ng-click="parentAtion()">parentAtion</button>
        <div ng-controller="childCtrl">
            {{message}}
            <button ng-click="childAtion()">childAtion</button>
        </div>
    </div>
    <script src="js/angular.min.js"></script>
    <script type="application/javascript">
        var app = angular.module('app', []);
        app.controller('parentCtrl', function ($scope) {
            $scope.message = 'hello angular';
            $scope.parentAtion = function () {
                $scope.message = 'parent scope';
            }
        })
        
        app.controller('childCtrl', function ($scope) {
            $scope.childAtion = function () {
                $scope.message = 'child scope';
            }
        })
    </script>
</body>
</html>

由于原型继承的关系,修改父级对象中的message会同时修改子对象中的值,但反之则不行。如果我们想在子级控制器中改变父对象中的值,则需要通过引用进行共享。

<!DOCTYPE html>
<html ng-app="app">
<head>
    <meta charset="utf-8">
</head>
<body>
    <div ng-controller="parentCtrl">
        {{dataModal.message}}
        <button ng-click="parentAtion()">parentAtion</button>
        <div ng-controller="childCtrl">
            {{dataModal.message}}
            <button ng-click="childAtion()">childAtion</button>
        </div>
    </div>
    <script src="js/angular.min.js"></script>
    <script type="application/javascript">
        var app = angular.module('app', []);
        app.controller('parentCtrl', function ($scope) {
            $scope.dataModal = {
                message: 'hello angular'
            }
            $scope.parentAtion = function () {
                $scope.dataModal.message = 'parent scope';
            }
        })
        
        app.controller('childCtrl', function ($scope) {
            $scope.childAtion = function () {
                $scope.dataModal.message = 'child scope';
            }
        })
    </script>
</body>
</html>

问题的本质在于字符串、数字和布尔型变量是值复制,数组、对象和函数则是引用复制,通过引用共享可以在子级作用域内部改变它会影响父级作用域的数据模型状态。

另外我们通过chrome的一个插件AngularJS Batarang可以很清晰的看出$scope对象的继承关系,会发现每个$scope对象都会有个$id,以及对于作用域$scope下的数据模型,如下:

AngularJS Batarang插件效果

需要说明的是ng-app对应的作用域是全局的,我们一般使用$rootScope对象表示,对应的$id等于1。

除了通过引用复制实现数据共享,我们也可以使用类似vue.js中的事件机制。

angular事件广播:

  • $broadcast:只能向child controller传递event与data
  • $emit:只能向parent controller传递event与data

$scope.$broadcast(name, data);
$scope.$emit(name, data);

angular事件监听:

  • $on:接收event与data

$scope.$on(eventName, function(event, data){
  // 这里写监听逻辑...
})

在$on的方法中的event事件参数,其对象的属性和方法如下:

事件属性 含义
event.targetScope 发出或者传播原始事件的作用域
event.currentScope 目前正在处理的事件的作用域
event.name 事件名称
event.stopPropagation() 一个防止事件进一步传播(冒泡/捕获)的函数(这只适用于使用$emit发出的事件)
event.preventDefault() 这个方法实际上不会做什么事,但是会设置defaultPrevented为true。直到事件监听器的实现者采取行动之前它才会检查defaultPrevented的值。
event.defaultPrevented 如果调用了preventDefault则为true

上述的例子可以改写为:

var app = angular.module('app', []);
app.controller('parentCtrl', function ($scope) {
    $scope.message = 'hello angular';
    $scope.parentAtion = function () {
        $scope.message = 'parent scope';
    }
    
    // 监听事件
    $scope.$on('sendMsg', function(event, data){    
        $scope.message = data;
    })
})

app.controller('childCtrl', function ($scope) {
    $scope.childAtion = function () {
        // 触发事件
        $scope.$emit('sendMsg', 'child scope');
    }
})

angular 依赖注入

前面我们对比了angular和vue对于数据模型共享的处理方式,发现两个框架在整体上大致相同,在细微上有所区别。对于一个大型模块化工程而言,除了需要处理数据模型数据流的问题,插件和依赖的处理同样也是实现模块化必不可少的一部分。我们如何将我们的应用分成一个个小模块,互不干扰高度自治,但是却又能够相互依赖。在vue中我们是通过构建工具例如webpack+模块化标准来实现,在angular中是通过依赖注入(Dependency Injection)实现的。

这里我们先来看一下知乎上的一个问题:AngularJS中的依赖注入实际应用场景?依赖注入是一个设计模式,遵循依赖倒转原则(Dependence Inversion Priciple, DIP)。关于依赖注入的实现原理后面再做深入探讨,我们先可以认为angular提供了一套机制可以很好的解决模块之间相互依赖的问题。

angular是用$provider对象来实现自动依赖注入机制,注入机制通过调用一个provide的$get()方法,把得到的对象作为参数进行相关调用。例如:

<div ng-controller="serveCtrl">
    {{message}}
</div>

<script type="application/javascript">
    var app = angular.module('app', []);    
    //  使用provider方法创建服务
    app.provider('dataServe',{  
        $get: function() {  
            return {  
                message:"dataServe Provide"  
            };  
        }  
    }); 
    
    app.controller('serveCtrl', function ($scope, dataServe) {
        // 调用服务
        $scope.message = dataServe.message;
    })
</script>

这里我们演示了angular中依赖注入的一个简单例子,在serveCtrl控制器中我们通过将dataServe作为函数参数名写入,就可以访问dataServe服务的内容,从而实现模块解耦。

上面是一种实现方法,但不是最佳实践,我们一步步说明其他写法。

首先我们需要知道在angular中声明和引用一个模块的方法:
声明模块的写法如下:

angular.module(name, [requires], [configFn]);

name:字符串类型,代表模块的名称;
requires:字符串的数组,代表该模块依赖的其他模块列表,如果不依赖其他模块,用空数组即可;
configFn:用来对该模块进行一些配置。

函数返回模块的引用

使用模块的方法:

angular.module(name)

上面创建服务,我们可以通过$provide服务实现:

angular.module('app', [], function($provide){
    $provide.provider('dataServe', function(){
        this.$get = function(){
            return {
                message:"dataServe Provide"  
            }
        }
    })
}).controller('serveCtrl', function ($scope, dataServe) {
    // 调用服务
    $scope.message = dataServe.message;
})var app = angular.module('app', []);
app.config(function($provide){
    $provide.provider('dataServe', function(){
        this.$get = function(){
            return {
                message:"dataServe Provide"  
            }
        }
    })
})
app.controller('serveCtrl', function ($scope, dataServe) {
    $scope.message = dataServe.message;
})

创建服务的几种常用方法

上述我们使用provider和$provide.provider两种不同的写法,但是都是需要写$get函数,为了简化创建服务的过程,angualr提供了其他的五种方法:

constant:定义常量,定义的值不能被改变,可以被注入到任何地方,但是不能被装饰器(decorator)装饰;

<div ng-controller="serveCtrl">
    {{message}}
</div>

<script type="application/javascript">
    var app = angular.module('app', []);
    app.config(function($provide) {
        $provide.constant('constantServe', 'constant serve');
    })
    app.controller('serveCtrl', function($scope, constantServe) {
        $scope.message = constantServe;
    }) 
</script>

语法糖:

app.constant('constantServe', 'constant serve');

value:可以是string,number甚至function,和constant的不同之处在于,它可以被修改,不能被注入到config中,可以被decorator装饰

<div ng-controller="serveCtrl">
    <button ng-click="showTips()">show tips</button>
</div>

<script type="application/javascript">
    var app = angular.module('app', []);    
    app.value('valueServe', function(){
        alert("哈哈");
    })
    app.controller('serveCtrl', function ($scope, valueServe) {
        $scope.showTips = valueServe;
    })
</script>

factory:factory为自定义工厂,是注册服务的最常规方式,它可返回任何对象,包括基本的数据类型。

<div ng-controller="serveCtrl">
    {{message}}
</div>

<script type="application/javascript">
    var app = angular.module('app', []);
    app.config(function($provide){
        $provide.factory('factoryServe', function(){
            return {
                message: 'factory serve'
            }
        })
    })
    app.controller('serveCtrl', function ($scope, factoryServe) {
        $scope.message = factoryServe.message
    })
</script>

语法糖:

app.factory('factoryServe', function(){
    return {
        message: 'factory serve'
    }
})

factory就是通过provider第二个参数为对象的方法实现,factory底层通过调用$provide.provider(name, {$get: $getFn}),而$getFn就是自定义factory的参数,即factory所传的方法需返回一个对象,这个对象会绑定到provider的$get属性上。

service:当使用service创建服务的时候,相当于使用new关键词进行了实例化。因此,你只需要在this上添加属性和方法,然后,服务就会自动的返回this。当把这个服务注入控制器的时候,控制器就可以访问在那个对象上的属性了。

<div ng-controller="serveCtrl">
    {{message}}
</div>

<script type="application/javascript">
    var app = angular.module('app', []);
    app.config(function($provide){
        $provide.service('serviceServe', function(){
            this.message = 'factory serve';
        })
    })
    app.controller('serveCtrl', function ($scope, serviceServe) {
        $scope.message = serviceServe.message
    })
</script>

语法糖:

app.service('serviceServe', function(){
    this.message = 'factory serve';
})

decorator:provider里面的装饰器——锦上添花神器

为什么使用decorator?
我们经常在使用某些Service的时候,更希望它能具备一些额外的功能,这时我们难道改这个Service吗?如果是系统自带的呢,改吗?这当然不现实吧。所以我们的装饰器decorator就发挥作用了,它能让已有的功能锦上添花。我们在config里面使用装饰器。

<div ng-controller="serveController">
    {{message}}
</div>

<script type="application/javascript">
    var app = angular.module("app", []);
    
    app.config(['$provide', function($provide) {
        $provide.decorator('infoService', function($delegate) {
            $delegate.email = "1028317108@qq.com";
            return $delegate;
        })
    }]);

    app.service('infoService', function() {
        this.name = 'zhaomenghuan';
    })

    app.controller('serveController', ['$scope', 'infoService', function($scope, infoService) {
        $scope.message = 'name:'+infoService.name + '<=>Emil:'+infoService.email;
    }]);
</script>

我们开始写的infoService没有Emil,我们通过装饰器decorator在不修改infoService代码的情况下添加了email新属性。

源码部分:

function provider(name, provider_) {
    if(isFunction(provider_)) {
        provider_ = providerInjector.instantiate(provider_);
    }
    if(!provider_.$get) {
        throw Error('Provider ' + name + ' must define $get factory method.');
    }
    return providerCache[name + providerSuffix] = provider_;
}

function factory(name, factoryFn) {
    return provider(name, { $get: factoryFn });
}

function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
        return $injector.instantiate(constructor);
    }]);
}

function value(name, value) { return factory(name, valueFn(value)); }

function constant(name, value) {
    providerCache[name] = value;
    instanceCache[name] = value;
}

function decorator(serviceName, decorFn) {
    var origProvider = providerInjector.get(serviceName + providerSuffix),
        orig$get = origProvider.$get;
    origProvider.$get = function() {
        var origInstance = instanceInjector.invoke(orig$get, origProvider);
        return instanceInjector.invoke(decorFn, null, { $delegate: origInstance });
    };
}

注意:所有的供应商都只被实例化一次,也就说他们都是单例的,除了constant,所有的供应商都可以被装饰器(decorator)装饰。模块的config方法只能注入 provider 和 constant;模块的run方法中可被注入的依赖包括服务(service)、值(value)和参量(constant),不能注入”provider”类型的依赖。

注入依赖的几种方法

通过数组标注在方法的参数中声明依赖(优先考虑)

app.controller('serveCtrl', ['$scope', 'factoryServe', function ($scope, factoryServe) {
    $scope.message = factoryServe.message;
}])

定义在控制器构造方法的$inject属性中

app.$inject = ['$scope', 'factoryServe']
app.controller('serveCtrl', function ($scope, factoryServe) {
    $scope.message = factoryServe.message;
})

隐式声明依赖

app.controller('serveCtrl', function ($scope, factoryServe) {
    $scope.message = factoryServe.message;
})

注入器可以从函数的参数名中推断所依赖的服务。上面的函数中声明了$scope和factoryServe服务作为依赖。 这种方式可是代码更加简洁,但这种方式不能和JavaScript的代码混淆器一起使用。可以通过ng-annotate在minifying之前隐式的添加依赖。

通过在ng-app所在的DOM元素中添加ng-strict-di切换到严格的依赖注入模式,strict模式下使用隐式的标注会报错,如果用angular.bootstrap手动启动angular应用,我们可以通过设置config中的strictDi属性,启动strict模式。

angular.bootstrap(document, ['myApp'], {
  strictDi: true
});

注入器($injector)

angular注入器($injector类似于spring容器)负责创建、查找注入依赖, 每个module都会有自己的注入器。注入器负责从我们通过$provide创建的服务中创建注入的实例。只要你编写了一个带有可注入性的参数,你都能看到注入器是如何运行的。每一个AngularJS应用都有唯一一个$injector,当应用启动的时候它被创造出来,你可以通过将$injector注入到任何可注入函数中来得到它($injector知道如何注入它自己!)。

一旦你拥有了$injector,你可以动过调用get函数来获得任何一个已经被定义过的服务的实例。例如:

<div ng-controller="serveController">
    {{message}}
</div>

<script type="application/javascript">
    var app = angular.module('app', []);
    
    app.factory('factoryServe', function(){
        return {
            message: 'factory serve'
        }
    })
    
    var injector = angular.injector(['app']);
    app.controller('serveController', ['$scope', function ($scope) {
        var factoryServe = injector.get('factoryServe');
        $scope.message = factoryServe.message;
    }])
</script>

这是因为Angular在编译模板阶段为ng-controller指令以及实例化serveController注入相关的依赖。

injector.instantiate(serveController);

总结

react,angular,vue这三大框架带给前端变化,远远不只是让我们放弃JQuery这种直接操作dom的方式,也不仅仅是解决数据绑定的问题,我想更多的是改变我们的思维方式,用数据驱动的方式去更新视图,通过划分组件或者作用域,来实现整体的颗粒化,实现模块间分治,同时也改变了前后端协作的工作模式。

参考

vue.js组件
AngularJS的学习–$on、$emit和$broadcast的使用
前端需要知道的 依赖注入(Dependency Injection, DI)
理解AngularJS中的依赖注入
AngularJs中的provide

作者:技术宅小青年
链接:https://www.jianshu.com/p/0fc26c75f089
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Git 克隆分支 - 简书

mikel阅读(696)

来源: Git 克隆分支 – 简书

  1. 首先,你需要使用$ git clone这个命令克隆一个本地库。

e:
cd ProxSpace/pm3
git clone https://github.com/iceman1001/proxmark3.git "iceman"

这将远端的proxmark3项目的master分支克隆到 E:\ProxSpace\pm3下的iceman文件夹,
注意要克隆的目录(比如这里的iceman)要先创建好,且里面不能有文件(必须是空目录)。

之后不会克隆任何一个分支下来的。

  1. 查看本地与远端分支情况: git branch -a
    假定你现在的命令行正处于已经在当前克隆好的文件夹中。

git branch -a
image.png

绿色代表本地已经有的分支。remotes是远端分支情况

  1. 假定你需要一个autoBuild(此处假定远程库中已经存在此分支,也就是你需要克隆的)分支用于开发的话,你需要在autoBuild分支上开发,就必须创建远程origin的autoBuild分支到本地,于是用checkout这个命令创建本地autoBuild分支(并不会在本地创建分支文件夹的,只是在本地建立了个和远端同步的分支):

$ git checkout -b autoBuild origin/autoBuild

再同步下:

$ git pull

不执行这步的话,新checkout的分支并不会同步内容下来,以后获取分支更新内容也是用这个命令.

image.png

这样就实现了克隆autoBuild分支。

再输入git branch -a 来看看分支情况:

image.png
  1. 切换分支:

git checkout autoBuild

这样就在本地切换到了autoBuild分支了。

作者:Thresh0ld
链接:https://www.jianshu.com/p/c261867cf49a
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

git 克隆指定分支代码_wudinaniya的博客-CSDN博客

mikel阅读(1863)

来源: git 克隆指定分支代码_wudinaniya的博客-CSDN博客

git拉取代码最常用的方式为:

git clone http://gitslab.yiqing.com/declare/about.git

这种方式没有指定分支,当代码有多个分支时,拉取的分支不一定就是master。比如,下面这个其实拉下来的就不是master分支代码:

  1. [root@izbp1845cet96se1qmb5ekz home]# git clone http://gitslab.yiqing.com/declare/about.git
  2. Cloning into ‘about’
  3. Username for ‘http://gitslab.yiqing.com’: account
  4. Password for ‘http://account@gitslab.yiqing.com’:
  5. remote: Counting objects: 116, done.
  6. remote: Compressing objects: 100% (86/86), done.
  7. remote: Total 116 (delta 45), reused 80 (delta 28)
  8. Receiving objects: 100% (116/116), 313.49 KiB | 508.00 KiB/s, done.
  9. Resolving deltas: 100% (45/45), done.
  10. [root@izbp1845cet96se1qmb5ekz home]# ls
  11. about
  12. [root@izbp1845cet96se1qmb5ekz home]# cd about/
  13. [root@izbp1845cet96se1qmb5ekz about]# git branch
  14. * develop

 

使用git拉代码时可以使用 -b 指定分支

指定拉 master 分支代码

git clone -b master http://gitslab.yiqing.com/declare/about.git

指定拉 develop 分支代码

git clone -b develop http://gitslab.yiqing.com/declare/about.git

 

查看当前项目拉的是哪个分支的代码:

进入项目根目录, 然后执行 git branch 命令

git branch

如图所示:

 

查看当前项目拉的是哪个分支的代码详情:

进入项目根目录, 然后执行 git branch -vv 命令

git branch -vv

如图:

查看分支上的递交情况:

进入项目根目录,执行 git show-branch

git show-branch

如图:

meteor下载太慢!3步教你搞定meteor下载和安装。_zhujuyu的博客-CSDN博客

mikel阅读(873)

来源: meteor下载太慢!3步教你搞定meteor下载和安装。_zhujuyu的博客-CSDN博客

操作系统:ubuntu 16.04 LTS

根据官网指导 https://www.meteor.com/install,下载meteor需要使用以下命令:

curl https://install.meteor.com/ | sh

但是这种下载速度实在太慢,难以忍受,于是撸起袖子自己干。

Step1:手动下载压缩包

https://d3sqy0vbqsdhku.cloudfront.net/packages-bootstrap/1.2.1/meteor-bootstrap-os.linux.x86_64.tar.gz

我直接用浏览器下载meteor的压缩包,速度明显快了,但依然用了20分钟左右。

Step2:更改脚本

我们将官网提供的脚本命令导出到本地保存为install.meteor.sh

curl https://install.meteor.com > install.meteor.sh

然后使用编辑器vim/nano/gedit打开 install.meteor.sh,找到TARBALL_URL所在位置:

TARBALL_URL=https://static-meteor.netdna-ssl.com/package……..

我们将其注释掉,改用我们的本地地址,这个本地地址一定要在浏览器中能够打开看到才行。网上有方法说上传到服务器再下载实在是画蛇添足。

TARBALL-URL=”file:///home/usr/Downloads/meteor-bootstrap-os.linux.x86_64.tar.gz”

保存文件并退出。

Step3:运行脚本

sh install.meteor.sh

秒成。

注意:一定要下载osx版本的安装包,我将安装包下载后上传到了百度云盘,

Linux要下再Linux版本