jquery和AngularJS 数据绑定和获取对比:
jquery,要操作DOM:
angularJS,无需操作DOM就可以进行动态数据变化:
要使用Angularjs就需要在html页面先引入:
ng-app:
html页面中,需要给标签绑定ng-app指令标记当前页面,注意ng-app通常绑定给body标签。
如果ng-app="" ,可以默认写为ng-app
只有给html绑定了ng-app,才会产生$rootScope。
如果不给页面body绑定ng-app指令,那么在view视图中{{}}就无法生效,页面直接显示为{{}}字符。
ng-model:
语句和表达式的区别:
ng-init:
用来初始化当前作用域变量
ng-init是单向数据绑定,由页面view->模型model;
ng-model是双向数据绑定,页面view->模型model ,也可以从模型model->页面view
双向数据绑定:
作用域对象和控制器对象:
给html绑定ng-app指令,会生成最顶层的$rootScope作用域对象。
给单独的标签添加ng-controller绑定一个函数,ng-controller指令会自动new此函数。这个函数会接收一个形参必须是$scope,在这个函数中就可以对ng-controller定义区域内的变量进行变量初始化和创建方法,产生一个单独的作用域空间。注意必须使用$scope初始化变量和创建方法。
所以控制器函数的形参一定是$scope。
总结:
ng-app会创建一个根作用域对象$rootScope,通过ng-init初始化全局变量。
ng-controller会创建控制器对象例如MyController,生成一个单独的作用域空间$scope,$scope是在$rootScope下的,在ng-controller控制的view视图内,可以直接调用ng-init初始化的变量。
例如:在$rootScope全局作用域下初始化age变量:
在控制器对象MyController区域view视图内直接调用age
ng-app和ng-controller也可以写在一个标签上
依赖注入:
依赖注入分为声明式依赖注入和命令式依赖注入,首先理解一下声明式和命令式的区别:
声明式依赖注入:
event就是依赖,同理控制器中的$scope也是依赖;
这种以形参的形式被注入使用的方式就是声明式依赖注入
命令式依赖注入:
AngularJS的模块对象
在angular中,像下面这种生成MyController生成控制器对象这种方式不多,更多的是使用Angular的模块对象angular.module.controller()更方便。
angular.module模块可在全局位置创建、注册、获取Angular模块。所有模块(angular核心或第三方)都必须使用这个机制注册才能在应用中生效。
一个模块式服务、指令、控制器、过滤器和配置信息的集合。angular.module用于配置injector。
首先想使用angular,就需要先引入:
书写视图:
JS:
视图中的ng-app绑定的名称就是模块的名字
生成作用域对象代码优化:
链式调用:
再次优化:
注意:
表达式:
常用指令:
ng-repeat:
ng-repeat的$index输出数组的下标;
ng-repeat的$first输出当前元素是否是第一项,输出布尔值;
ng-repeat的$last输出当前元素是否是最后一项,输出布尔值;
ng-repeat的$middle输出当前元素是否属于中间项,输出布尔值;
ng-repeat的$odd输出当前元素下标是否属于奇数,输出布尔值;
ng-repeat的$even输出当前元素下标是否属于偶数,输出布尔值;
遍历数组显示数据,数组有几个元素就会产生几个新的作用域,见下图验证:
ng-bind:
ng-show、ng-hide:
ng-style:
ng-mouseenter、ng-mouseleave:
ng-class:
需求:循环ul标签,各行变色
AngularJS内置服务 $http:
遍历动态生成表格:
angular的过滤器filter
参考:AngularJS 过滤器 (详解)_angularjs过滤器-CSDN博客
过滤器作用:将数据转换成自己想要的形式后输出,格式化数据;
过滤器写法:待处理数据 | 过滤器名称:参数
angular内置过滤器:
currency :"货币"
例如:
date : "日期格式字符串"
例如:
tip: 过滤器可以链式调用
uppercase
将字符串text大写输出
filter
filter第一个参数可以是下列三种类型,第二个参数为true的时候顺序反转。
等等......
详细可以看上面的参考链接,博主很详细。
自定义过滤器:
如果内置的过滤器无法满足自己的需求,就可以自定义过滤器。
需求:将手机号码中间4位用型号表示:
js:
自定义过滤器写法:
angular.moudule('ng-app绑定的名称',[]).filter("过滤器名称",回调(return回调))
view:
优化:
无论号码多长,只保留前三位和后四位,中间使用*隐藏
angularJS的指令:
上面的地址涵盖了angularJS的所有内置指令
ng-src:
如果直接给src绑定{{a}},后台会报错
如果使用ng-src就不会报错 。<img ng-src="{{a}}"
ng-cloak:
没加载之前先隐藏,在网速慢的时候,变量还未渲染时,不会显示{{}}空的字符串,而是这个div直接不显示
ng-href:
为防止页面还没有加载完毕时,客户五点了a标签却没有任何响应的问题
ng-switch
ng-bind-html 和 ng-bind的区别:
ng-bind 和 ng-bind-template:
使用ng-bind-template就可以输出
ng-include:
ng-options:
先来看使用普通方法ng-repeat渲染下拉:
再通过使用ng-options渲染下拉:
ng-options替你组织options
1、必须有ng-model
2、值 as 文字 for item in arr
ng-options使用升级:
select下拉分组,group by xxx
自定义指令directives:
先看angular1.5之前,使用自定义指令directive来写子组件:
注意:
如果自定义指令名称包含大写字母, 比如写成frankButton,那么在引用自定义指令是,要写成小写并加-。见下:所以自定义指令名称经常使用驼峰命名法
注意:通过templateUrl引入的页面,页面内只能有一个根元素,否则会报错。
自定义指令templateUrl引用的页面只能有一个根元素
如果有多个根元素,会报以下错误:
templateUrl引用的地址也可以写成这样,引入的文件通过给script标签设置type="text/ng-template" id="xx",自定义指令时templateUrl直接引用 id绑定的名称。
代码验证:
自定义指令作为属性使用:
replace设为true时,后台html显示:
replace设为false时,后台html显示:
自定义指令作为元素标签直接使用:
自定义指令作为类名使用:
自定义指令作为注释使用:
使用时指令前面要加directive:
自定义指令的transclude属性:当我们给元素添加自定义属性时,显示自定义属性templateUrl引用的页面的同事,保留被添加自定义指令页面与哪有的内容。
自定义指令的controller:
用来定义自定义属性templateUrl或template引入的html页面中使用到的属性和方法:
例如:
例如:
自定义指令的scope:
scope默认为false,表示父子公用一个作用域,当在自定义的子组件"myDirect"的controller中输出$scope时是会包含上级父元素"myCtrl"里的变量方法的,见下:
scope属性默认为false时,父子组件公用一个作用域
当scope为false,即父子公用作用域,并且父子组件中有相同的组件变量A,子组件的A的值会覆盖父组件的这个变量A的值
当scope属性为true时:,父子组件作用域独立,防止数据源污染,
问题,父子作用域独立是,子组件中如何使用父组件内的变量和方法呢?
此时scope属性还可以是一个对象,当scope是一个对象的时候,可以存在如下三种方式访问子组件、访问父组件的方式。
自定义指令的link和compile:
compile:
link:
在指令中操作DOM,我们需要link参数。
link的3个参数:
link函数的第一个参数scope可以访问到自定义指令中controller中定义的属性和方法。
在link中可以通过scope.$root访问$rootScope作用域内的变量和方法。
自定义指令的controllerAs,主要是重命名在link函数中作为参数可以访问到:
再来看angularJS1.5版本之后,创建子组件的方式:
写法:
angular.module.component('驼峰式组件名',{
template:"<div></div>", //也可以使用引入的方式templateUrl
controller:function($scope){...}
})
页面引用:
这里因为再子组件myComp没找到变量msg,所以没有输出,如果想要访问父组件的变量,那么子组件的controller函数就要引入$rootScope变量:
也可以使用factory来存储公共变量:
系统服务$http:
get请求:
post请求:
angularJS的监听服务:
AngularJS的自定义服务
value、constant、factory、service、provider服务创建的变量在控制器中使用时要注入,并且不要带$。
value服务:
举例:让两个控制器实现变量数据交流
html部分:
JS部分:
constant服务:
factory服务:
是通过回调函数返回一个对象的方法去声明全局变量
service和provider服务:(最常使用)
如果在service服务内部不通过this来创建变量,那么在控制器中使用时是访问不到这个变量的,输出为undefined。
在上面的代码中,如果就想在控制器中使用secret变量,那么在service服务中,可以通过“特权函数(get获取函数)”来将这个secret变量return抛出,那么在控制器中就可以通过特权函数访问到这个变量了。
如果想在外部对service内部的私有变量进行改变,也可以给特权函数传值(set修改函数)进行修改:
provider服务:
provider服务的回调函数内部通过this.$get = 回调,在回调内返回对象的方式创建全局变量。
那么如何验证以下这点呢?在控制器中不引入provider全局变量时,如何验证provider是已经存在了的。
控制器中不引入provider服务变量,而是在provider回调函数中,直接打印,看控制台是否输出即可知道provider服务是否是一直存在的,而非注入才存在:
子组件使用父组件的变量(双向数据绑定)
自定义指令的scope为对象,不继承外层的scope,新建的scope是独立的,与外层scope隔离。自定义指令scope需要通信时,可以通过传递属性名映射的方式把父scope中指定的属性传递给这个独立的scope。
绑定策略:
@:
单项文本绑定,传递一个字符串值,传递的数据类型只能是字符串。当父作用域属性改变时,隔离的scope中的属性值随着变化;当隔离的scope中的属性值改变时,副作用域的属性值不随着变化(父变子变,子变父不变)
=:
双向绑定,传递父作用域的一个属性,传递的数据类型可以是字符串、数组、对象等。当父作用域属性改变时,隔离的scope中的属性值随着变化;当隔离的scope中的属性值改变时,父作用域的属性值也随着变化(父变子变,子变父变)
&:
执行父作用域中的函数。
举例①:
举例②:
父组件acceptImageStatistics的html、js部分,以及子组件使用了父组件的变量;
子组件acceptImgSelect的html、js部分,对父组件的变量进行使用、绑定、修改(双向数据绑定)
如果scope对象里的属性是驼峰写法,那么在实际使用时要使用- 分隔使用:
$scope.$apply():用来更新绑定的数据
https://www.cnblogs.com/actiondream/p/8046736.html
什么时候手动调用$apply()方法?
如果AngularJS总是将我们的代码wrap到一个function中并传入$apply(),以此来开始一轮$digest循环,那么什么时候才需要我们手动地调用$apply()方法呢?实际上,AngularJS对此有着非常明确的要求,就是它只负责对发生于AngularJS上下文环境中的变更会做出自动地响应(即,在$apply()方法中发生的对于models的更改)。AngularJS的built-in指令就是这样做的,所以任何的model变更都会被反映到view中。但是,如果你在AngularJS上下文之外的任何地方修改了model,那么你就需要通过手动调用$apply()来通知AngularJS。这就像告诉AngularJS,你修改了一些models,希望AngularJS帮你触发watchers来做出正确的响应。
比如,如果你使用了JavaScript中的setTimeout()来更新一个scope model,那么AngularJS就没有办法知道你更改了什么。这种情况下,调用$apply()就是你的责任了,通过调用它来触发一轮$digest循环。类似地,如果你有一个指令用来设置一个DOM事件listener并且在该listener中修改了一些models,那么你也需要通过手动调用$apply()来确保变更会被正确的反映到view中。
让我们来看一个例子。假如你有一个页面,一旦该页面加载完毕了,你希望在两秒钟之后显示一条信息。你的实现可能是下面这个样子的:
通过运行这个例子,你会看到过了两秒钟之后,控制台确实会显示出已经更新的model,然而,view并没有更新。原因也许你已经知道了,就是我们忘了调用$apply()方法。因此,我们需要修改getMessage(),如下所示:
如果你运行了上面的例子,你会看到view在两秒钟之后也会更新。唯一的变化是我们的代码现在被wrapped到了$scope.$apply()中,它会自动触发$rootScope.$digest(),从而让watchers被触发用以更新view。
Note:顺便提一下,你应该使用$timeout service来代替setTimeout(),因为前者会帮你调用$apply(),让你不需要手动地调用它。
而且,注意在以上的代码中你也可以在修改了model之后手动调用没有参数的$apply(),就像下面这样:
以上的代码使用了$apply()的第二种形式,也就是没有参数的形式。需要记住的是你总是应该使用接受一个function作为参数的$apply()方法。这是因为当你传入一个function到$apply()中的时候,这个function会被包装到一个try…catch块中,所以一旦有异常发生,该异常会被$exceptionHandler service处理。
总结:
$scope.$apply有两种使用方式:
①:$scope.$apply() 修改值后直接调用;
②:$scope.$apply(function(){...修改值操作});