Home  >  Article  >  Web Front-end  >  Thoughts after first getting to know the angular framework_AngularJS

Thoughts after first getting to know the angular framework_AngularJS

WBOY
WBOYOriginal
2016-05-16 15:14:521054browse

Because of the actual development needs at work, I started to come into contact with the angular framework. From the initial comparison, tortured and devastated by various problems and concepts, now I have a certain understanding and feel the need to briefly summarize my understanding. Please forgive me for any shortcomings.

1. Two-way data binding
Various MV** frameworks are currently popular in the industry, and related frameworks are constantly emerging, and angular is one of them (MVVM). In fact, the core issue of the MV** framework is to separate the view layer from the model, reduce the coupling of the code, and achieve the separation of data and performance. MVC, MVP, and MVVM all have the same goals, but the differences between them It lies in how to associate the model layer with the view.

How data flows in the model and view layers has become the key to the problem. Angular implements two-way binding of data through dirty-check. The so-called two-way binding means that changes in the view can be reflected in the model layer, and changes in model data can be reflected in the view. So how does Angular achieve two-way binding? Why does it become dirty-check? Let’s start with an original question on the front end:

html:

 <input type="button" value="increase 1" id="J-increase" />
 <span id="J-count"></span>

js:

 <script>
 var bindDate = {
  count: 1,
  appy: function () {
   document.querySelector('#J-count').innerHTML = this.count;
  },
  increase: function () {
   var _this = this;
   document.querySelector('#J-increase').addEventListener('click', function () {
    _this.count++;
    appy();
   }, true);
  },
  initialize: function () {
    // 初始化
   this.appy();
    //
   this.increase();
   }
  };
  bindDate.initialize();
 </script>

In the above example, there are two processes:

The view layer affects the model layer: Clicking the button on the page causes the number of data counts to increase by 1
The model layer reflects the view layer: After the count changes, it is reflected on the view layer through the apply function
This is data processing that was previously implemented using libraries such as jquery and YUI. The problems here are obvious:

  • Involves a lot of DOM operations;
  • The process is cumbersome;
  • The code coupling is too high, making it difficult to write unit tests.

Let’s take a look at how angular processes data:

The first step. Add a watcher: when the data changes, which objects need to be detected need to be registered first

// 对angular里面的源码进行了精简 
 $watch: function(watchExp, listener, objectEquality) {
  var scope = this,
   array = scope.$$watchers,
  watcher = {
    fn: listener,
    last: initWatchVal,
   get: get,
   exp: watchExp,
    eq: !!objectEquality
  };
  if (!array) {
   array = scope.$$watchers = [];
 }
  array.unshift(watcher);
 }

The second step. dirty-check: when the data under a certain scope changes, you need to traverse and detect the registered $$watchers = [...]

 $digest: function() {
 while (length--) {
   watch = watchers[length];
  watch.fn(value, lastValue, scope);
 }
 }

This achieves two-way binding of data. Is the above implementation similar to a custom event? You can see that the observer design pattern or (publisher-subscriber) is used.

2. Dependency injection
Students who have used the spring framework know that Ioc and AOP are the two most important concepts in spring, and Ioc can be used to inject dependencies (DI). It is obvious that angular has a very strong back-end color.

Similarly, let’s first look at how to solve object interdependence without using DI:

 function Car() {
 ...
}
 Car.prototype = {
 run: function () {...}
}
 
function Benz() {
 var cat = new Car();
 }
Benz.prototype = {
  ...
}


In the above example, class Benz depends on class Car, and this dependency is solved directly through internal New. The disadvantages of this are very obvious. The code coupling becomes higher, which is not conducive to maintenance. The back-end framework has been aware of this problem for a long time. In the early days, spring registered the dependencies between objects in xml files. Later, it solved the DI problem more conveniently through anotation. Students on the COS side can take a look at the back-end code.

The js language itself does not have an annotation mechanism, so how does angular implement it?

1. Simulation annotations

 // 注解的模拟
 function annotate(fn, strictDi, name) {
 var $inject;
 if (!($inject = fn.$inject)) {
  $inject = [];
  $inject.push(name);
 }else if (isArray(fn)) {
  $inject = fn.slice(0, last);
 }
  return $inject;
 }
 createInjector.$$annotate = annotate;

2. Creation of injection object

 function createInjector(modulesToLoad, strictDi) {
  //通过singleton模式创建对象
  var providerCache = {
    $provide: {
      provider: supportObject(provider),
      factory: supportObject(factory),
      service: supportObject(service),
      value: supportObject(value),
      constant: supportObject(constant),
     decorator: decorator
   }
   },
  instanceCache = {},
  instanceInjector = (instanceCache.$injector =
  createInternalInjector(instanceCache, function(serviceName, caller) {
  var provider = providerInjector.get(serviceName + providerSuffix, caller);
     return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
    }));
 return instanceInjector;
 }


3. Get the injection object

function invoke(fn, self, locals, serviceName) {
 var args = [],
  $inject = annotate(fn, strictDi, serviceName);

 for (...) {
  key = $inject[i];
   // 替换成依赖的对象
   args.push(
   locals && locals.hasOwnProperty(key)
     &#63; locals[key]
    : getService(key, serviceName)
   );
 }
  if (isArray(fn)) {
  fn = fn[length];
  }   
  return fn.apply(self, args);
}

At this point, have you seen a lot of back-end framework design ideas? Just simulate one without anotation. No wonder PPK says that angular is "a front-end framework by non-front-enders for non-front-enders"

3.controller communication
In actual development, the application system will be very large. It is impossible for an application app to have only one controller, so there is the possibility of communication between different controllers. There are two main ways to solve this common problem:

1. Event mechanism: Register events on $rootScope. The problem with this is that too many events will be registered on $rootScope, which will cause a series of subsequent problems

 //controller1
app.controller('controller1', function ($rootScope) {
 $rootScope.$on('eventType', function (arg) {
    ......
  })
 })

// controller2
app.controller('controller2', function ($rootScope) {
   $rootScope.$emit('eventType',arg);
 or
  $rootScope.$broadcast('eventType',arg);
 })

2. Make full use of the DI features of angular through service: and use the feature that service is a singleton to act as a bridge between different controllers

// 注册service
app.service('Message', function () {
 return {
  count: void(0);
 }
 })
 // controller1,修改service的count值
app.controller('controller1', function ($scope, Message) {
  $scope.count = 1;
 Message.count = $scope.count;
});
 // controller2, 获取service的count值
app.controller('controller2', function ($scope, Message) {
$scope.num = Message.count;
 });

4.Features of service

1. Singleton: Only service in angular can perform DI such as controller and directive. Neither controller nor directive have these functions. Service literally provides some basic functions. The service is not related to the specific business, while the controller and directive are closely related to the specific business, so the uniqueness of the service needs to be ensured.

2. lazy new: angular will first generate the provider of the service, but does not immediately generate the corresponding service. It will only instantiate these services when they are needed. .

3. Provider) classification: provider(), factory, service, value, constant, where provider is the lowest implementation, and other methods are based on it Syntactic sugar (sugar), it should be noted that these services will eventually add the $get method, because the specific service is generated by executing the $get method.

5. Implementation of directive
The compilation of directive includes two stages: compile and link. To put it simply, the compile phase mainly deals with the template DOM. At this time, the scope issue is not involved, that is, no data rendering is performed. For example, the ngRepeate instruction modifies the template through compile. After executing compile, the link function will be returned, overwriting the link defined later. function; link is mainly used for data rendering, which is divided into two links: pre-link and post-link. The order of parsing of these two links is reverse. Post-link parses the internal part first, and then the external part. This has a great impact on the directive. Parsing is safe because directives can also include directives. At the same time, links process the real DOM, which will involve performance issues in DOM operations.

The content covered in this article is not very universal, and there will be corresponding supplements later. I hope everyone can also learn and discuss the angular framework.

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn