去天津玩了一趟

据说所有事情都早晚会变成回忆。所以为了让回忆有趣意一点,我来记述一下这两天去天津旅游的行程。

第一天早晨乘坐九点多的高铁一路顺利的到达天津。下车之后出错了站台,导致后来选错了酒店。

在酒店踌躇半天之后跑去看了张学良故居

以上是张学良故居的一角。

中午在金牌餐厅吃了八珍豆腐。这个菜很好吃


下午去听了人民公园里的西岸相声。我常来听,主要是为了发掘自己有多高明


晚上在听一居吃了天津老爆三


第二天逛了大悲禅院


中午吃了包子

Reload Express.js application on file save

When you start with Node.js and Express you are probably friends with
CTRL + S (Save file)

CMD + Tab (Mac, switch windows)

CTRL + C (Stop server/application in terminal)

UP ARROW then ENTER (Restart server/application)

However there are tools to do this for you, one is Nodemon, and you can install this globably with
npm install -g nodemon
For your standard Node.js app which you start with node server.js you change that call to nodemon server.js. Now, each time you make a change Nodemon will handle restarting the app … think of it frantically calling CTRL+C, UP ARROW & ENTER in the background for you.
For Express.js the setup is slightly different. From the terminal you would use something like this (Mac/Linux) npm start or DEBUG=myApp npm start to get your project up and running on http://localhost:3000. To use Nodemon here you need to edit your projects package.json file so it looks like this

  “scripts”:{

    // “start”: “node ./bin/www”

    “start”: “nodemon ./bin/www”

   }
Once that’s done, start your Express.js project the normal way and each time you make a change you can go straight to the browser and refresh the page.

Nodejs里的异步编程模型

三套机制

  • 事件发布/订阅模式。
  • Promise/Deferred模式。
  • 流程控制库。

事件发布/订阅模式的操作极其简单,示例代码如下:

// 订阅
emitter.on("event1", function (message) {
  console.log(message);
});
// 发布
emitter.emit('event1', "I am message!");

可以看到,订阅事件就是一个高阶函数的应用。事件发布/订阅模式可以实现一个事件与多个回调函数的关联,这些回调函数又称为事件侦听器。通过emit()发布事件后,消息会立即传递给当前事件的所有侦听器执行。侦听器可以很灵活地添加和删除,使得事件和具体处理逻辑之间可以很轻松地关联和解耦。

事件发布/订阅模式自身并无同步和异步调用的问题,但在Node中,emit()调用多半是伴随事件循环而异步触发的,所以我们说事件发布/订阅广泛应用于异步编程。

事件发布/订阅模式常常用来解耦业务逻辑,事件发布者无须关注订阅的侦听器如何实现业务逻辑,甚至不用关注有多少个侦听器存在,数据通过消息的方式可以很灵活地传递。在一些典型场景中,可以通过事件发布/订阅模式进行组件封装,将不变的部分封装在组件内部,将容易变化、需自定义的部分通过事件暴露给外部处理,这是一种典型的逻辑分离方式。在这种事件发布/订阅式组件中,事件的设计非常重要,因为它关乎外部调用组件时是否优雅,从某种角度来说事件的设计就是组件的接口设计。

从另一个角度来看,事件侦听器模式也是一种钩子(hook)机制,利用钩子导出内部数据或状态给外部的调用者。Node中的很多对象大多具有黑盒的特点,功能点较少,如果不通过事件钩子的形式,我们就无法获取对象在运行期间的中间值或内部状态。这种通过事件钩子的方式,可以使编程者不用关注组件是如何启动和执行的,只需关注在需要的事件点上即可。下面的HTTP请求是典型场景:

var options = {
  host: 'www.google.com',
  port: 80,
  path: '/upload',
  method: 'POST'
};
var req = http.request(options, function (res) {
  console.log('STATUS: ' + res.statusCode);
  console.log('HEADERS: ' + JSON.stringify(res.headers));
  res.setEncoding('utf8');
  res.on('data', function (chunk) {
    console.log('BODY: ' + chunk);
  });
  res.on('end', function () {
    // TODO
  });
});
req.on('error', function (e) {
  console.log('problem with request: ' + e.message);
});
// write data to request body
req.write('data\n');
req.write('data\n');
req.end();
  • 如果对一个事件添加了超过10个侦听器,将会得到一条警告。这一处设计与Node自身单线程运行有关,设计者认为侦听器太多可能导致内存泄漏,所以存在这样一条警告。调用 emitter.setMaxListeners(0);可以将这个限制去掉。另一方面,由于事件发布会引起一系列侦听器执行,如果事件相关的侦听器过多,可能存在过多占用CPU的情景。
  • 为了处理异常,EventEmitter对象对error事件进行了特殊对待。如果运行期间的错误触发了error事件,EventEmitter会检查是否有对error事件添加过侦听器。如果添加了,这个错误将会交由该侦听器处理,否则这个错误将会作为异常抛出。如果外部没有捕获这个异常,将会引起线程退出。一个健壮的EventEmitter实例应该对error事件做处理。

 

angularjs和WebApp(试着翻译)

2.0跟IE的关系

IE6和IE7无法特别稳定执行,因为custom tags 和 hashchange events无法使用

在IE8里面则需要手动定义自定义标签,并插入到DOM树上,比如(document.createElement(‘ng-pluralize’),document.createElement(‘ng-view’)

3.0数据绑定和作用域切换

事件绑定机制根据事件自动触发,触发之后进行数据检查,$scope本身提供了一个key/value存储的哈希表。输入事件(比如键盘被按键了,鼠标焦点之类)、浏览器事件(timeout一类)、服务唤起(比如$http一类的)都会导致脏数据检测。顺便有些情况下,比如地址栏被改变了,或者你希望直接改变那里面的数据,就得手动调用 $scope.$apply()。一般情况下不推荐这么做。

4.0 $rootScope对象之妙用

每个controller里面的scope都是rootscope的子类,然后跟rootscope其实有联系。

$scope extends $rootScope

看个例子

App.run([‘$rootScope’,function($rootScope) { //this will be available to all scope variables $rootScope.includeLibraries = true; //this method will be available to all scope variables as well $rootScope.include = function(libraries) { var scope = this; //attach each of the libraries directly to the scope variable for(var i=0;i<libraries.length;i++) { var key = libraries[i]; scope[key] = getLibrary(key); } return scope; }; }]);

controller实例里面可以解决的方式如下

App.controller(‘SomeCtrl’, [‘$scope’, function($scope) { if($scope.includeLibraries) { //the flag was set in the $rootScope object $scope = $scope.include([‘plugin1’, ‘library1’]); } }]);

5.$apply 和 $digest 和 $$phase

如果在angularjs中引入了第三方类库,你需要有个额外的功能监视数据的变化,比如第三方框架使用了某些动作改变页面数据,这时候需要调用 $scope.$apply(),这个动作意味着调用了$watch把所有的变量变化都监控了一下,本来这件事是系统后台调用的。

部分情况下这个动作可能会抛出异常,因为后台此时正在运行一个digest,为了避免这种情况的发生,需要使用一个全局对象 $scope.$$phase来判断当前是否有后台进行的数据更新操作。

于是为了稳妥起见我们可以自己使用 下面的安全更新操作

//when you add it to the $rootScope variable, then it’s accessible to all other $scope variables. $rootScope.$safeApply = function($scope, fn) { fn = fn || function() {}; if($scope.$$phase) { //don’t worry, the value gets set and AngularJS picks up on it… fn(); } else { //this will fire to tell angularjs to notice that a change has happened //if it is outside of it’s own behaviour… $scope.$apply(fn); } }; //and you can run it like so. $scope.some_value = ‘value…’; $scope.$safeApply($scope, function() { //this function is run once the apply process is running or has just finished });

下面有个例子,这里我们要修改location url所以使用下面的代码

//be sure to inject $scope and $location somewhere before this var changeLocation = function(url, force) { //this will mark the URL change $location.path(url); //use $location.path(url).replace() if you want to replace the location instead $scope = $scope || angular.element(document).scope(); if(force || !$scope.$$phase) { //this will kickstart angular if to notice the change $scope.$apply(); } };

6.0在services和controller中进行通信

如果现在有个用户动作需要影响几乎所有的controller和directive的话,那就需要使用$emit, $on and $broadcast

如果你现在有个需要所有controller都处理的事件,可以用broadcast来做

//get the topmost scope var $scope = angular.element(document).scope(); //logout event var logoutEvent = ‘logout’; var logoutArgs = [‘arg’]; $scope.$broadcast(logoutEvent, logoutArgs); //login event var logoutEvent = ‘logout’; var logoutArgs = [‘arg’]; $scope.$broadcast(logoutEvent, logoutArgs);

接下来在每个controller里面接收代码如下

// //in your controller

//

App.controller(‘Ctrl’, [‘$scope’, function($scope)

{ $scope.$on(‘logout’, function(args) { alert(‘bye bye’); });

$scope.$on(‘login’, function(args) { alert(‘hello there’); }); }]);

在directive里面

// //in your directive // App.directive(‘sessionStatus’, function() { return function($scope, element, attrs) { $scope.$on(‘login’, function() { element(‘html’, ‘You are logged in!’); }); $scope.$on(‘logout’, function() { element(‘html’, ‘You are logged out!’); }); }; });

如果在是字controller里面提交一个动作给全局,那么可以用$emit

App.controller(‘Ctrl’, [‘$scope’, function($scope) { $scope.onLogoutClick = function() { $scope.$emit(‘logout’); } }]); //upper $scopes will respond to this with the same $on method.

7.0 为router上的controller加上点附加处理功能

example of it:

//checkout the route code below first before reading this
App.controller('Ctrl', ['$scope', '$http', 'argument1', 'argument2', 'argument3',
                function($scope,   $http,   argument1,   argument2,   argument3) {
  alert(argument1); //someDependeny's value or toString method
  alert(argument2); //"some value"
  alert(argument3); //the response.data value returned from GET /path/to/some/url
}]);

//here's where the magic happens
App.config(['$routeProvider',function($routeProvider) {
  $routeProvider.when('/some/page/with/an/:id',{
    templateUrl: '/path/to/some/template.html',
    controller: Ctrl,
    resolve: {
      // this is a registered dependency and works the same
      // as a dependeny injection would within a controller
      argument1: 'someDependency', 

      //this is resolved instantly since there is nothing going on
      argument2: function() { return 'some value'; }, 

      argument3: function() {
        return $http.get('/path/to/some/url',function(response) {
          //this is what is returned as the value for argument3
          return response.data; 
        }
      }
    }
  });
}]);

When the application makes it’s way to the path /some/page/with/an/:id

这个动作实际上就是绕过router的动作,直接处理请求并发起请求绕过了。这算是一种补充数据的办法

当然,还可以直接改router对象

The $route variable can also be injected directly into the controller and this can be used to fetch information about the current route:

App.controller('Ctrl', ['$route', function($route) {
  $route.current.templateUrl; //the URL of the template
  $route.current.params; //same as $routeParams
  $route.current.controller; //the name of the controller (Ctrl)
}]);

继续

8.0自定义自己的services

your application.

App.factory('myHttp',['$http',function($http) {
  return function() {
    get : function(url, success, fail) {
      $http.get(url).success(function(response) {
        return response.data;
      }).error(fail);
    }
  };
}]);

//this service can now be called by doing...
$myHttp.get('/path', function(data) {
  alert(data);
});

Also, below is a description of how data is shared between services within the same model.

App.factory('myFoo',['$http',function($http) {
  //any variables defined in this area will be ACCESSIBLE
  //within the any of the other services which are defined
  //within the same module. So if a variable called foo...
  var foo = 'bar';
  //then foo can be accessed in another service. Be sure to
  //keep this in mind since it's hard to debug
  return foo;
}]);

App.factory('myBar',['$http',function($http) {
  var bar = 'bar2';
  return foo.toString() + bar; //this should return either bar2 or barbar2
}]);

You can also inject any of your own services into any other services when created; this is very useful for code reuse and testing.

这地方就是自己弄个一个services,封装了原来的http动作,然后加上了点自己的动作。

9.0 ngshow什么的改变css

The same effect can be created by using angular

<div class="session">
  <span class="admin" data-ng-show="isAdmin">Hello Adminspan>
  <span class="admin" data-ng-hide="isAdmin">Hello Userspan>
div>

Just be sure to set the binding value

$scope.isAdmin = true; //or false or whatever

This works, but when the page is still downloading (when first loaded) you may see both values at the same time so to get around this just use cloaking.

<div class="session ng-cloak">...div>

And define the CSS for it as well:

.ng-cloak {
  /* this will change to block when scope and angular is ready */
  display:none;
}

Oh! And one more thing. If you wish to set the isAdmin value directly into your HTML, then do the following using the data-ng-init:

<div class="session ng-cloak" data-ng-init="isAdmin=false;">
  <span class="admin" data-ng-show="isAdmin">Hello Adminspan>
  <span class="admin" data-ng-hide="isAdmin">Hello Userspan>
div>

The data-ng-init attribute is useful for pre-setting values

10.错误异常捕获

route is not recognized within your application.

$routeProvider.when('/404',{
  controller : ErrorCtrl
});
$routeProvider.otherwise({
  redirectTo : '/404'
});

then you can capture the event within your scope by doing the following:

App.run(['$rootScope','$location',function($rootScope, $location) {
  $rootScope.$on("$routeChangeError", function (event, current, previous, rejection) {
    //change this code to handle the error somehow
    $location.path('/404').replace();
  });
}]);

set a custom service to wrap all your AJAX calls then you can catch errors before they’re passed onto other parts of your application.

App.factory('myHttp',['$http','$location',function($http, $location) {
  var onEmpty = function() {
    window.location = '/404';
  };

  return function() {
    get : function(url, success, fail) {
      $http.get(url).success(function(response) {
        var data = response.data;
        if(!data) {
          onEmpty();
          return;
        }
        success();
      }).error(onEmpty);
    }
  };
}]);

Be sure to only use this method when you access resources and data that is required within your application (like JSON data for a specific view).

11 使用$index在循环中获取循环变量进度

To get access to the index of a loop in angular you can access it from the $index value directly.

<ol>
  <li data-ng-repeat="option in options">
    <h2>Option #{{ $index + 1 }}: {{ option.value }}h2>
  li>
ol>

Keep in mind that there are also other options available such as $first, $middle, and $last. All of these and more are covered within the

location对象的获取

angular可以处理location对象,专门用于保存本地链接地址的哈希值

To keep track of the URL when it changes, you will need to setup a polling event.

App.run(['$rootScope', '$location', function($rootScope, $location) {
  $rootScope.$watch(
    function() { return $location.path() },
    function(path) {
      //new path!
      alert(path);
    }
  );
}]);

Additionally you can set these events explicitly within your scope variable

App.run(['$rootScope', function($rootScope) {
  $rootScope.$on('$locationChangeStart', function(event, newUrl) {
    alert('new location');
  });
}]);

自定义filter

App.filter(‘my’, function() {
return function(data) {
return data;
};
});
You can use of these filters directly in your HTML:

<span class=”some-data”>{{ value | my }}<span>
Or you can also access these filters directly in your services and controllers via dependency injection.

App.factory(‘someService’, [‘$filter’, function($filter) {
return function(data) {
return $filter(‘my’)(data);
};
}]);

表单的处理

<form novalidate class=”simple-form”>
<ol class=”fields”>
<li>
<label for=”input-name”>Name:</label>
<input id=”input-name” type=”text” data-ng-model=”name” />
</li>
<li>
<label for=”input-email”>Email:</label>
<input id=”input-email” type=”email” data-ng-model=”email” />
</li>
</ol>
<button data-ng-click=”submit()”>Submit</button>
</form>

表单出来的时候是处理的双向绑定数据,数据提交需要自己处理

这是国家化代码的例子

Ideally you wouldn’t stick the english translations directly into your own webapge so you can switch this so that translations are looked up in a global translation lookup table.

You would have to define your own lookup since this is something angular doesn’t provide by itself.

var LOOKUP = {
‘messages.zero’ : ‘No have no messages in your inbox’,
‘messages.one’ : ‘You have one message in your inbox’,
‘messages.many’ : ‘You have %messagesCount% messages in your inbox’
}
var translate = function(key, args) {
var data = LOOKUP[key];
if(data) {
for(var key in args) {
var value = args[key];
key = ‘%’ + key + ‘%’;
data = data.replace(key,value);
}
return data;
}
return ”;
};

时间日期国际化的例子

<!– this shows up as Sep 9, 2012 –>
<span class=”string-date”>{{ site.curl_left }} ‘2012-09-01′ | date:’medium’ {{ site.curl_right }}</span>

<!– same thing but longer and using a variable –>
<span class=”string-date”>{{ site.curl_left }} someDateVariable | date:’fullDate’ {{ site.curl_right }}</span>

<!– and you can set your own –>
<span class=”string-date”>{{ site.curl_left }} anotherDateVariable | date:’EEEE, MMMM d,y’ {{ site.curl_right }}</span>
You can also access the date filter directly within your controllers and services with use of the $filter service.

var dateFilter = $filter(‘date’);
var mediumDateString = dateFilter(‘2012-09-01’, ‘medium’);
var fullDateString = dateFilter(someDateVariable, ‘fullDate’);
var anotherDateString = dateFilter(anotherDateVariable, ‘EEEE, MMMM d,y’);

 

 

angularjs概览(大概其的翻译)

angularjs是由谷歌提供的一套框架,这套框架以其灵活多变,组织结构清晰,便于测试等优势很快就为广大开发爱好者关注。框架本事基于MVC架构,(是的,和reactjs这种纯粹的view框架是完全一样的东西,其实和vuejs这种是一类的,但是实际上vuejs是根据这个来的说)。此框架主要用于在客户端开发富互联网应用。(这个称谓之前叫做富媒体应用,现在改名字了)

angularjs只是个前端框架,提供了数据绑定,数据模型验证,模板页,单页内路由导航的技术,一般使用ajax方法和后端进行通信,通信结构多数情况是是纯粹的json,有时候为了方便我们把后端做成只提供json的restful框架。

1.0 此篇文章包含那些内容

此篇文章包含angularjs入门的方方面面,我觉的特别好所以才试着根据它来扩展的。包括控制器和作用域(一般这两件事是入门概念),services, models, templates, directives, filters, modules and configurations

2.0 Web应用(不是Web网站)

这两者是完全不同的,Web应用的特点是基于MVC框架,用JavaScript编写业务逻辑,使用数据绑定和模板页来进行页面的呈现,以及用ajax从服务器拿到数据,一般这个数据载体是json。这套逻辑的特点是整个应用程序像是一个应用框架,而不是逻辑紧密的页面和数据呈现。您可以会议一下早些年那些黏糊糊的html和服务器端代码混写的时代,以及点击一个按钮就要全页刷新,每个前置页面都得在服务器端配置一个handle页面的时代,那玩意叫做Web网站。

这种web应用的最大优势就是可以把每个页面分离之后单独运行,以及可以不在浏览器内运行。只要有个桌面解析html和javascript的环境就行。实际上这一套框架在移动端可以使用phonegap或者cordova进行打包,或者在桌面端用http://electron.atom.io/ 来进行打包,实现跨平台应用,所以angularjs这种框架实际上应用场景很广泛。

3.0 工作方式是怎样的?

angularjs的工作核心就是把逻辑和表示层分离。客户端通过使用directives, filters, bindings and binding-specific operations.这些技术来实现表示层的样式和基本呈现方法,而 Controllers, Services and Models则被用于进行逻辑封装和数据呈现统一。以及这样做的最大好处就是服务器端不用生成任何HTML了。(几乎)

以及和所有的MVC架构差不多,angularjs也可以劫持地址栏的地址,把它们拆分成不同的入口,把每个入口用不同的controller来处理,这样就用完全的前端模块化方法来处理业务逻辑了。不需要后端参与,后端只负责提供数据服务了。

4.0下面我们开始了

<script type=“text/javascript” src=“/path/to/angular/angular.js”>script> <script type=“text/javascript” src=“/path/to/angular/angular-resource.js”>script>

一般来说我们使用bower来安装依赖包,我本来是CDN的倡导者,建议大家使用CDN来获取公共js,但是这些年,情况越来也不好,好多CDN居然敢在公共库里插广告….

5.0模块化入口

angularjs的模块化类似于其它变成语言的名字空间,在这上面加入了依赖注入和错误追踪。

模块化的语法如下,HTML页面里

<html data-ng-app=“YOUR_APP_NAME”>

JavaScript里面

var App = angular.module(‘YOUR_APP_NAME’, [‘ngResource’]);

模块名称要对应,这是程序入口,每个模块管理自己的作用域,以及错处理中错误代码的位置。

模块创建的第二个参数,也就是数据是一个依赖项,意思是该模块的创立依赖那些第三方模块(其实哪儿有那么些个第三方模块,一大半情况下都是使用angularjs自己的附加功能,比如常见的rescource这种http请求的高级版,或者router这种为单页应用设计的路由模块,以及还有animation这种我一直都知道但是没有艺术细胞也不知道怎么用的模块,angularjs在第一代的时候很像哥几个为了趁手一点弄个了小功能,后来不断加上插件,最后变成一个有点臃肿但是还能看的类库集合,你如果从一开头就关注它,那么就可以很容易的理解为什么会忽然多出一些看起来奇怪的模块,因为那些都是功能上的新特性。但是angularjs2就完全不一样了,一开头就开始弄的特正规,以至于写个hello world都要搞半天。这事咱们以后再聊。)

模块创立之后,所有的工作组件,比如routes, models, filters and directives都依赖于它。

顺便,模块不能重名这种小事您应该知道吧….

6.0数据绑定和表达式(这就是angularjs一开始就让人觉的很赞的魔法)

绑定动作和表达式的目标就是把数据从js里放到HTML中,应该说避免了HTML和后端代码的混编,但是把HTML和JavaScript混编在一起了。很多架构觉的这样不优雅,比如reactjs就觉的干嘛这么讨厌,直接用JavaScript生成表示层元素类实例,接着渲染一下不就好了,这样想用html渲染就用html渲染,想用原生平台渲染,比如ios或者android上用原生渲染就原生渲染直接出原生应用。

我无意评价那种更好,只能说,看情况吧。

angularjs的表达式里能做这些数据的渲染和绑定操作。data binding, two-way data binding, conditionals, for in and foreach loops, model binding and so on.

举个例子:

<div class=“records” data-ng-repeat=“record in records | orderBy:orderProp”> <h5> {{ record.title }} h5> div>

这里的records在一个叫做$scope的作用域下面,关于作用域,你可以理解为每个controller都单独封装的一个变量空间,以及作用域对象还有一个全局的,在模块下面,每个模块单的有一个,用来管理那些通用的内容,但是(敲黑板)我们一般建议大家在不要使用全局对象,而是把要全局弄的工作封装到services中,给大家提供服务。这件事儿后面再聊。

针对上面的例子的数据是长这样的

$scope.records = [ { title : ‘one’ }, { title : ‘two’ }, { title : ‘three’ } ];

所以你能看出来,这里顺序显示了三条记录的中的title列,然后顺序是根据一个叫做orderprop的内容来做的,这个orderprop可能来自于某个文本控件或者自定义的filter,至于什么是filter,你可以理解为某个可以处理数据的对象,专门用来解决绑定数据的呈现问题,我们在后面会告诉你怎么写这个对象,顺便filter是跟着模块走的,属于每个模块自己的一个内建对象。

7.0依赖注入

这是angularjs执行的核心,前面的绑定的代码已经告诉大家可以通过在html中写一些符号加入JavaScript变量,然后浏览器运转的时候这些变量的值会被取出并送显,这件事能玩的转全靠依赖注入,它的工作方式就是监视html中那些你加入的标记,然后处理它们。

它可以处理你在angularjs中写到的几乎所有内容。controllers, module configuraitons, directives, filters, resources and routes

下面是一段依赖注入的代码

//the controller definition App.controller(‘Ctrl’, [‘$scope’, ‘$http’, ‘$location’, function($scope, $http, $location) { /* to change the URL after something has happened then you can use $location */ $location.path(‘/path/to/new/page’); }]);

依赖注入有什么好处呢,我看好处就是可以把代码彻底隔离,因为有了依赖注入,实际上每个angularjs中的代码都可以写作一般的工程,这样一来你就可以很方便的进行代码编写而不必关心UI了,进一步的你可以在完全没有UI的情况下测试angualrjs里的所有代码。我们后面也许会聊到mocha

这是一个用来做测试的框架,在写angularjs的时候我们通常使用它来进行代码的功能测试。

8.0路由功能

路由功能一方面处理用户的Http请求里的url把其中的一些部分拆分出来作为controller入口,另一部分作为参数传递给这个函数入口,目的通常是为了单页应用框架使用的。单页应用框架中是在一个物理页面中放多个webview,这么做多半是为了打包。无论是打包成为移动应用(phongap或者cordova),还是为了减少请求次数把网页打包(webpack),以及甚至打包作为一个桌面应用(electron),目前打包都特别流行。

router代码如下,以及router需要单独引入ngrouter模块

App.config([‘$routeProvider’, function($routes) { $route.when(‘/’,{ templateUrl : ‘/templates/home.html’, controller : HomeCtrl }); $route.when(‘/register’,{ templateUrl : ‘/templates/register.html’, controller : RegisterCtrl }); $routes.otherwise({ redirectTo : ‘/’ }); }]);

可以看出ngrouter模块直接依赖于主模块。

一般入口的router包含各个webviewe也就是不同的controller,然后每个controller的代码在单独的js里,里面一般都是针对这个webview里面提供的接受参数进行处理的代码,也就是说,每个controller里面也可能有单独的router对象。

9.0控件和作用域

代码如下

app.controller(‘SomeCtrl’, [‘$scope’, function($scope) { $scope.value = ‘some value’; }]);

作用域对象作为一个参数给控件。

然后作用域对象这么用。

<div class="header">{{ title }}div>
$scope.title = 'this is awesome';
<div class="header">this is awesomediv>

9.1 强制更新scope

部分情况下可能angularjs没有办法意识到变量已经发生变化了,于是我们需要用apply来告知它。

//lets say you have

{{ someVar }}

inside your HTML.

$scope.someVar = ‘value’; //if a scope digestion is already going on then it will get picked up and you won’t //have to call the $scope.$apply() method if(!$scope.$$phase) { //this is used to prevent an overlap of scope digestion $scope.$apply(); //this will kickstart angular to recognize the change }

9.2 rootscope

如果你打算跨过controller的分野,直接在所有作用域共享内容(一般是计数变量或者方法,不过我们一般建议方法还是用services)您可以这么干。

App.run([‘$rootScope’, function($rootScope) { $rootScope.sharedFunction = function() { … }; }]);

9.3 controller的使用

在HTML中声明一个

<div data-ng-controller=“SomeCtrl”>div>

在router中声明一个

$routes.when(‘/some/path’,{ controller: ‘SomeCtrl’, templateUrl: ‘/templates/controller.html’ });

10 services(总算说到这个了)

这个东西就是公用方法,在不同地方都可以使用到的方法

定义以及在各个地方使用的例子如下

//define the service

App.factory(‘myService’, [‘myOtherService’, ‘$location’, function(myOtherService, $location) { return function(input) { //do something with the input using the myOtherService or the $location objects. return input; }; }]);

//use the service within the controller

App.controller(‘HomeCtrl’, [‘$scope’, ‘myService’, function($scope, myService) { var input = ‘123’; input = myService(input); }]);

//use the service a directive

App.directive(‘myDirective’, [‘myService’,function(myService) { return { link: function($scope, element, attrs) { var input = ‘123’; input = myService(input); } } }]);

11.模型

模型基本上和其它应用架构的差不多,就是提供服务用的

下面是个例子

App.factory(‘ModelName’, [‘$resource’, function($resource) { $resource.url(‘/path/to/model/controller/:id’,

{ id : ‘@id’, //this binds the ID of the model to the URL param },

{ query : { method : ‘GET’, isArray : true }, //this can also be called index or all save :

{ method : ‘PUT’ }, //this is the update method create :

{ method : ‘POST’ }, destroy :

{ method : ‘DELETE’ } } }]);

调用也很简单

App.controller(“ShomeCtrl”, [‘ModelName’, ‘$scope’, function(ModelName, $scope) { //now you can use ModelName to do your business }]);

定义之后就可以在controller作用域里随便用了,就和本地操作一样了。

//list all the records on the page var results = ModelName.query({ search : ‘all’ }, onSuccessFn, onFailureFn); //get a specific record /* onSuccessFn and onFailureFn are optional callback functions where you can further customize the response */ var record = ModelName.get({ id : 123 }, onSuccessFn, onFailureFn); //create a new ModelName record var record = new ModelName(); //update that record record.someAttr = ‘someValue’; record.$save(); //or if you prefer to submit your data in a different way ModelName.save({ id : record.id },{ somePostObject : { attr1 : ‘value’, attr2 : ‘value2’ } }); //destroy the record (and include a token) record.destroy({ token : record.token });

下面来个完整点的例子(官方向导里面的)

先定义模块

angular.module('core.phone', ['ngResource']);
接着实现模块
angular.
  module('core.phone').
  factory('Phone', ['$resource',
    function($resource) {
      return $resource('phones/:phoneId.json', {}, {
        query: {
          method: 'GET',
          params: {phoneId: 'phones'},
          isArray: true
        }
      });
    }
  ]);

再封装一把
angular.module('core', ['core.phone']);
调用者
angular.module('phoneList', ['core.phone']);
调用者组件
angular.
  module('phoneList').
  component('phoneList', {
    templateUrl: 'phone-list/phone-list.template.html',
    controller: ['Phone',
      function PhoneListController(Phone) {
        this.phones = Phone.query();
        this.orderProp = 'age';
      }
    ]
  });
这里面
this.phones = Phone.query();
就是调用模块服务,加载了json文件。

12.0 directives

这东西主要用来封装代码和复用代码使用的。一般来说就是在当前HTML作用域里创建一个新的,可复用的作用域代码,然后复用和隔离。

angular.directive(‘myDirective’,function($compile) { return { //(optional) the contents of this template can be // downloaded and constructed into the element templateUrl : ‘/path/to/some/template.html’, //whether or not to replace the inner //data within the element replace : true, //this is where your magic happens link : [‘$scope’, function($scope) { $scope.title = ‘…’; }] }; });

顺便一提,这里的scope是可以和包含它的controller共享的,当然也可以隔离,也可以指定从里面可以访问外面等等,具体可以参考ppt。总之这个东西是用来共享变量的。

13.0 filters

这是一个可复用的方法用于在绑定的时候对输出数据进行过滤

App.filter(‘myUppercase’, function(data) {

for(var i=0; i < data.length; i++) {

data[i].title = data[i].title.toUpperCase(); }

return data; });

在HTML中使用很方便

<div data-ng-repeat=“for record in records | filter:myUppercase”></div>

直接用也很方便

var values = [‘one’,‘two’,‘three’]; values = $filter(‘myUppercase’)(values);

14.HTML5的API介入

App.config([‘$locationProvider’, function($location) { $location.html5Mode(true); //now there won’t be a hashbang within URLs for browers that support HTML5 history }]);

后面几个我觉的也就那意思,以及第二篇也很好。

https://www.yearofmoo.com/2012/10/more-angularjs-magic-to-supercharge-your-webapp.html

 

 

2015年终总结

我决定对自己坦诚,坦诚的意思就是记录下来自己每一年的情况,并尽量诚实的面对面对自己的内心。

在过去的2015年里。我经历了以下几件大事。

  1. 2014年底我和老婆去海南玩的时候还不知道老婆已经怀孕,还游了泳,然后我还傻了吧唧和她一起做了换乘飞机才回来,老婆真是坚强,飞回来以后发现怀孕了。于是这一年主要工作就是围绕着孩子的到来。
  2. 2014年单位的工作依然没什么太大变化,领导从上到下换了很多次,很多人更换了工作岗位和位置,我的工作职责和汇报关系没有本质变化,薪酬也保持在一个稳定的状态,我对此表示满意
  3. 外面的事儿越来越多,除了老客户还有新客户,除了老朋友还有新朋友,应该说取得这个进步是来之不易的,保持这个状态是可喜的。
  4. 学校的授课内容逐渐淡出,保留研究生导师工作,大概会在一两年后也淡出,毕竟不是学霸,也该了解自己擅长的领域和工作,能有这么一段经历已经很好了。
  5. 锻炼身体,准备迎接新的更大的挑战。
  6. 保持乐观积极的心态,让自己在面对困难的时候不发愁,不退缩。
  7. 和宝宝一起健康快乐的成长。或者至少能陪伴她健康快乐的成长。
  8. 感谢太太,感谢岳父母,感谢父母,感谢一切帮过忙的亲戚,没你们,这一年我怕是不能过来了。
  9. 明年是本命年了,没有太多展望,只能说一切按部就班水到渠成就好。