Angular 面试问题
一、AngularJS 是什么?
AngularJS 是一个由 Google 开发的开源 JavaScript 框架。它主要用于构建动态的 Web 应用程序,并且易于从 HTML 文档中更新和获取信息。AngularJS 帮助开发者编写易于维护的架构,并且可以在客户端代码中进行测试。
1.1 AngularJS 的特点
-
基于 MVC 设计模式:AngularJS 采用 MVC(Model-View-Controller)设计模式,帮助开发者更好地组织代码。 -
SPA 支持:AngularJS 提供了完整的单页面应用(SPA, Single Page Application)框架支持。 -
依赖注入:AngularJS 内置了依赖注入机制,使得组件之间的依赖关系更加清晰。 -
双向数据绑定:AngularJS 支持数据的双向绑定,简化了数据同步的工作。 -
路由功能:AngularJS 内置了路由功能,方便管理复杂的前端应用。 -
易于测试:AngularJS 从设计之初就考虑到了测试的需求,使得构建强大的测试成为可能。 -
DOM 操作:AngularJS 包含了一个轻量级的 jQuery 替代品——jqLite,用于 DOM 操纵。 -
前后端分离:AngularJS 使客户端与服务器端的逻辑分离,提高了应用的可维护性。 -
使用 POJO:AngularJS 使用普通的 JavaScript 对象(Plain Old JavaScript Object, POJO),不需要专门的 getter 或 setter 方法。 -
开发工具兼容:你可以使用任何 HTML 编辑器或者开发 IDE,如 Visual Studio 或 Visual Studio Code 来构建 Angular 应用。
二、AngularJS 中的指令是什么?
AngularJS 指令是用来扩展 HTML 和 DOM 元素行为的特殊属性,通常以 ng-
前缀开始。这些指令告诉 AngularJS 的 HTML 编译器 $compile
将特定的行为附加到 DOM 元素上。
2.1 AngularJS 内置指令
AngularJS 提供了一套内置指令,例如:
-
ngBind
:用于绑定数据到 HTML 元素。 -
ngModel
:用于定义模型变量,并提供双向数据绑定行为。 -
ngClass
:用于条件性地添加或删除元素上的类。 -
ngApp
:指示 AngularJS HTML 编译器$compile
开始的位置。 -
ngInit
:用于初始化 AngularJS 应用的数据变量。 -
ngRepeat
:用于重复 HTML 语句。
示例代码
<div ng-app="myApp">
<div ng-init="message='Hello AngularJS!'">
<p>{{ message }}p>
<ul>
<li ng-repeat="item in items">{{ item.name }}li>
ul>
div>
div>
三、AngularJS 中的表达式是什么?
AngularJS 表达式类似于 JavaScript 代码片段,通常写在双花括号 {{ }}
之中。Angular 表达式是 JavaScript 代码片段的一个子集,包含在 HTML 元素中。
3.1 AngularJS 表达式的使用
表达式可以包含各种有效的表达式,例如:
-
数字运算: {{ 2 + 2 }}
-
字符串连接: {{ 'Hello' + ' World' }}
-
对象访问: {{ person.name }}
-
数组索引: {{ items[0].name }}
示例代码
<div ng-controller="appController">
<span>
4+5 = {{ 4 + 5 }}
span>
<br />
<br />
<span ng-init="quantity=5; cost=25">
Total Cost = {{ quantity * cost }}
span>
div>
四、AngularJS 中的货币过滤器是什么?
AngularJS 中的货币过滤器 currency
默认包含美元符号 $
。使用格式如下:
{{ currency_expression | currency : symbol : fractionSize}}
4.1 如何使用货币过滤器
默认使用
如果不提供货币符号,默认会使用美元符号 $
:
Default Currency {{ amount | currency }}
用户定义
可以通过定义 Unicode 或十六进制代码来自定义货币符号:
Indian Currency {{ amount | currency:"?" }}
五、AngularJS 中的 $scope 是什么?
在 AngularJS 中,$scope
是一个指向应用程序模型的对象。它是连接视图(DOM 元素)与控制器的对象。在控制器中,模型数据通过 $scope
对象来访问。AngularJS 支持 MV* 模式,其中 $scope
成为 MV* 的模型。
5.1 $scope 的作用
-
通信桥梁: $scope
对象作为视图和控制器之间通信的桥梁。 -
数据与函数: $scope
包含数据和函数。 -
顶级作用域:每个 AngularJS 应用都有一个 $rootScope
,它是顶层作用域。 -
事件传播: $scope
可以监听表达式变化并传播事件。
示例代码
html>
<html>
<head>
<title>AngularJS Test Applicationtitle>
<script src="angular.js">script>
head>
<body ng-app="myapp">
<h2>AngularJS - Scope Inheritanceh2>
<div ng-controller="ParentController">
<div ng-controller="firstChildController">
<div ng-controller="secondChildController">
<p>Parent Name:{{parentName}}p>
<p>First Child Name:{{level1name}}p>
<p>Second Child Name:{{level2name}}p>
div>
div>
div>
<script>
var app = angular.module("myapp", []);
app.controller("ParentController", function($scope) {
$scope.parentName = "Parent Controller";
});
app.controller("firstChildController", function($scope) {
$scope.level1name = "First Child Controller";
});
app.controller("secondChildController", function($scope) {
$scope.level2name = "Second Child Controller";
});
script>
body>
html>
以上示例展示了如何在 AngularJS 中使用 $scope
来在不同控制器之间传递数据。每个控制器定义了自己的作用域变量,并且这些变量可以在对应的视图中使用。通过嵌套的控制器,可以看到 $scope
的继承特性。
六、AngularJS 中的 $rootScope 是什么?
$rootScope
在 AngularJS 中是所有其他作用域的父级作用域,它是顶层的数据容器。我们可以将数据存储在 $rootScope
中,并在需要时从中读取。
6.1 使用 $rootScope
通过 $rootScope
,我们可以在一个控制器中设置值,在另一个控制器中读取它。这使得全局共享数据变得简单。
示例代码
html>
<html ng-app="myApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js">script>
<script>
var myApp = angular.module('myApp', []);
function controllerOne($scope, $rootScope) {
$rootScope.name = 'From Rootscope set in controllerOne';
}
function controllerTwo($scope, $rootScope) {
$scope.name2 = $rootScope.name;
}
script>
head>
<body>
<div style="border: 5px solid gray; width: 300px;">
<div ng-controller="controllerOne">
Setting the rootscope in controllerOne
div>
<div ng-controller="controllerTwo">
Hello, {{name2}}!
div>
<br />
div>
body>
html>
在这个例子中,controllerOne
设置了 $rootScope.name
的值,而 controllerTwo
通过 $scope.name2
访问了这个值。
七、AngularJS 中的 SPA(单页应用)是什么?
单页应用(SPA, Single Page Application)是一种Web应用形式,它们加载一个HTML页面并在用户与应用交互时动态更新该页面。SPA 利用了 AJAX 和 HTML 来创建流畅响应的应用程序,无需频繁重新加载整个页面。
7.1 单页应用的关键点
-
界面响应:应用程序在用户界面上是响应式的,没有页面闪烁。 -
后退/前进按钮:浏览器的后退/前进按钮按预期工作。 -
更多的 JavaScript:比起实际的 HTML,有更多的 JavaScript 脚本。 -
动态数据加载:从服务器端 API 加载动态数据,通常使用 RESTful web 服务和 JSON 格式。 -
丰富的 UI 交互:UI 组件之间的丰富交互。 -
减少数据传输:减少了从服务器传输的数据量,大部分页面处理发生在客户端。 -
标签和子标签:应用程序包含标签和子标签,点击时加载不同的 HTML 容器到页面中。 -
跨浏览器兼容性:AngularJS 编写的应用程序具有跨浏览器兼容性,Angular 自动处理适合每个浏览器的 JavaScript 代码。
八、如何在 AngularJS 中实现路由?
路由是 AngularJS 的核心特性之一,对于构建包含多个视图的单页应用(SPA)非常有用。在 SPA 中,所有视图都是不同的 HTML 文件,通过路由加载应用的不同部分,并有助于逻辑地划分应用使其更易管理。
8.1 添加路由的方法
为了配置路由,我们需要在模块中定义 $routeProvider
,该定义包含在名为 ngRoute
的模块中。以下是一个简单的路由配置示例:
var app = angular.module("AngularApp", ['ngRoute']);
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/page1', {
templateUrl: 'Modules/Page1/page1.html',
controller: 'Page1Controller'
}).
when('/page2', {
templateUrl: 'Modules/Page2/page2.html',
controller: 'Page2Controller'
}).
otherwise({
redirectTo: '/page1'
});
}]);
在这个例子中,当 URL 匹配 /page1
时,将加载 page1.html
并且使用 Page1Controller
控制器;如果 URL 匹配 /page2
,则加载 page2.html
并且使用 Page2Controller
控制器;如果 URL 不匹配上述路径,则重定向到 /page1
。
九、AngularJS 中有多少种数据绑定类型?
数据绑定是软件开发技术中的一个重要特性,它是应用视图和业务逻辑(视图模型)之间的连接桥。在 AngularJS 中,数据绑定是模型和视图之间自动同步的过程。当模型改变时,视图会被自动更新,反之亦然。AngularJS 支持单向和双向数据绑定。
9.1 数据绑定指令
AngularJS 提供了几种数据绑定相关的指令:
-
ng-bind
:更新指定 HTML 元素的文本内容。 -
ng-bind-html
:安全地插入 HTML 内容。 -
ng-bind-template
:用模板插值替换元素文本内容。 -
ng-non-bindable
:告知 Angular 不要编译或绑定当前 DOM 元素的内容。 -
ng-model
:绑定输入、选择、文本区域或任何自定义表单控件,并提供双向绑定及验证行为。
示例代码
<p ng-bind="message">p>
<p ng-bind-html="safeHtmlContent">p>
<p ng-bind-template="{{user.firstName}} {{user.lastName}}">p>
<div ng-non-bindable>{{expression}}div>
<input type="text" ng-model="username" />
十、AngularJS 中的工厂方法是什么?
AngularJS 工厂(Factory)的功能与服务(Service)相似,但是工厂允许我们创建一个新的对象,并将函数作为该对象的属性,最后返回这个对象。这样可以更好地封装逻辑。
10.1 创建工厂
工厂可以通过模块的 .factory()
方法来定义。
示例代码
<div ng-app="Myapp">
<div ng-controller="exampleCtrl">
<input type="text" ng-model="num.firstnumber" />
<input type="text" ng-model="num.secondnumber" />
<input type="button" ng-click="Factoryclick()" value="Factoryclick" />
<input type="button" ng-click="servclick()" value="Serviceclick" />
factory result {{facresult}} service result {{secresult}}
div>
div>
<script>
var myapp = angular.module('Myapp', []);
myapp.controller('exampleCtrl', ['$scope', '$http', 'factories', 'services', function(scope, http, fac, ser) {
scope.Factoryclick = function() {
var firstnumber = parseInt(scope.num.firstnumber);
var secondnumber = parseInt(scope.num.secondnumber);
scope.facresult = fac.sumofnums(firstnumber, secondnumber);
}
scope.servclick = function() {
var firstnumber = parseInt(scope.num.firstnumber);
var secondnumber = parseInt(scope.num.secondnumber);
scope.secresult = ser.sersumofnums(firstnumber, secondnumber);
}
}]);
myapp.factory('factories', function($http) {
return {
sumofnums: function(a, b) {
return a + b;
}
}
});
myapp.service('services', function($http) {
this.sersumofnums = function(a, b) {
return a + b;
};
});
script>
在这个例子中,我们定义了一个工厂 factories
和一个服务 services
,两者都提供了求两个数之和的方法。通过控制器中的按钮点击事件,可以调用这两个方法,并展示结果。
十一、AngularJS 中如何实现验证?
AngularJS 提供了强大的客户端验证功能。有许多表单指令可用于实现各种类型的验证。下面是一些基本的验证类型及其实现方式:
11.1 数据类型验证
在 HTML 控件中使用 type
属性来指定数据类型,如数字类型。$error.{your data type}
可以用来显示错误信息。
<p>
<input type="number" name="StudentRollNumber" ng-model="StudentRollNumber" required>
<span style="color:red" ng-show="myForm.StudentRollNumber.$dirty && myForm.StudentRollNumber.$invalid">
<span ng-show="myForm.StudentRollNumber.$error.required">学生学号是必需的。span>
<span ng-show="myForm.StudentRollNumber.$error.number">无效的数字!span>
span>
p>
11.2 必填字段验证
为 HTML 控件添加 required
属性,$error.required
可用于显示必填字段的消息。
<p>
<input type="text" name="StudentName" ng-model="StudentName" required>
<span style="color:red" ng-show="myForm.StudentName.$dirty && myForm.StudentName.$invalid">
<span ng-show="myForm.StudentName.$error.required">学生姓名是必需的。span>
span>
p>
11.3 日期验证
指定 type
为 date
并利用系统的内置格式。$error.date
可用于显示日期验证消息。
<p>
学生出生日期:<br>
<input type="date" name="BirthDate" ng-model="BirthDate" required>
<span style="color:red" ng-show="myForm.BirthDate.$dirty && myForm.BirthDate.$invalid">
<span ng-show="myForm.BirthDate.$error.required">学生出生日期是必需的。span>
<span ng-show="myForm.BirthDate.$error.date">不是一个有效的日期。span>
span>
p>
11.4 邮箱验证
指定 type
为 email
并使用 $error.email
显示邮箱验证消息。
<input type="email" name="email" ng-model="email" required>
<span style="color:red" ng-show="myForm.email.$dirty && myForm.email.$invalid">
<span ng-show="myForm.email.$error.required">邮箱是必需的。span>
<span ng-show="myForm.email.$error.email">无效的电子邮件地址。span>
span>
11.5 范围验证(最大值和最小值)
为控件指定 max
或 min
属性,使用 $error.max
或 $error.min
来显示错误信息。
<input type="number" name="marks" ng-model="marks" max="100" required>
<span style="color:red" ng-show="myForm.marks.$dirty && myForm.marks.$invalid">
<span ng-show="myForm.marks.$error.required">成绩是必需的。span>
<span ng-show="myForm.marks.$error.number">无效的数字。span>
<span ng-show="myForm.marks.$error.max">最高分为100。span>
span>
11.6 自定义验证
除了以上提供的内置验证,AngularJS 还允许你创建自定义验证器。你可以定义一个自定义验证指令或者在控制器中定义验证逻辑。
十二、什么是 $rootScope
以及如何使用它?
$rootScope
是 AngularJS 应用程序的顶级作用域,所有的其他作用域都是它的子作用域。通过 $rootScope
,可以在不同控制器间共享数据。
12.1 如何使用 $rootScope
首先需要在 标签中添加 ng-app
属性来初始化 AngularJS 应用。然后,可以在控制器中注入 $rootScope
并设置全局变量。
<html ng-app="app" xmlns="https://www.w3.org/1999/xhtml">
<head runat="server">
<title>title>
<script src="angular.min.js">script>
<script>
angular.module('app', []).controller('x', function ($scope, $rootScope) {
$rootScope.showAlert = "Hello Everyone";
});
angular.module('app').controller('x2', function ($scope, $rootScope) {
$scope.val = $rootScope.showAlert;
alert($scope.val);
});
script>
head>
<body>
<form id="form1" runat="server">
<div ng-app="app">
<div ng-controller="x">div>
<div ng-controller="x2">{{val}}div>
div>
form>
body>
html>
在这个例子中,showAlert
变量被设置在 $rootScope
上,因此可以在任何其他控制器中访问它。
十三、解释 AngularJS 中的依赖注入
依赖注入(Dependency Injection, DI)是 AngularJS 中的一个重要特性,它是一种设计模式,其中对象作为依赖项被传递进来。依赖注入帮助我们移除硬编码的依赖关系,并使依赖关系可配置。使用 DI 可以让组件更易于维护、复用和测试。
13.1 为什么需要依赖注入
-
分离依赖项的创建和消费过程。 -
允许独立开发依赖项。 -
可以根据需要更改依赖项。 -
允许在测试时注入模拟对象作为依赖项。
AngularJS 使用多种类型的依赖:
-
值(Value) -
工厂(Factory) -
服务(Service) -
提供者(Provider) -
常量(Constant)
13.2 依赖注入示例
angular.module('AppModule', [])
.controller("AppController", function($scope, $window, $log, $http) {
// 控制器逻辑
});
在这个示例中,$scope
, $window
, $log
, 和 $http
都是从 AngularJS 注入的依赖。
十四、解释如何使用 AngularJS 将文本转换为大写
AngularJS 提供了一个过滤器 uppercase
,可以将文本转换为全大写。
14.1 使用 uppercase
过滤器
<html ng-app xmlns="https://www.w3.org/1999/xhtml">
<head runat="server">
<title>title>
<script src="angular.min.js">script>
<script>
function x($scope) {
$scope.test = "this text will be displayed in UPPERCASE";
}
script>
head>
<body>
<form id="form1" runat="server">
<div ng-controller="x">
未转换为大写:{{test}}<br />
转换为大写:{{test | uppercase}}
div>
form>
body>
html>
在这个例子中,test
变量的值被通过 | uppercase
过滤器转换为大写。
十五、解释 ng-repeat
指令
ng-repeat
指令是 AngularJS 中最常用和最有用的指令之一。它遍历一个项目集合并创建 DOM 元素。它会持续监视数据源的变化,并在数据变化时重新渲染模板。
15.1 ng-repeat
指令语法
<table class="table table-bordered">
<tr ng-repeat="emp in empDetails">
<td>{{emp.name}}td>
<td>{{emp.salary}}td>
tr>
table>
在这个例子中,ng-repeat
指令遍历 empDetails
集合,并为集合中的每一项创建一个 DOM 元素。
15.2 ng-repeat
创建的变量
ng-repeat
指令在为集合的每个元素创建的作用域中创建了一些特殊的变量,这些变量对于确定元素在集合中的位置非常重要:
-
$index
:当前迭代项的索引。 -
$first
:如果当前项是第一个元素,则为真。 -
$middle
:如果当前项既不是第一个也不是最后一个,则为真。 -
$last
:如果当前项是最后一个元素,则为真。
十六、AngularJS 中的控制器是什么?
控制器是一组绑定到特定作用域的 JavaScript 函数,即 ng-controller
指令。Angular 会实例化新的控制器对象,并将其注入到新的作用域中。控制器包含视图的业务逻辑,并避免直接使用控制器来操作 DOM。
16.1 控制器规则
-
我们可以使用控制器来设置作用域对象的初始状态,并向该对象添加行为。 -
不应使用控制器来操纵 DOM;它应该只包含业务逻辑,并且可以使用数据绑定和指令来进行 DOM 操纵。 -
不应使用控制器来格式化输入,而应使用 Angular 表单控件。 -
不应使用过滤器输出,而应使用 Angular 过滤器。 -
不应使用控制器跨控制器共享代码或状态,而应使用 Angular 服务。 -
不应管理其他组件的生命周期。
16.2 创建控制器
-
需要 ng-controller
指令。 -
将控制器代码添加到模块中。 -
根据功能命名控制器。 -
控制器名称使用驼峰式命名(例如 SimpleController)。 -
设置作用域对象的初始状态。
<div ng-app="mainApp" ng-controller="SimpleController">
div>
16.3 ng-Controller
指令
ng-Controller
指令将一个关联的控制器类绑定到视图上。
十七、AngularJS 中的过滤器是什么?
过滤器用于修改数据,并且可以在表达式或指令中使用管道符(|
)来组合。过滤器格式化表达式的值以便向用户展示。它们可以在视图模板、控制器或服务中使用,并且我们可以轻松地创建自己的过滤器。
AngularJS 内置的过滤器包括:
-
currency
: 将所有数字转换为货币格式,默认货币符号为$
。 -
date
: 将数字转换为日期格式。 -
filter
: 用于过滤数组。 -
json
: 将对象转换为 JSON 字符串。 -
limitTo
: 对数组进行截断显示。 -
lowercase
: 将所有字母转换为小写。 -
number
: 格式化数字,可以指定小数位数。 -
orderBy
: 对数组排序。 -
uppercase
: 将所有字母转换为大写。
十八、AngularJS 中的模块和控制器是什么?
18.1 模块
AngularJS 模块是一个包含所有 Angular 组件(如控制器、服务、指令、过滤器、配置等)的容器。
模块是 AngularJS 应用程序的入口点,类似于 .NET 控制台应用程序中的 Main
方法。我们可以通过模块来决定 AngularJS 应用程序应该如何启动。
创建一个简单的模块:
var myApp = angular.module('myModuleApp', []);
在这个代码中,myModuleApp
是模块名称,如果此模块依赖于其他模块,我们可以在 []
中注入它们。
18.2 控制器
控制器是一个控制数据的 JavaScript 构造函数。构造函数每次调用都会创建一个新的对象实例。
创建一个控制器的例子:
myApp.controller('myController', function($scope) {
// 控制器逻辑
});
十九、AngularJS 中的服务是什么?
服务是 AngularJS 中最重要的概念之一。一般而言,服务是在应用程序中负责特定任务的功能。AngularJS 服务基于两个原则设计:
-
懒加载:Angular 只有在应用程序组件依赖于它并通过依赖注入使用时才会实例化服务。 -
单例:每个依赖于服务的组件都会获取由服务工厂生成的单一实例的引用。
AngularJS 提供了许多内置服务,例如 $http
、$route
、$window
、$location
等。每个服务都负责一个特定的任务,比如 $http
用于发起 AJAX 请求以获取服务器数据,$route
定义路由信息等。内置服务总是以 $
符号开头。
二十、AngularJS 中的双击事件是什么?
ng-dblclick
指令允许您指定鼠标在网页上双击时的自定义行为。您可以像这样将 ng-dblclick
作为 HTML 元素的属性来使用:
<ANY_HTML_ELEMENT ng-dblclick="{expression}">
...
ANY_HTML_ELEMENT>
创建一个双击事件的示例:
html>
<html ng-app="myApp">
<head>
<script src="angular.min.js">script>
head>
<body ng-controller="MyController">
名字:
<input ng-model="name" type="text" />
<button ng-dblclick="sayHello()">双击button>
<h3>{{message}}h3>
body>
<script>
var myApp = angular.module('myApp', []);
myApp.controller('MyController', function($scope) {
$scope.sayHello = function() {
$scope.message = 'Hello ' + $scope.name;
};
});
script>
html>
在这个例子中,当双击按钮时,sayHello
函数会被调用,并且会将消息设置为 Hello {name}
,这里的 {name}
是输入框中的值。
二十一、AngularJS 中的 ng-include、ng-click 和 ng-repeat 指令是什么?
21.1 ng-include 指令
ng-include
指令用于在一个主页面中包含其他文件。这对于创建可重用的布局组件非常有用,例如头部、主体和脚部。通过这种方式,可以使页面看起来更整洁,并且使代码和设计分离。
例如:
<body ng-app="myApp" ng-controller="MainCtrl">
<div ng-include="'header.html'">div>
<div>这里是页面主体部分。div>
<div ng-include="'footer.html'">div>
body>
21.2 ng-click 指令
ng-click
指令用于处理元素上的点击事件。当用户点击带有 ng-click
指令的元素时,AngularJS 会执行该指令所绑定的函数。
例如:
<button ng-click="doSomething()">点击我button>
在控制器中定义 doSomething
函数:
app.controller('MainCtrl', function($scope) {
$scope.doSomething = function() {
alert('你点击了按钮!');
};
});
21.3 ng-repeat 指令
ng-repeat
指令类似于 C# 中的 foreach 循环,用于在视图中展示一组项的集合。例如,如果你想展示员工列表,你可以使用 ng-repeat
指令。
例如:
<table>
<tr ng-repeat="employee in employees">
<td>{{employee.name}}td>
<td>{{employee.position}}td>
<td>{{employee.location}}td>
tr>
table>
二十二、AngularJS 中的 ng-disabled 指令是什么?
ng-disabled
指令用于启用或禁用 HTML 元素。当 ng-disabled
的表达式计算结果为真时,元素将被禁用。
例如:
<input type="checkbox" ng-model="isEnabled">
<button ng-disabled="!isEnabled">提交button>
在这个例子中,如果复选框被选中,则按钮被禁用;如果复选框未被选中,则按钮可用。
二十三、AngularJS 中的 ng-app 指令是什么?
ng-app
指令用于定义 AngularJS 应用程序。它可以自动引导(bootstrap)一个 AngularJS 应用程序,并指定 AngularJS 应用程序的根元素。通常将 ng-app
放在 或 标签上。在一个 HTML 文档中可以定义多个 ng-app
指令,但只有一个是自动引导的,其他的需要手动引导。
例如:
<div ng-app="myApp" ng-controller="myCtrl">
姓名: {{firstName}}
div>
二十四、为什么使用 AngularJS 以及 AngularJS 的优势有哪些?
AngularJS 基于 MVC 模式,帮助开发者构建结构良好、易于测试和维护的前端应用。
使用 AngularJS 的原因:
-
AngularJS 基于 MVC 模式,有助于正确组织 Web 应用。 -
使得响应式和结构良好的 Web 应用更加扩展性和可读性。 -
使用双向数据绑定,任何模型的变化都会更新视图,反之亦然,无需直接操作 DOM 或事件。 -
支持创建自定义指令,使得组件可重用并抽象 DOM 操作逻辑。 -
支持服务和依赖注入,可以根据需求轻松地将一些实用代码注入到控制器中。
AngularJS 的优势:
-
代码可重用,支持自定义指令。 -
强大的数据绑定,双向数据绑定与 HTML 和作用域一起工作。 -
易于根据需求定制。 -
在互联网上有很好的支持,并且随着时间推移不断有新特性。 -
支持所有主流浏览器。 -
内置表单验证和模板支持。 -
单元测试友好,不需要加载整个应用,仅加载特定模块即可开始单元测试。
二十五、AngularJS 中的 REST(Representational State Transfer)是什么?
REST 是一种基于 HTTP 请求的操作风格。请求的 URL 识别要操作的数据,而 HTTP 方法标识要执行的操作。REST 是一种 API 风格而不是正式规范,对于什么是 RESTful 存在很多讨论和争议。AngularJS 在消费 RESTful Web 服务方面非常灵活。你可以使用 $http
服务来发起 AJAX 请求,特别是如果你来自 jQuery 背景的话。最终,为了更好地与 REST 服务交互,可以使用 $resource
服务。
一个 RESTful Web 服务应当遵循以下约束:
-
基于 URL(例如, https://www.example.com/api/resource
)。 -
使用诸如 JSON 的 Internet 媒体类型进行数据交换。 -
使用标准的 HTTP 方法(GET、PUT、POST、DELETE)。
HTTP 方法在与 REST 服务一起使用时的目的如下:
-
POST
用于创建新资源或在需要大量请求数据时检索资源列表。 -
PUT
用于更新现有资源。 -
GET
用于检索资源或资源列表。 -
DELETE
用于删除资源。
为了实现这一点,首先需要创建一个模型类,如下所示:
属性名 | 类型 | 是否必需 |
---|---|---|
name | String | 是 |
category | String | 是 |
price | number | 是 |
二十六、AngularJS 中的 ng-switch 指令是什么?
ng-switch
指令用于根据作用域中的表达式的不同值有条件地替换 DOM 结构。ng-switch-when
或 ng-switch-default
指令用于显示或隐藏 ng-switch
指令内的元素。你可以在 ng-switch
内放置多个元素,并且每个元素需要有一个 "when" 属性来指定何时显示该元素。当匹配的表达式被找到时,相应的元素会被显示出来,否则它将被隐藏。
示例:
<h4>ngSwitch 示例h4>
<div ng-app="app" ng-controller="HelloController">
员工姓名:
<select ng-model="selection" ng-options="name for name in names">select>
<div ng-switch on="selection">
<div ng-switch-when="Tejas">您选择了 "Tejas"div>
<div ng-switch-when="Rakesh">您选择了 "Rakesh"div>
<div ng-switch-when="Jignesh">您选择了 "Jignesh"div>
<div ng-switch-default>请选择姓名div>
div>
div>
控制器代码:
var app = angular.module("app", []);
app.controller("HelloController", function($scope) {
$scope.names = ['Tejas', 'Jignesh', 'Rakesh'];
});
二十七、为什么在 AngularJS 中使用 $http 服务或 AJAX 请求?
AJAX 是现代 Web 应用的基础,每当你需要与服务器通信而不引起浏览器加载新内容(从而丢弃你的 AngularJS 应用)时,你都会使用到本文描述的服务。如果你是从 RESTful API 获取数据,那么你应该使用 $resource
服务。$resource
提供了一个基于 $http
服务的更高层次的 API,并且使得执行常见的数据操作更为简单。
发送 AJAX 请求的方法有两种:
-
使用 $http
服务定义的便捷方法,这些方法允许你使用最常用的 HTTP 方法(如 GET、POST、DELETE 等)来发送请求。 -
将 $http
服务对象当作一个函数,并传入一个配置对象。
配置 AJAX 请求:
$http
服务的所有方法都接受一个可选的参数,即一个包含配置设置的对象。对于大多数应用,默认的 AJAX 请求配置已经足够,但你也可以通过定义配置对象上的属性来调整请求的方式。
配置选项包括但不限于:
-
data
: 设置发送到服务器的数据。如果设置为一个对象,AngularJS 将其序列化为 JSON 格式。 -
headers
: 用于设置请求头。 -
method
: 设置用于请求的 HTTP 方法。 -
params
: 用于设置 URL 参数。 -
timeout
: 指定请求过期前的毫秒数。 -
transformRequest
: 用于在发送到服务器之前操纵请求。 -
transformResponse
: 用于在从服务器接收后操纵响应。 -
url
: 设置请求的 URL。 -
withCredentials
: 当设置为 true 时,会在请求中包含认证 cookie。
示例 HTML 文件代码:
html>
<html ng-app="TestApp">
<head>
<title>AngularJS AJAXtitle>
<script src="angular.js">script>
<script src="app.js">script>
<script src="ajax_config.js">script>
head>
<body ng-controller="ajaxController">
<div class="panel panel-default">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Nameth>
<th>Categoryth>
<th>Priceth>
tr>
thead>
<tbody>
<tr ng-hide="products.length">
<td colspan="4" class="text-center">No Datatd>
tr>
<tr ng-repeat="item in products">
<td>{{item.Name}}td>
<td>{{item.Category}}td>
<td>{{item.Price | currency}}td>
tr>
tbody>
table>
<p>
<button class="btn btn-primary" ng-click="loadData()">Load Databutton>
<button class="btn btn-primary" ng-click="loadXMLData()">Load Data (XML)button>
p>
div>
body>
html>
示例 JavaScript 文件代码:
var testApp = angular.module('TestApp', []);
testApp.controller('ajaxController', ['$scope', '$http', function($scope, $http) {
$scope.loadData = function() {
$http.get("data.json").then(function(response) {
$scope.products = response.data;
});
};
$scope.loadXMLData = function() {
var config = {
transformResponse: function(data, headersGetter) {
var headers = headersGetter();
if ((headers('content-type') === 'application/xml' || headers('content-type') === 'text/xml') && angular.isString(data)) {
var products = [];
var productElems = angular.element(data.trim()).find('product');
angular.forEach(productElems, function(value, key) {
var product = angular.element(value);
products.push({
Category: product.attr('Category'),
Book: product.attr('Book'),
Publishers: product.attr('Publishers'),
Price: product.attr('Price')
});
});
return products;
} else {
return data;
}
}
};
$http.get("data.xml", config).then(function(response) {
$scope.products = response.data;
});
};
}]);
二十八、为什么使用 AngularJS 全局对象服务?
AngularJS 包含这些服务的主要原因是让测试变得更容易,但单元测试的一个重要方面是需要隔离一小段代码并测试其行为,而不测试其依赖的组件——基本上是创建一个聚焦的测试。DOM API 通过全局对象(如 document
和 window
)暴露功能。
这些对象使得在进行单元测试时不测试浏览器如何实现其全局对象的情况下隔离代码变得困难。使用如 $document
这样的服务可以让 AngularJS 代码不直接使用 DOM API 的全局对象编写,并允许使用 AngularJS 测试服务来配置特定的测试场景。
以下是一些暴露 DOM API 特性的服务:
-
$anchorScroll
: 滚动浏览器窗口到指定的锚点。 -
$document
: 提供一个包含 DOMwindow.document
对象的 jqLite 对象。 -
$interval
: 提供对window.setInterval
函数的增强封装。 -
$location
: 提供访问 URL 的方法。 -
$log
: 提供对console
对象的封装。 -
$timeout
: 提供对window.setTimeout
函数的增强封装。 -
$window
: 提供对 DOMwindow
对象的引用。
二十九、何时以及为何使用及创建服务?
服务用于封装我们需要在应用程序中重用的功能,但这些功能并不明确地适合我们之前讨论过的模型-视图-控制器(Model-View-Controller, MVC)模式。服务主要用于处理横切关注点(Cross-cutting Concerns)。AngularJS 模块定义了三种定义服务的方法:factory、service 和 provider。使用这些方法的结果相同——提供一个可以在整个 AngularJS 应用程序中使用的功能服务对象——但是每个方法创建和服务对象管理的方式略有不同。
内置服务
以下是一些 AngularJS 内置的服务:
-
$anchorScroll
: 滚动浏览器窗口到指定的锚点。 -
$animate
: 动画内容转换。 -
$compile
: 处理 HTML 片段以创建可以用来生成内容的函数。 -
$controller
: 作为 $injector 服务的包装器,实例化控制器。 -
$document
: 提供一个包含 DOMwindow.document
对象的 jqLite 对象。 -
$exceptionHandler
: 处理应用程序中引发的异常。 -
$filter
: 提供对过滤器的访问。 -
$http
: 创建和管理 AJAX 请求。 -
$injector
: 创建 AngularJS 组件的实例。 -
$interpolate
: 处理包含绑定表达式的字符串以创建可以用来生成内容的函数。 -
$interval
: 提供对window.setInterval
函数的增强封装。 -
$location
: 提供对浏览器位置对象的包装。 -
$log
: 提供对全局console
对象的封装。 -
$parse
: 处理表达式以创建可以用来生成内容的函数。 -
$provide
: 实现由模块公开的许多方法。 -
$q
: 提供延迟对象/承诺。 -
$resource
: 提供支持以处理 RESTful API。 -
$rootElement
: 提供对 DOM 中根元素的访问。 -
$rootScope
: 提供对作用域层次结构顶部的访问。 -
$route
: 提供支持以根据浏览器 URL 路径更改视图内容。 -
$routeParams
: 提供有关 URL 路由的信息。 -
$sanitize
: 替换危险的 HTML 字符为它们的安全显示对应字符。 -
$swipe
: 识别滑动手势。 -
$timeout
: 提供对window.setTimeout
函数的增强封装。 -
$window
: 提供对 DOMwindow
对象的引用。
使用 Factory 方法创建服务
定义服务的最简单方法是使用模块的 factory
方法,传递服务名称和返回服务对象的工厂函数。例如:
// ServiceApp.js
var serviceApp = angular.module('ServiceApp', []);
serviceApp.factory("logService", function() {
var messageCount = 0;
return {
log: function(msg) {
console.log("(LOG + " + messageCount++ + ") " + msg);
}
};
});
然后,在另一个模块中注入这个服务模块:
// App.js
var testApp = angular.module('TestApp', ['ServiceApp']);
并在 HTML 文件中使用该服务:
html>
<html ng-app="TestApp">
<head>
<title>AngularJS Factorytitle>
<script src="angular.js">script>
<script src="serviceApp.js">script>
<script src="app.js">script>
<script src="Factory.js">script>
head>
<body ng-controller="FactoryController">
<div class="well">
<div class="btn-group" tri-button counter="data.totalClicks" source="data.device">
<button class="btn btn-default" ng-repeat="item in data.device">{{item}}button>
div>
<h5>Total Clicks: {{data.totalClicks}}h5>
div>
body>
html>
// Factory.js
testApp.controller('FactoryController', function($scope, logService) {
$scope.data = {
device: ["Mobile", "Laptops", "IPad"],
totalClicks: 0
};
$scope.$watch('data.totalClicks', function(newVal) {
logService.log("Total click count: " + newVal);
});
});
testApp.directive("triButton", function(logService) {
return {
scope: { counter: "=counter" },
link: function(scope, element, attrs) {
element.on("click", function(event) {
logService.log("Button click: " + event.target.innerText);
scope.$apply(function() {
scope.counter++;
});
});
}
}
});
三十、在 AngularJS 中解释 Provider 方法
Module.provider
方法允许你更精细地控制服务对象是如何创建或配置的。provider
方法的参数是所定义服务的名称和一个工厂函数。此工厂函数必须返回一个提供了名为 $get
的方法的提供者对象,而 $get
方法又必须返回服务对象。当需要服务时,AngularJS 会调用工厂方法来获取提供者对象,然后再调用 $get
方法来获取服务对象。使用提供者方法并不会改变服务的消费方式,这意味着不需要对示例中的控制器或指令做任何改动。
使用提供者方法的优势在于你可以向提供者方法添加可用于配置服务对象的功能。
为了演示这一过程,我们可以修改 serviceapp.js
文件如下:
var serviceApp = angular.module('ServiceApp', []);
serviceApp.provider("logService", function() {
var counter = true;
var debug = true;
return {
messageCounterEnabled: function(setting) {
if (angular.isDefined(setting)) {
counter = setting;
return this;
} else {
return counter;
}
},
debugEnabled: function(setting) {
if (angular.isDefined(setting)) {
debug = setting;
return this;
} else {
return debug;
}
},
$get: function() {
return {
messageCount: 0,
log: function(msg) {
if (debug) {
console.log("(LOG" + (counter ? " + " + this.messageCount++ + ") " : ") ") + msg);
}
}
};
}
};
});
通过这种方式,你可以在应用程序启动时配置 logService
的行为,例如启用或禁用消息计数或调试输出。
三十一、AngularJS 中的事件处理
在创建如用户交互表单等高级 AngularJS 应用程序时,我们需要处理诸如鼠标点击、移动、键盘按键、变更事件等 DOM 事件。AngularJS 提供了一种简单的方式来添加事件监听器。我们可以通过使用 AngularJS 事件监听器指令之一来将事件监听器附加到 HTML 元素上。
一些常见的 AngularJS 事件监听器指令包括:
-
ng-click
-
ng-dblclick
-
ng-mousedown
-
ng-mouseup
-
ng-mouseenter
-
ng-mouseleave
-
ng-mousemove
-
ng-mouseover
-
ng-keydown
-
ng-keyup
-
ng-keypress
-
ng-change
下面是一个简单的 AngularJS 事件监听器指令示例:
html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js">script>
<script>
angular.module("myapp", [])
.controller("Controller1", function ($scope) {
$scope.myData = {};
$scope.myData.dvClick = function () {
alert("Div clicked");
}
});
script>
head>
<body ng-app="myapp">
<div ng-controller="Controller1">
<div ng-click="myData.dvClick()">Click herediv>
div>
body>
html>
在这个例子中,当用户点击 div
内的文本时,myData.dvClick()
函数将会被调用。正如你在控制器函数中看到的那样,myData
对象有一个 dvClick()
函数被添加到了它上面。事件监听器函数是由控制器函数添加到 $scope
对象上的。
三十二、开发者选择 AngularJS 的主要原因是什么?
AngularJS 是由 Google 开发的一个开源 Web 应用框架,广泛用于构建高度健壮且可扩展的单页面应用(SPA)。以下是开发者选择 AngularJS 的几个主要原因:
-
高性能:AngularJS 受欢迎的原因在于其易于使用和维护,直观的功能,强大的性能,以及构建新特性的效率。开发人员不需要花费大量时间来调试问题,并且可以轻松进行小的更改。 -
依赖管理的有效性:AngularJS 非常擅长依赖注入。对于 SPA,Angular 让动态加载和依赖的组织变得极其容易,无需担心实例化的问题或命名空间问题。此外,由于依赖项是注入的,你可以轻松地用 $httpBackend
模拟$http
服务来进行有效的测试。 -
DOM 中的标记:在 AngularJS 中,标记直接放入 HTML 文档中,这简化了与现有应用程序的集成,并提高了可扩展性。你可以从本地文件系统中的基本 HTML 文档开始使用 AngularJS,并且它允许你构建自定义属性和元素来扩展基本的 HTML 词汇。
三十三、解释 AngularJS 中的 $routeProvider
?
$routeProvider
用于设置 URL 的配置并将其映射到相应的 HTML 页面或 ng-template,并附带一个控制器。AngularJS 中的路由由 $routeProvider
这个服务提供者来处理。这个服务使得将控制器、视图模板与浏览器中的当前 URL 地址连接起来变得非常容易。
你可以使用 myApp
模块的 config()
方法来配置 $routeProvider
。$routeProvider
的 when
方法用于将 URL 绑定到一个模板。这个方法接收一个 URL(例如 /viewDelhi
),它使用 templateUrl
参数映射到一个模板(例如 delhi.htm
)。when
方法还使用 controller
参数为模板绑定一个控制器(例如 controller: 'AddDelhi'
)。
示例代码如下:
mainApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/viewDelhi', {
templateUrl: 'delhi',
controller: 'AddDelhi'
}).
when('/viewMumbai', {
templateUrl: 'mumbai',
controller: 'AddMumbai'
}).
when('/viewJaipur', {
templateUrl: 'jaipur',
controller: 'AddJaipur'
}).
otherwise({
redirectTo: '/viewDelhi'
});
}]);
三十四、创建新的 AngularJS 指令时可以使用哪些属性?
在创建新的 AngularJS 指令时,可以使用以下属性:
-
restrict:限制属性决定了 AngularJS 如何触发模板内的指令。默认值为 "A"
,表示作为属性触发。其他选项包括"E"
(仅匹配元素名称)、"C"
(仅匹配类名称)、"M"
(仅匹配注释名称)或这些选项的组合。 -
templateUrl:告诉 AngularJS HTML 编译器用单独文件中的 HTML 内容替换模板中的自定义指令。 -
template:指定一个内联模板作为字符串。如果指定了 URL,则不会使用。 -
replace:如果为 true
,则替换当前元素;如果为false
或未指定,则将此指令附加到当前元素。 -
transclude:让你将原始子元素移动到新模板内的某个位置。 -
scope:为此指令创建一个新的作用域而不是继承父作用域。 -
controller:创建一个控制器,用于发布跨指令通信的 API。 -
require:要求另一个指令存在以便此指令正确工作。 -
link:编程式地修改结果 DOM 元素实例,添加事件监听器,并设置数据绑定。 -
compile:编程式地修改指令副本中的 DOM 模板,例如在其他指令中使用时。你的编译函数也可以返回链接函数来修改结果元素实例。
三十五、AngularJS 中的不同类型的指令有哪些?
AngularJS 中的指令主要分为以下几种类型:
-
属性指令(Attribute Directives):当找到匹配的属性时,指令处于活动状态。例如, 将数字验证功能添加到输入框。
-
元素指令(Element Directives):当找到匹配的元素时,指令处于活动状态。例如, 可以定义一个自定义元素。 -
组件指令(Component Directives):当找到匹配的组件时,指令处于活动状态。例如, 可能用于定义一个自定义组件。
-
CSS 类指令(Class/CSS Directives):当找到匹配的 CSS 类时,指令处于活动状态。例如, 可以通过 CSS 类来激活某些行为。
三十六、自定义指令中的编译(Compile)和链接(Link)选项是什么?
理解编译(Compile)与链接(Link)选项是 AngularJS 中较为高级的话题之一,它让我们了解 AngularJS 实际是如何工作的。通常情况下,链接(Link)函数被频繁使用。这两个函数基本上是互斥的,即如果同时定义了两者,那么编译(Compile)函数会覆盖链接(Link)函数。
-
编译(Compile):遍历 DOM 并收集所有的指令,并处理模板 DOM 的转换。其结果是一个链接函数。 -
链接(Link):链接函数负责将作用域链接到 DOM。
在定义自定义指令时,你可以定义一个链接(Link)函数或者指定一个对象,该对象可以包含前(Pre)后(Post)两个链接函数。
如果像下面这样定义了编译(Compile)函数,它将覆盖链接(Link)函数:
app.directive('example', function() {
return {
compile: function(tElement, tAttrs, transclude) {
// 编译逻辑
return function link(scope, iElement, iAttrs, controller) {
// 链接逻辑
};
}
};
});
在定义链接(Link)函数时,你可以定义一个单一的函数或指定一个对象,该对象可以进一步定义前(Pre)后(Post)两个链接函数:
app.directive('example', function() {
return {
link: function(scope, element, attrs) {
// 如果只定义了一个函数,它将作为 Post 链接函数执行
},
link: {
pre: function preLink(scope, element, attrs) {
// 前链接逻辑
},
post: function postLink(scope, element, attrs) {
// 后链接逻辑
}
}
};
});
前(Pre)链接函数会在 DOM 被真正插入到文档之前被执行,而后(Post)链接函数会在 DOM 被插入之后被执行。
三十七、解释 AngularJS 中的注入器(Injector)是什么?
$injector
服务负责确定函数声明的依赖项并解析这些依赖项。下表列出了 $injector
服务支持的方法:
名称 | 描述 |
---|---|
annotate(fn) | 获取指定函数的参数,包括那些不对应于服务的参数 |
get(name) | 获取指定服务名的服务对象 |
has(name) | 如果存在指定名称的服务则返回真 |
invoke(fn, self, locals) | 使用指定的 this 值和非服务参数值调用指定的函数 |
$injector
服务位于 AngularJS 库的核心部分,虽然很少需要直接与其打交道,但它有助于理解和定制 AngularJS 的工作方式。然而,这类定制应该谨慎考虑并且彻底测试。
从根元素获取 $injector
服务:
$rootElement
服务提供了对应用了 ng-app
指令的 HTML 元素的访问权限,它是 AngularJS 应用的根。$rootElement
服务表现为一个 jqLite 对象,这意味着你可以使用 jqLite 方法来定位元素或修改 DOM。$rootElement
服务对象还有一个名为 injector
的附加方法,该方法返回 $injector
服务对象。
三十八、说明“作用域(Scope)”的特性是什么?
作用域($scope
)是视图(View)和控制器(Controller)之间的粘合剂。它将控制器与视图连接起来:
-
$scope
是控制器和视图之间的粘合剂。 -
$scope
是 HTML 和视图之间的桥梁。 -
视图和模型都可以访问 $scope
。 -
在 MVC 模型中, $scope
可以被视为 ViewModel。 -
$scope
为 DOM 和表达式提供执行上下文。 -
$scope
提供了一个 DOM 元素绑定的执行上下文。 -
$scope
是事实的来源。 -
当视图改变时 $scope
会被修改,而当$scope
改变时视图也会被更新。 -
$scope
是一个普通的 JavaScript 对象。可以根据需要添加和移除属性。 -
$scope
包含控制器中应显示和执行的数据和函数。 -
所有的 $scope
最终都是$rootScope
的子代。 -
$rootScope
是带有ng-app
指令的 DOM 元素的顶级作用域。 -
所有的 $scope
都是通过原型继承创建的。 -
$scope
可以访问其父级作用域。 -
$scope
包含用于渲染视图的数据和功能。 -
每个创建的控制器都会创建一个新的 $scope
。 -
控制器中包含应用程序逻辑,而控制器的 $scope
中包含数据。 -
当 $scope
对象不再需要在视图中使用时,它将被清理并销毁。 -
指令本身没有自己的作用域,但有一些例外,比如 ng-controller
和ng-repeat
。 -
当 Angular 开始运行时,所有 $scope
都会附加到视图。 -
$scope
传递数据和行为给视图。
三十九、AngularJS 与 Backbone.js 和 Knockout.js 的区别
以下是 AngularJS 与 Backbone.js 和 Knockout.js 之间的一些主要区别:
-
文件大小:
-
AngularJS:大约 142KB(压缩并最小化后) -
Backbone.js:大约 7.3KB(gzip/minified) -
Knockout.js:大约 21KB(gzip/minified)
-
-
版本和许可:
-
AngularJS:V1.4.2 & MIT(开源) -
Backbone.js:V1.2.1 & MIT(开源) -
Knockout.js:V3.3.0 & MIT(开源)
-
-
依赖关系:
-
AngularJS:无依赖 -
Backbone.js:依赖 underscore.js 和 jQuery -
Knockout.js:无依赖
-
-
数据绑定:
-
AngularJS:支持完整的数据绑定,并提供创建自定义数据绑定的选项 -
Backbone.js:默认不支持数据绑定,但可以通过插件实现 -
Knockout.js:完全支持数据绑定,并且可以绑定多个属性,还提供创建自定义数据绑定的选项
-
-
路由:
-
AngularJS:支持路由功能,并且非常简单 -
Backbone.js:支持路由功能,并且非常简单 -
Knockout.js:默认不支持路由,但可通过第三方库实现
-
-
视图:
-
AngularJS:使用 HTML 作为模板语言 -
Backbone.js:默认没有模板,但可以通过第三方模板如 underscore.js 或 handlebars 添加 -
Knockout.js:使用 HTML 作为模板语言
-
-
测试:
-
AngularJS:支持测试驱动开发(TDD) -
Backbone.js:默认不支持测试,但可以使用如 Jasmine 和 Sinon.js 这样的第三方测试工具 -
Knockout.js:默认不支持测试,但可以使用如 Jasmine 和 Sinon.js 这样的第三方测试工具
-
-
数据处理:
-
AngularJS:不支持 jQuery,但可以使用 Angular 的 $http
服务 -
Backbone.js:支持 jQuery 的 $.ajax
,易于理解 -
Knockout.js:支持 jQuery 的 $.ajax
和 knockout mapping
-
-
设计模式:
-
AngularJS:支持 MVC 和 MVVM 设计模式 -
Backbone.js:支持 MVP 设计模式 -
Knockout.js:支持 MVVM 设计模式
-
-
浏览器支持:
-
AngularJS:支持 IE9, IE10, IE11 -
Backbone.js:依赖于支持的浏览器,如 IE6+,Chrome,Firefox,Safari 5.1+ 和 Opera -
Knockout.js:支持所有主流浏览器,如 IE6+,Firefox 3.5+,Chrome,Opera 和 Safari
-
-
第三方集成:
-
AngularJS:不支持第三方集成 -
Backbone.js:不支持第三方集成 -
Knockout.js:支持第三方集成
-
-
文档和支持:
-
AngularJS:有可用的文档和社区 -
Backbone.js:据我所知没有官方文档,但社区支持广泛 -
Knockout.js:有可用的文档和社区
-
四十、AngularJS 与 jQuery 的区别
尽管 AngularJS 和 jQuery 都具有某些共同点,例如单元测试运行器、动画支持、AJAX/JSONP 支持,但它们也有明显的不同之处:
-
AngularJS 带有 RESTful API 支持,而 jQuery 没有。 -
AngularJS 支持 MVC 模式,而 jQuery 不支持。 -
AngularJS 提供双向数据绑定功能,而 jQuery 不支持。 -
AngularJS 支持深度链接路由,而 jQuery 不支持。 -
AngularJS 文件大小比 jQuery 文件要大得多。 -
如果开发重型 Web 应用程序,则更适合选择 AngularJS。
四十一、AngularJS 中的自定义指令是什么?
在 AngularJS 中,您可以为以下类型的元素创建自定义指令:
-
元素指令:当遇到匹配的元素时,指令被激活。限制模式由 “E” 定义。 -
属性指令:当遇到匹配的属性时,指令被激活。限制模式由 “A” 定义。 -
CSS 指令:当遇到匹配的 CSS 样式时,指令被激活。限制模式由 “C” 定义。 -
注释指令:当遇到匹配的注释时,指令被激活。限制模式由 “M” 定义。
四十二、AngularJS 的启动过程是什么?
启动 AngularJS 应用程序有两种方式:
-
自动启动(Automatic Bootstrap):当 DOM 内容加载完毕后,Angular 会寻找 ngApp 指令,这指定了应用程序的根目录。如果找到了 ngApp 指令,Angular 会加载与此指令关联的模块。
例如,在下面的代码中,Angular 会加载 "myApp" 模块:
<html ng-app='myApp'>
...
html> -
手动启动(Manual Bootstrap):在这种情况下,您不需要将 ngApp 指令附加到 HTML 元素上,而是调用
angular.bootstrap(document, ['myApp'])
函数。这允许您在 Angular 编译页面之前执行一些操作。例如:
<body>
<div ng-controller="myController"> Best movie: {{MovieName}}! div>
...
<script>
angular.element(document).ready(function() {
angular.bootstrap(document, ['myApp']);
});
script>
body>
注意:在手动启动 Angular 应用程序的情况下,不应该使用 ngApp 指令。
四十三、AngularJS 中的常量(Constants)是什么?
在 AngularJS 中,常量类似于服务,用于定义全局数据。常量使用 "constant" 关键字进行声明。
就像我们在 ASP.NET 应用程序的 Web.Config 文件中定义 app-keys,以便在整个应用程序中使用一样,我们可以在 AngularJS 中声明全局的常量数据,这些数据可以在整个应用程序中使用。
我们可以像依赖其他服务(例如 $http
)那样在控制器或服务中注入常量。AngularJS 使用单例结构来创建常量依赖。
因此,您可以创建一个 Config.js 文件,并在应用程序的任何地方注入它。
首先创建 Angular 模块:
var app = angular.module('ConstantApp', []);
然后,在 Config.js 文件中定义常量:
app.constant('config', {
appName: 'Constants',
appVersion: 2.0
});
现在,在控制器中使用上面定义的常量:
app.controller('mainController', function ($scope, config) {
$scope.ApplicationName = config.appName;
});
最后,在 HTML 视图中使用这个作用域:
<title>{{ApplicationName}}title>
总结:常量可用于多种用途。这篇博客只是关于常量的基本演示解释。
四十四、解释 AngularJS 中的 ngClick 和 ngDblclick 指令
AngularJS 提供了许多内置指令。在这里我们将讨论 ngClick 和 ngDblclick 指令。
ngClick
此指令允许我们在元素点击事件时定义自定义行为。此指令具有最高优先级。在表达式中,事件对象可以通过 $event
访问。
语法:
<ANY ELEMENT ng-click="expression">
...
ANY ELEMENT>
示例:
HTML
<h4>ngClick 示例h4>
<div ng-controller="HomeController">
<button ng-click="click()">点击这里button>
div>
控制器
var app = angular.module("app", []);
app.controller("HomeController", function($scope) {
$scope.click = function() {
alert('执行点击事件');
}
});
ngDblclick
此指令允许我们在元素双击事件时定义自定义行为。此指令具有最高优先级。在表达式中,事件对象可以通过 $event
访问。
语法:
<ANY ELEMENT ng-dblclick="expression">
...
ANY ELEMENT>
示例:
HTML
<h4>ngDblclick 示例h4>
<div ng-controller="HomeController">
<button ng-dblclick="dblclick()">双击这里button>
div>
控制器
var app = angular.module("app", []);
app.controller("HomeController", function($scope) {
$scope.dblclick = function() {
alert('执行双击事件');
}
});
四十五、AngularJS 中的一向数据绑定(One-Way Data Binding)是什么?
一向数据绑定意味着 HTML 元素反映了模型的变化。当模型值发生变化时,HTML 元素不会改变模型中的值。
换句话说,当模型变化时,这种变化会反映在视图上,但是视图不会改变模型。换句话说,开发者必须编写额外的代码来自动同步模型和视图组件之间的数据。一向绑定也可以称为单向绑定。
一向绑定示意图:
(图示说明了一向绑定的概念,但实际的图像需要查看相关资料获得)
让我们通过一个例子来理解:
代码
<input type="text" ng-model="message" />
<p>{{message}}p>
按下 F5 刷新页面
当您更改输入框中的文本时,
标签中的文本会随之更新。但如果试图直接更改
标签中的文本,AngularJS 不会检测到这种变化并将它反映到模型中。这就是一向数据绑定的行为。
四十六、AngularJS 中的一向数据绑定(One-Way Data Binding)是什么?
AngularJS 的核心特性之一是双向数据绑定(Two-Way Data Binding),这使得它非常流行。在双向数据绑定中,模型中的任何变化都会立即反映在视图中,视图中的任何变化也会更新模型。
然而,有时我们也需要使用一向数据绑定。一向数据绑定意味着数据从模型流向视图,但不能反过来。这意味着当模型改变时,视图会更新,但是视图中的改变不会影响模型。这种方式通常更高效并且有助于避免不必要的复杂性,尤其是在大型应用中。
示例:
html>
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<title>title>
<script src="Script/angular.js">script>
<script type="text/javascript">
var myApp = angular.module('myApp', [])
.controller('myController', function($scope) {
$scope.name = "Anoop";
});
script>
head>
<body ng-app="myApp">
<div ng-controller="myController">
Enter Name: <input type="text" ng-model="name" />
<p>Hello! {{name}}p>
div>
body>
html>
在这个例子中,当您更改输入框中的文本时,
标签中的文本会随之更新。但如果您尝试直接更改
标签中的文本,AngularJS 不会检测到这种变化并将它反映到模型中。这就是一向数据绑定的行为。
四十七、解释 AngularJS 中的 ng-hide 指令?
ng-hide 指令用于使 HTML 元素不可见。我们来看一个例子:
html>
<html ng-app>
<head>
<title>My Angular Apptitle>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js">script>
head>
<body>
<div ng-app="">
<p ng-hide="true">这段文字是不可见的。p>
<p ng-hide="false">这段文字是可见的。p>
div>
body>
html>
在上面的代码中,我们有两个
标签。其中一个标签上的 ng-hide 指令的值设置为 false
,另一个设置为 true
。设置为 false
的标签将显示,而设置为 true
的标签将隐藏。
四十八、AngularJS 中的动画元素是什么?
服务允许您在元素添加、移除或在中移动时提供过渡效果。animate服务允许您在元素添加、移除或在DOM中移动时提供过渡效果。animate 服务本身并不定义任何动画,而是依赖于 CSS3 的动画和过渡特性。动画可以有效地吸引用户的注意力,使应用状态之间的转换更加平滑。然而,动画应该保持简短、快速,并且谨慎使用。
定义和应用动画:
您不是直接使用 $animate 服务来应用动画,而是使用 CSS 定义动画或过渡,并遵循特定的命名约定,然后将这些名称作为类应用于带有 AngularJS 指令的元素。
支持动画的内置指令及其相关的名称如下:
指令 | 名称 |
---|---|
ng-repeat | enter, leave, move |
ng-view | enter, leave |
ng-include | enter, leave |
ng-switch | enter, leave |
ng-if | enter, leave |
ng-class | add, remove |
ng-show | add, remove |
ng-hide | add, remove |
四十九、AngularJS 中的 ngClass 指令是什么?
ngClass 指令允许我们根据 Angular 变量或评估后的表达式添加或删除 CSS 类,或者根据动态数据绑定一个或多个类。
关于 ngClass 的几点说明:
-
ngClass 指令动态地将一个或多个 CSS 类绑定到 HTML 元素。 -
ngClass 指令的值可以是一个字符串、一个对象或一个数组。 -
如果是一个字符串,它应该包含一个或多个以空格分隔的类名。 -
如果是一个对象,它应该包含键值对,其中键是一个布尔值,值是要添加的类名。只有当键设置为 true
时才会添加该类。
示例:
<div ng-class="{class1: expression1, class2: expression2}">
Hello World!
div>
<div ng-class="{'class1 class2': expression1}">
Hello World!
div>
五十、为什么在 AngularJS 中使用无作用域控制器(Scopeless Controller)?
有时控制器会因为使用 $scope
提供给视图数据和行为而变得复杂,在这种情况下,可以使用无作用域控制器。
但是,如果您已经完美地设计了您的 AngularJS 应用程序,那么就没有必要使用无作用域控制器。
创建无作用域控制器:
// angular module(app.js)
angular.module('myApp', []);
// Controller (homeController.js)
var app = angular.module("myApp");
app.controller("myController", function() {
this.title = '无作用域控制器测试';
this.name = 'Anupam';
this.sayHello = function() {
alert('Hello ' + this.name);
}
});
在这个例子中,使用 this
关键字而不是 $scope
来在控制器中添加数据和行为。
如何从控制器获取数据到视图:
html>
<html ng-app="myApp" ng-controller="myController as ctrl">
<head>
<script src="Scripts/angular.min.js">script>
<script src="app/app.js">script>
<script src="app/homeController.js">script>
<link href="Css/bootstrap.min.css" rel="stylesheet" />
<title>{{ctrl.title}}title>
head>
<body>
<nav role="navigation" class="navbar navbar-default">
<div class="navbar-header">
<a href="#" class="navbar-brand">{{ctrl.title}}a>
div>
nav>
<div class="container body-content">
<div class="col-md-6">
<div class="row">
<div class="well-lg">Hi {{ctrl.name}}div>
div>
<div class="row">
<div class="well-lg">
<input type="button" ng-click="ctrl.sayHello()" value="Say Hello" class="btn" />
div>
div>
div>
div>
body>
html>