Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the common mistakes made by AngularJS developers

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly introduces the common mistakes made by AngularJS developers, which can be used for reference. I hope you can learn a lot after reading this article. Let's take a look at it.

Introduction

AngularJS is one of the JS frameworks nowadays, and one of its goals is to simplify the development process, which makes it very suitable for the development of apps with smaller meta-form, but also extends to the development of client applications with all the characteristics. Easy to develop, more features and better results lead to more applications, accompanied by some traps. This article lists some common ease and problems with AngularJS, especially when developing an app.

1. MVC directory structure

AngularJS is a MVC framework that lacks a good term. Its models is not defined as a framework as in backbone.js, but its structural patterns still match well. When working in a MVC framework, grouping files together based on file type is a common requirement:

Templates/ _ login.html _ feed.html app/ app.js controllers/ LoginController.js FeedController.js directives/ FeedEntryDirective.js services/ LoginService.js FeedService.js filters/ CapatalizeFilter.js

This layout, especially for those with a Rails background, seems reasonable. But as app gets bigger and bigger, this layout causes a bunch of folders to open every time. Whether you are using Sublime, Visual Studio, or Vim with Nerd Tree, spend a lot of time scrolling through the directory tree to find files.

If we group files according to the functional module to which each file belongs, rather than according to the layer to which it belongs:

App/ app.js Feed/ _ feed.html FeedController.js FeedEntryDirective.js FeedService.js Login/ _ login.html LoginController.js LoginService.js Shared/ CapatalizeFilter.js

Then it is much easier to find the files of a functional module, which can naturally improve the speed of development. Maybe not everyone can agree with mixing html files with js files. But at least it saves valuable time.

2. Module grouping

It is common practice to show all the submodules in the main module from the beginning. But it's okay to start a small app, but it's not easy to manage when it gets bigger.

Var app = angular.module ('app', []); app.service (' MyService', function () {/ / service code}); app.controller ('MyCtrl', function ($scope, MyService) {/ / controller code})

A better approach is to group similar types of submodules:

Var services = angular.module ('services', []); services.service (' MyService', function () {/ / service code}); var controllers = angular.module ('controllers', [' services']); controllers.controller ('MyCtrl', function ($scope, MyService) {/ / controller code}); var app = angular.module (' app', ['controllers',' services'])

The effect of this method is similar to that of the above method, but not very much. Using the idea of grouping will make the job easier.

Var sharedServicesModule = angular.module ('sharedServices', []); sharedServices.service (' NetworkService', function ($http) {}); var loginModule = angular.module ('login', [' sharedServices']); loginModule.service ('loginService', function (NetworkService) {}); loginModule.controller (' loginCtrl', function ($scope, loginService) {}); var app = angular.module ('app', [' sharedServices', 'login'])

When creating a large application, all modules may not be placed on one page, but grouping modules by type will make them more reusable.

3 dependency injection

Dependency injection is one of the best patterns in AngularJS. It makes testing more convenient and makes the objects it depends on clearer. AngularJS is very flexible for injection. One of the easiest ways is to pass the dependent name into the function for the module:

Var app = angular.module ('app', []); app.controller (' MainCtrl', function ($scope, $timeout) {$timeout (function () {console.log ($scope);}, 1000);})

Here, it is clear that MainCtrl depends on $scope and $timeout.

Until you are ready to go into production and compress your code. With UglifyJS, the above example would be:

Var app=angular.module ("app", []); app.controller ("MainCtrl", function (eMagol t) {t (function () {console.log (e)}, 1e3)}))

How does AngularJS know what MainCtrl depends on now? AngularJS provides a very simple solution: pass dependencies as an array of strings, and an element of the array is a function that takes all dependencies as parameters.

App.controller ('MainCtrl', [' $scope','$timeout', function ($scope, $timeout) {$timeout (function () {console.log ($scope);}, 1000);}])

Next, in the compressed code, AngularJS can also know how to find dependencies:

App.controller ("MainCtrl", ["$scope", "$timeout", function (console.log t) {t (function () {console.log (e)}, 1e3)}]) 3.1 Global dependencies

Usually when writing an AngularJS application, there is an object bound to the global scope as a dependency. This means that it is available in any AngularJS code, but it breaks the dependency injection model and creates some problems, especially in testing.

AngularJS encapsulates these global variables in modules so that they can be injected like standard AngularJS modules.

Underscore.js is a great library that simplifies Javascript code to functional mode, and it can be converted into a module:

Var underscore = angular.module ('underscore', []); underscore.factory (' _', function () {return window._; / / Underscore must already be loaded on the page}); var app = angular.module ('app', [' underscore']); app.controller ('MainCtrl', [' $scope','_', function ($scope, _) {init = function () {_ .keys ($scope) } init ();}])

It allows applications to continue to use the style of AngularJS dependency injection and allows underscore to be swapped out during testing.

This may seem unimportant, like an unimportant job, but it becomes necessary if your code is using use strict.

4 controller expansion

The controller is meat and tomato in AngularJS application. It's simple, especially at the beginning, when you put too much logic in the controller. The controller should not do any DOM operations or have DOM selectors, which should be done by using ngModel instructions (directives). Similarly, the business logic should be in the service (services), not the controller.

The data should also be stored in the service (services) unless it is already associated with $scope. Services is the individual that remains in the whole application life cycle, and the controller is transient in all stages of application. If the data is stored in the controller, it needs to be fetched from somewhere else when it is re-instantiated. Even if the data is stored in localStorage, getting the data is several orders of magnitude slower than getting it from the Javascript variable.

AngularJS works in compliance with the simple responsibility principle (SRP). If the controller is the coordinator of the view and model, then the logic it has should be minimized. This will make testing easier.

5 the difference between Service and Factory

Almost every developer who is new to AngularJS will be confused about these two things. Although they (almost) achieve the same effect, they are really not grammatical sugars.

Here are their definitions in the AngularJS source code:

Function factory (name, factoryFn) {return provider (name, {$get: factoryFn});} function service (name, constructor) {return factory (name, ['$injector', function ($injector) {return $injector.instantiate (constructor);}]);}

From the source code, it is obvious that the service function only calls the factory function, and then the factory function calls the provider function. In fact, value, constant, and decorator are also wrappers of provider provided by AngularJS, but there is no such confusion about their usage scenarios, and the documentation is very clear.

So does Service simply call the factory function once? The focus is on $injector.instantiate; in this function, service receives a constructor object that is de-instantiated by $injector using the new keyword. (original: with in this function $injector creates a new instance of the service's constructor function.)

Here is a service and a factory that perform the same function.

Var app = angular.module ('app', []); app.service (' helloWorldService', function () {this.hello = function () {return "Hello World";};}); app.factory ('helloWorldFactory', function () {return {hello: function () {return "Hello World";})

When either helloWorldService or helloWorldFactory is injected into controller, they have a return string "Hello World" with the name of the hello method. The constructor of this service is instantiated only once on declaration, and various references are made to each other each time the factory object is injected, but the factory is instantiated only once. All providers are singleton.

Since they all perform the same function, why do these two formats exist? Factory is slightly more flexible than service because they can return functions using the new keyword (original: Factories offer slightly more flexibility than services because they can return functions which can then be new'd). Elsewhere, in terms of the factory pattern of object-oriented programming. A factory can be an object used to create other objects.

App.factory ('helloFactory', function () {return function (name) {this.name = name; this.hello = function () {return "Hello" + this.name;})

Here is an example of a controller that uses the service and two factory mentioned earlier. Note that helloFactory returns a function, and the value of the variable name is set when the object uses the new keyword.

App.controller ('helloCtrl', function ($scope, helloWorldService, helloWorldFactory, helloFactory) {init = function () {helloWorldService.hello (); / /' Hello World' helloWorldFactory.hello (); / / 'Hello World' new helloFactory (' Readers'). Hello () / / 'Hello Readers'} init ();})

Only use services at the beginning of the game.

Factory is more suitable when you are designing a class that requires private methods:

App.factory ('privateFactory', function () {var privateFunc = function (name) {return name.split ("). Reverse (). Join ("); / / reverses the name}; return {hello: function (name) {return "Hello" + privateFunc (name);}};})

In this example, privateFactory contains a private privateFunc function that cannot be accessed externally. Services can also be used in this way, but the structure of the Factory code is clearer.

6 will not use Batarang

Batarang is an excellent plug-in for chrome browsers for developing and debugging AngularJS applications.

Batarang provides model browsing to see which models within Angular have been bound to the scopes. Can be used for values that need to be viewed at run time for isolated scope (isolate scopes) bindings in instructions.

Batarang also provides dependency diagrams. For introducing an untested code base, this tool can quickly determine which services should get more attention.

* Batarang provides performance analysis. Although AngularJS is high-performance out of the box, with the growth of the application of custom instructions and complex business logic, sometimes the page is not smooth enough. Using Batarang's performance analysis tool, you can easily see which functions takes up more time in the digest cycle. The tool can also display the entire monitor tree (full watch tree), which is useful when there are too many watch on the page.

7 too many watchers

As mentioned above, external AngularJS is good. Because dirty checks are required in a cycle digestion, there will be obvious problems with the loop once the number of watcher exceeds 2100.000. (2000 is only a reference number. AngularJS has more stringent control over cyclic digestion in version 1.3.There is a more detailed description of this Aaron Graye.)

This IIFE (quick response function) outputs the current number of watcher on this page, and you can simply copy it to console to see the details. The source of IIFE is similar to Jared's answer about StackOverflow.

(function () {var root = $(document.getElementsByTagName ('body')); var watchers = []; var f = function (element) {if (element.data (). HasOwnProperty (' $scope')) {angular.forEach (element.data (). $scope.$$watchers, function (watcher) {watchers.push (watcher);}) } angular.forEach (element.children (), function (childElement) {f ($(childElement));});}; f (root); console.log (watchers.length);} ()

Using this, you can determine the number of watcher and watch tree in terms of Batarang efficiency, and you can see where there is a watch for data that has not changed or where it has not changed.

When there is no change in data, but you want it to be a template in Angular, consider using bindonce.Bindonce as an instruction in Angular that may use templates without increasing the number of watch.

8 Review $scope

Javascript's prototype-based inheritance and class-based inheritance are different in some subtle ways. Usually this is not a problem, but the difference often occurs when using $scope. Every $scope in AngularJS inherits from its parent $scope, and the * layer is $rootScope. ($scope behaves differently in instructions where the isolation scope inherits only those properties that are explicitly declared. )

Sharing data from the parent is not important for prototype inheritance. However, if you are not careful, it will obscure the properties of the parent $scope.

We want to present a user name on the navigation bar and enter the login form.

{{user}} {{user}}

Test you: when the user enters a value in the text box with ngModel set, which template will be updated? Is it navCtrl,loginCtrl or both?

If you choose loginCtrl, then you may have a better understanding of the mechanism of prototype inheritance. When looking for a literal value, the prototype chain is not involved. If the navCtrl is to be updated, it is necessary to find the prototype chain. This happens when a value is used as an object. (remember that in Javascript, function and number combination objects are counted as objects.)

So to get the desired effect, you need to create an object on navCtrl that can be referenced by loginCtrl.

{{user.name}} {{user.name}}

Now that user is an object, the prototype chain will be taken into account, and the template for navCtrl and $scope will be updated with loginCtrl.

This may seem like a well-designed example, but problems arise when it comes to creating a child $scope like ngRepeat.

9 manual testing

While test-driven development may not be the preferred way for every developer, every time developers check to see if their code works or starts smashing things, they are doing manual testing.

There is no reason not to test an AngularJS application. AngularJS was designed to be easy to test from the start. Dependency injection and ngMock modules are evidence of this. The core team developed some tools to take testing to another level.

9.1 Protractor

Unit testing is the basic element of a set of test sets, but with the increase of application complexity, integration testing will lead to more practical problems. Fortunately, the AngularJS core team provided the necessary tools.

"We have built Protractor, an end-to-end test run tool that simulates user interaction and helps you verify the health of your Angular application."

Protractor uses the Jasmine test framework to define tests. Protractor provides a robust set of API for different page interactions.

There are other end-to-end tools, but Protractor has its own advantages. It knows how to run with AngularJS code, especially when faced with the $digest loop.

9.2 Karma

Once the integration test is written using Protractor, the test needs to be run. Waiting for tests to run, especially integration tests, can be frustrating for developers. The AngularJS core team also felt the pain and developed Karma.

Karma is a Javascript test run tool that can help you turn off feedback loops. Karma can run tests when specific files are modified, or it can test in parallel on different browsers. Different devices can point to the Karma server to override the actual scenario.

Use of 10 jQuery

JQuery is a very good class library. It standardizes cross-platform development. It plays a very important role in modern web page development. Although jQuery has many powerful functions. But his design philosophy is very different from that of AngularJS.

AngularJS is used to develop application frameworks; jQuery is a class library used to simplify HTML document object traversal and manipulation, event handling, animation and Ajax. This is the essential difference between the two. AngularJS focuses on the architecture of the application, not just to supplement the functionality of HTML pages.

As described in the document, AngularJS allows you to further extend HTML according to the needs of your application. Therefore, if you want to gain an in-depth understanding of AngularJS application development, you should no longer hold jQuery's thigh. JQuery will only limit the programmer's way of thinking to existing HTML standards.

The DOM operation should appear in the instruction, but that doesn't mean you have to use the jQuery wrapper set. Before using jQuery, consider that some features are already provided by AngularJS. Instructions are based on each other and can create useful tools.

One day it will be necessary to use the jQuery library, but it was a mistake to introduce it in the first place.

Thank you for reading this article carefully. I hope the article "what are the common mistakes made by AngularJS developers" shared by the editor will be helpful to you? at the same time, I also hope you can support us and pay attention to the industry information channel. More related knowledge is waiting for you to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report