AngularJS基础语法(2009版本)

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 参考手册 | 菜鸟教程

上面的地址涵盖了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(){...修改值操作});

  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值