What are the differences between ng-if and ng-show/hide?
The first difference is that ng-if is created only when the expression after the dom node is true, ng-show is created at the beginning, and display:block and display:none are used to control display and not display.
The second difference is that ng-if will (implicitly) produce a new scope, and the same is true for ng-switch, ng-include, etc. to dynamically create an interface.
This will cause the ng-model to be bound with the basic variable in ng-if and bind this model to another display area in the outer div. When the inner layer changes, the outer layer will not change synchronously because there are already two variables.
<p>{{name}}</p><div ng-if="true"> <input type="text" ng-model="name"></div>ng-show does not have this problem because it does not come with its own first-level scope.
The way to avoid this kind of problem is to always bind elements in the page to the object's properties (data.x) instead of directly binding to the base variable (x).
See the scope in AngularJS for details
When ng-repeat iterates over an array, if there are the same values in the array, what problems will be there and how to solve them?
Duplicates in a repeater are not allowed. Adding track by $index can solve it. Of course, you can also trace by any ordinary value, as long as you can uniquely identify each item in the array (create the association between the dom and the data).
Can the expression written in ng-click use the methods on JS native objects?
Not only expressions in ng-click, but only native JS methods cannot be called directly as long as they are in the page, because these do not exist in the $scope of the controller corresponding to the page.
Take a chestnut:
<p>{{parseInt(55.66)}}<p>
You will find that nothing is displayed.
But if you add this function in $scope:
$scope.parseInt = function(x){ return parseInt(x);}Of course there is no problem like this.
For this kind of requirement, using a filter may be a good choice:
<p>{{13.14 | parseIntFilter}}</p>app.filter('parseIntFilter', function(){ return function(item){ return parseInt(item); }}){{now | 'yyyy-MM-dd'}} In this expression, how can vertical lines and subsequent parameters be customized?
filter, formats data, receives an input, processes it according to a certain rule, and returns the processing result.
Built-in filter
There are nine types of built-in filters:
date(date)
currency
limitTo (limits array or string length)
orderBy (sort)
lowercase (lowercase)
uppercase (caps)
number (format the number, add a thousand separator, and receive parameters to limit the number of decimal places)
filter (process an array and filter out elements containing a substring)
json (formatting json object)
There are two ways to use filter, one is to directly on the page:
<p>{{now | date : 'yyyy-MM-dd'}}</p>
Another one is to use it in js:
// $filter('filter name')(Objects that need to be filtered, parameter 1, parameter 2,...)
$filter('date')(now, 'yyyy-MM-dd hh:mm:ss');
Custom filter
// Form app.filter('filter name',function(){ return function(Object that needs to be filtered, filter parameter 1, filter parameter 2,...){ //... Do something to return the object after processing; }}); // Chestnut app.filter('timesFilter', function(){ return function(item, times){ var result = ''; for(var i = 0; i < times; i++){ result += item; } return result; }})What is the relationship between factory, service and provider?
factory
Put the service method and data in an object and return this object
app.factory('FooService', function(){ return { target: 'factory', sayHello: function(){ return 'hello ' + this.target; } }});service
Create a service through constructor method and return an instantiated object
app.service('FooService', function(){ var self = this; this.target = 'service'; this.sayHello = function(){ return 'hello ' + self.target; }});Provider
Create a service that can be configured through config. The returned in $get is to use factory to create the content of the service
app.provider('FooService', function(){ this.configData = 'init data'; this.setConfigData = function(data){ if(data){ this.configData = data; } } this.$get = function(){ var self = this; return { target: 'provider', sayHello: function(){ return self.configData + ' hello ' + this.target; } } } }});// What is injected here is FooService providerapp.config(function(FooServiceProvider){ FooServiceProvider.setConfigData('config data');});From the underlying implementation perspective, the service calls factory and returns its instance; the factory calls provider, returning the content defined in its $get. The factory and service function are similar, except that the factory is a normal function that can return anything (return can be accessed, so how to write those private variables, you know); the service is a constructor, which can not be returned (those bound to this can be accessed); the provider is an enhanced factory, which returns a configurable factory.
See AngularJS Factory vs Service vs Provider
What mechanism is used for data binding of angular? Detailed description of the principle
Dirty inspection mechanism.
Bidirectional data binding is one of the core mechanisms of AngularJS. When there is any data change in the view, it will be updated to the model. When there is any data change in the model, the view will also be updated simultaneously. Obviously, this requires a monitoring.
The principle is that Angular sets up a listening queue on the scope model to listen for data changes and update view. Every time an object is bound to the view, AngularJS will insert a $watch into the $watch queue to detect whether there are any changes in the model it monitors. When the browser receives an event that can be processed by angular context, the $digest loop will be triggered, traversing all $watches and finally updating the dom.
Give a chestnut
<button ng-click="val=val+1">increase 1</button>
When clicking, an update operation will be generated (at least two $digest loops are triggered)
Press the button
The browser receives an event and enters the angular context
The $digest loop starts to execute, querying whether each $watch changes
Since $watch monitoring $scope .val reported changes, a $digest loop is enforced
No changes detected in the new $digest loop
The browser takes back the controller and updates the dom corresponding to the new value of $scope.val
The upper limit of the $digest loop is 10 times (a exception is thrown after more than 10 times to prevent infinite loops).
See data binding for AngularJS
Two horizontal interface blocks a and b. If an event is triggered in a, what ways can b know? Detailed description of the principle
In other words, this problem is how to communicate between horizontal interface modules. There are two methods, one is to share services and the other is to be based on events.
Shared services
In Angular, a singleton object can be generated through factory, and this object can be injected into modules a and b that need communication.
Based on events
There are two ways to do this
The first is to use the parent controller. In the child controller, trigger an event ( $emit ) to the parent controller, then listen for ( $on ) events in the parent controller, and then broadcast ( $broadcast ) to the child controller. In this way, through the parameters carried by the event, data is propagated through the parent controller and among the same level controllers.
The second type is to use $rootScope. Each Angular application has a root scope $rootScope by default. The root scope is at the top level, and there are scopes at all levels hanging from it. Therefore, if the subcontroller directly uses $rootScope to broadcast and receive events, communication between peers can be achieved.
See the communication between controllers in AngularJS
How should an angular application be well layered?
Dividing directory structure
For small projects, you can organize them by file type, such as:
cssjs controllers models services filters
However, for larger projects, it is best to divide them according to business modules, such as:
cssmodules account controllers models services filters templates disk controllers models services filters templates
It is best to have a common directory under modules to store public things.
Splitting of logical code
As an MVVM framework, Angular applications should be divided according to model, view model (controller), and views.
The splitting of the logic code here mainly refers to trying to make the controller layer very thin as much as possible. Extract shared logic into the service (such as background data requests, data sharing and cache, event-based inter-module communication, etc.), extract shared interface operations into directive (such as encapsulating date selection, paging, etc. into components, etc.), extract shared format operations into filter, etc., etc.
In complex applications, corresponding constructors can also be established for entities, such as hard disk (Disk) module, which may have several views such as list, new creation, and details, and corresponding controllers respectively. Then, a Disk constructor can be built to complete the data addition, deletion, modification and verification operations. If there is a Disk-related controller, the Disk constructor is injected into the Disk constructor and an instance is generated. This instance has the methods of adding, deletion, modification and verification. This not only has clear layers but also realizes reuse (making the controller layer thinner).
Refer to the in-depth practice of AngularJS in Suning Cloud Center
What routing libraries are commonly used for angular applications and what are their differences?
ngRoute and ui.router are commonly used in Angular1.x, and there is also a new router (component-oriented) designed for Angular2. The one behind has not been used in the actual project, so I won’t talk about it.
Whether it is ngRoute or ui.router, as an additional additional feature of the framework, must be introduced in the form of module dependencies.
the difference
The ngRoute module is an Angular routing module, while the ui.router module is a third-party module developed based on the ngRoute module.
ui.router is based on state (state), ngRoute is based on url, and the ui.router module has more powerful functions, mainly reflected in the nesting aspects of views.
Use ui.router to define routes with clear parent-child relationships, and insert child routing templates into <div ui-view></div> of the parent routing template through the ui-view directive, thereby realizing view nesting. This cannot be defined in ngRoute. If <div ng-view></div> is used in the parent-child view at the same time, it will fall into a dead loop.
Example
ngRoute
var app = angular.module('ngRouteApp', ['ngRoute']);app.config(function($routeProvider){ $routeProvider .when('/main', { templateUrl: "main.html", controller: 'MainCtrl' }) .otherwise({ redirectTo: '/tabs' });ui.router
var app = angular.module("uiRouteApp", ["ui.router"]);app.config(function($urlRouterProvider, $stateProvider){ $urlRouterProvider.otherwise("/index"); $stateProvider .state("Main", { url: "/main", templateUrl: "main.html", controller: 'MainCtrl' })If you plan a fully-component system through angular directive, what challenges may you encounter?
I have never made a complete set of components with directive myself, so I can't explain it.
One thing that can be thought of is how components interact with the outside world and how they can be used through simple configuration.
Angular applications developed by different teams. If you want to integrate them, what problems may be encountered and how to solve them?
Conflicts between different modules may be encountered.
For example, all developments of one team are carried out under moduleA, while the code developed by another team is carried out under moduleB
angular.module('myApp.moduleA', []) .factory('serviceA', function(){ ... }) angular.module('myApp.moduleB', []) .factory('serviceA', function(){ ... }) angular.module('myApp', ['myApp.moduleA', 'myApp.moduleB'])This will cause serviceA under two modules to be overwritten.
It seems that there is no good solution in Angular1.x, so it is best to make unified planning in the early stage, make agreements, and develop strictly in accordance with the agreement. Each developer only writes specific block code.
What are the disadvantages of angular?
Strong constraints
This leads to high learning costs and is unfriendly to the front end.
But when following AngularJS conventions, productivity will be high and Java programmer-friendly.
Not conducive to SEO
Because all content is dynamically acquired and rendered, search engines cannot crawl.
One solution is that for normal user access, the server responds to the content of the AngularJS application; for search engine access, it responds to HTML pages specifically for SEO.
Performance issues
As the MVVM framework, because the two-way binding of data is implemented, there will be performance problems for large arrays and complex objects.
Methods that can be used to optimize the performance of Angular applications:
Reduce monitoring items (such as one-way binding for data that does not change)
Actively set the index (specify track by, simple types use themselves as index by default, and objects use $$hashKey by default, for example, change to track by item.id)
Reduce the amount of rendered data (such as paging, or fetching a small part of the data each time, and retrieving it as needed)
Data flattening (for example, for tree structures, use flattening structures to build a map and tree data. When operating on the tree, since the same reference as the flat data, the tree data changes will be synchronized to the original flat data)
In addition, for Angular1.x, there are problems with dirty checking and module mechanism.
Mobile
Ionic can be tried, but it is not perfect.
How to view Peter-Paul Koch's view on Angular in January 2015?
How do you view the controller as syntax introduced in angular 1.2?
The most fundamental benefit
Before angular 1.2, any binding on the view was directly bound to $scope
function myCtrl($scope){ $scope.a = 'aaa'; $scope.foo = function(){ ... }}Using controllerAs, no need to inject $scope again, controller becomes a very simple javascript object (POJO), a more pure ViewModel.
function myCtrl(){ // Use vm to capture this to avoid the internal functions causing the context to change when using this var vm = this; vm.a = 'aaa';}principle
From the source code implementation point of view, the controllerAs syntax just creates an attribute on $scope with the as alias for instance of the controller object.
if (directive.controllerAs) { locals.$scope[directive.controllerAs] = controllerInstance;}However, in addition to making the controller more POJO mentioned above, you can also avoid encountering a pit related to AngularJS scope (that is, the pit in which ng-if generates a first-level scope, which is actually a pit in the inheritance of the median type of the JavaScript prototype chain. Because when using controllerAs, all fields on the view are bound to a referenced attribute, such as vm.xx, so the pit no longer exists).
<div ng-controller="TestCtrl as vm"> <p>{{name}}</p> <div ng-if="vm.name"> <input type="text" ng-model="vm.name"> </div></div>question
One problem you will encounter with controllerAs is that because no $scope is injected, methods under $emit, $broadcast, $on, $watch, etc. cannot be used. These event-related operations can be encapsulated and handled uniformly, or $scope is introduced into a single controller for special treatment.
Reference angular controller as syntax vs scope
Details of angular's "dependency injection"
chestnut
Dependency injection is a software design pattern that aims to handle dependencies between codes and reduce coupling between components.
For example, if you are not using AngularJS, you may need to do this if you want to query data from the background and display it in the front end:
var animalBox = document.querySelector('.animal-box');var httpRequest = { get: function(url, callback){ console.log(url + ' requested'); var animals = ['cat', 'dog', 'rabbit']; callback(animals); }}var render = function(el, http){ http.get('/api/animals', function(animals){ el.innerHTML = animals; })} render(httpRequest, animalBox);However, if the parameters are not passed when the render is called, like the following, an error will be reported because el and http cannot be found (the dependency is defined, and the dependency will not be automatically found when running)
render();
// TypeError: Cannot read property 'get' of undefined
And using AngularJS, you can do this directly
function myCtrl = ($scope, $http){ $http.get('/api/animals').success(function(data){ $scope.animals = data; })}In other words, when Angular App is running, myCtrl is called and two dependencies, $scope and $http are automatically injected.
principle
AngularJS infers the dependency service name through the parameter name of the constructor, and uses toString() to find the corresponding string corresponding to this defined function, then parses out the parameters (dependencies) in regularity, then gets the corresponding dependency in the dependency map, and instantiates it and passes it in.
To simplify it, it's probably like this:
var inject = { // Storage dependency mapping relationship storage: {}, // Register the dependency register: function(name, resource){ this.storage[name] = resource; }, // parse out the dependency and call resolve: function(target){ var self = this; var FN_ARGS = /^function/s*[^/(]*/(/s*([^/)]*)/)/m; var STRIP_COMMENTS = /((////.*$)|(///*[/s/S]*?/*//))/mg; fnText = target.toString().replace(STRIP_COMMENTS, ''); argDecl = fnText.match(FN_ARGS)[1].split(/, ?/g); var args = []; argDecl.forEach(function(arg){ if(self.storage[arg]){ args.push(self.storage[arg]); } }) return function(){ target.apply({}, args); } }}Using this injector, the previous chestnut that does not use AngularJS can be called after modifying it.
inject.register('el', animalBox);inject.register('ajax', httpRequest);reender = inject.resolve(render);reender();question
Because AngularJS injector assumes that the parameter name of the function is the name of the dependency, and then search for the dependency, if the dependency is injected as in the previous chestnut, after the code is compressed (the parameters are renamed), the dependency cannot be found.
// function myCtrl = ($scope, $http){ ...}// function myCtrl = (a, b){ ...}Therefore, the following two methods are usually used to inject dependencies (there are requirements for the order in which dependencies are added).
Array annotation method
myApp.controller('myCtrl', ['$scope', '$http', function($scope, $http){ ...}])Explicit $inject
myApp.controller('myCtrl', myCtrl);function myCtrl = ($scope, $http){ ...}myCtrl.$inject = ['$scope', '$http'];Replenish
For a DI container, three elements must be included: the registration of dependencies, the declaration of dependencies, and the acquisition of objects.
In AngularJS, both module and $provide can provide the registration of dependencies; the built-in injector can obtain objects (automatically complete dependency injection); the declaration of dependencies is as mentioned in the previous question.
Here is a chestnut
// For module, more than one parameter is passed, which means a new module is created, and an empty array means no dependency on other modules// There is only one parameter (module name), which means obtaining module// Define myApp, add myApp.services as its dependency angular.module('myApp', ['myApp.services']);// Define a service module, register all services in this module angular.module('myApp.services', [])// $provider has factory, service, provider, value, constant// Define an HttpServiceangular.module('myApp.services').service('HttpService', ['$http', function($http){ ...}])refer to
[AngularJS] Implement a simple dependency injection by yourself
Understand modules and injectors in angular, i.e. dependency injection
Dependency injection practical application scenario in AngularJS
How to view angular2
Compared with Angular1.x, Angular2 has made great changes and is almost a brand new framework.
Based on TypeScript (which can be developed using TypeScript), strong language types are more beneficial when large-scale project teams collaborate.
Componentization improves the efficiency of development and maintenance.
There are also modules that support dynamic loading, new routers, native support for promises, etc.
It caters to future standards and absorbs the advantages of other frameworks, which is worth looking forward to, but there are also more things to learn (ES next, TS, Rx, etc.).
The above is a compilation of the information for AngularJS interview questions. We will continue to add relevant information in the future. Thank you for your support for this website!