其他框架-Angular

  • 时间:
  • 来源:新网

   

【1.5.8版本和1.6.2版本的区别】
1、$http
1.5.8之前 $http都是用success/error接收数据 1.6.2是通过then和catch控制成功和失败函数,并且返回值之前是直接拿到,1.6.2返回时一个新的对象,要通过params.data才能获取

t01dd6811033b021c6d.jpg

2、路由
href锚点由 #/index --> #!/index 多了一个!号,如果不想在每一个标签href都写!,要通过$locationProvider配置hashPrefix(\'\')前缀为空

3、跨域
要设置白名单,提前把你想要的跨域的域名填写到指定位置,设置白名单后就不需要callback参数的设置
eg:
白名单操作
app.config(\'$sceDelegateProvider\',[\'$sceDelegateProvider\', function(){

$sceDelegateProvider.resourceUrlWhiteList([\'self\', \'http://localhost/api/**\']);

}])


【AngulaarJS】(ng)
1、4个特性:MVC 模块化 自动化双向数据绑定 指令系统

2、所有需要ng管理的代码(容器)必须被包裹在一个ng-app指令的元素(Angular应用程序管理的边界)中,对包裹在内的ng指令进行分析和操作 ng-xxx属性称之为指令(directive)

3、模块化编程基本思想步骤(这里的步骤指的是单向绑定,即模型数据展示给视图)

(1)创建一个模块 var app = angular.module("模块名称","该模块依赖的其他模块名称(没有依赖就写"[]")");
(2)把模块名称赋值给ng-app(划分的边界)
(3)通过该模块创建出一个控制器(controller) app.controller("DemoController(控制器名称)",function($scope 该参数写死){$scope.user = {} ...})这里的$scope就是数据库,可以把里面的数据、行为暴露给视图
(4)把该控制器赋值给边界标签的 ng-controller

4、angular.module注意细节

**传入一个参数是获取模块(前提有这个模块)传入两个参数是创建模块,如果没有这个模块而且也没有填写第二个参数"[]"那么就会报错

【MVC】
1、只是一种应用程序的开发思想,不是设计模式

Model: 处理数据和业务逻辑
View: 以友好的方式向用户展示数据
控制器(Controller): 组织调度相应的处理模型(注:一个模型内可以有多个控制器,控制器之间不能嵌套)

【内置指令(指令系统)】
(基本)
1、ng-app 指定应用根元素,至少有一个(边界)
2、ng-controller 指定控制器
3、ng-model 视图层绑定数据给模型层(双向绑定的基础)
4、ng-init 初始化数据(当数据层没有数据传过来,默认用初始化数据值 eg: ng-init="name=\'zs\'");
5、ng-bind 绑定模型层的数据,这样避免在内容中 "{{}}" 这样格式先在页面出现一次,缺点:每次只能绑定一个数据 用法: ng-bind="name"
6、ng-bind-template 绑定模型层多个数据 用法 ng-bind-template="{{name}} {{age}}"

(常用)
7、ng-switch 处理类似tab栏的例子,接收数据属性,常与ng-switch-when使用,后者是指定属性值
8、ng-src 增强图片路径,不会出现裂图情况,因为ng-不是html原本属性
9、ng-href 增强地址
10、ng-class 控制类名(用法 ng-class="{类名: ture/false}")
11、ng-include 引入模板(在一个网站中引入多个html文件拼接在一个网站上,ng-include="\'index.html\'" (注意里面要加上单引号)必须要在服务器上才可以正常引入)
12、ng-disabled 表单禁用
13、ng-readonly 表单只读
14、ng-checked 单/复选框表单选中
15、ng-selected 下拉框表单选中
16、ng-click="click($event)" 这里的$event是ng提供的类似于鼠标事件中的e,传递参数

【ng-repeat的补充】
1、正常情况数组或者对象可以通过 no-repeat="key in property" 或者 no-repeat="(index, val) in property"在元素上进行迭代

但是遇到数组有重复的名字的时候,如[\'a\',\'b\',\'c\',\'a\']; 控制台就会出现重复元素的报错信息,解决办法no-repeat="key in property track by $index", track by是让数组都有一个不重复的值进行标记,后面跟随的$index只要是数组元素不重复的信息即可,如id,下标等标识

2、ES5新增的属性str.startsWith/endWith】
可以通过这样的写法得出元素开头的字符

eg: ng-repeat="name in arr track by $index" ng-class="{red: name.startsWith="a"}"; 这样就实现全部a开头的绑定red类名,可以实现查找字符查找数组内容

【ng-model的补充】
1、ng-model只能给表单元素(select)进行双向绑定,当给select标签通过ng-model绑定属性,那么select中的option中的value值会同步到ng-model绑定的属性上,这样就可通过同步的值去控制一些想要的效果

eg:

<select name="" id="" ng-model="style"> <option value="red">红色</option> <option value="green">绿色</option> </select> <div ng-class="style"></div> //当选择红色时,style的值就会等于red,那么ng-class的值也会变为red

【自定义指令】
1、通过模块对象的directive方法自定义指令

app.directive("temp", function(){
/*返回一个对象,这个对象就是自定义指定的相关内容*/
return {
restrict: "ECMA", //E: element元素 A: attribute属性 C:class类 M: mark replace必须为true
templateUrl: "./head.html", //template:’<ul><li>列表</li></ul>’ 或者 templateUrl: ‘./head.html’
replace: true //是否替换原有标签(指的是html标签)
}
})

注: 这里的E 指的是 <temp></temp>这样指定
A 指的是 <div temp></div>

【作用域】
1、angularJS作用域是通过html标签属性中的控制器进行嵌套,访问方式类似函数作用域访问方式

【管道符"|"】
1、在过滤器和正则表达式中都大量用到管道符概念,其作用是把管道符前面的结果,用后面的方式输出(及前方的输出结果为后者的输入)

【过滤器】(就是一个方法)
1作用:就是接收一个输入,通过某个规则进行处理.然后返回处理结果

2、eg:
<p>{{price|currency:\'¥\'}}</p> //默认 $20.00格式 冒号后面为参数,改变单位

<p>{{date |date:\'yyyy-MM-dd hh:mm:ss\'}}</p> //默认直接返回系统时间 冒号后面改变格式

<p>{{course|filter:\'s\'}}</p> //filter子串匹配 必须跟上参数去匹配数组中对应的字符是否有相应的参数字符

<p>{{student2|filter:{age:80}|json}}</p> //json转换json格式

<p>{{student2|limitTo:-1}}</p> //limitTo限制个数,后面必须跟参数,可以接受负值由后往前找

<p>{{str|uppercase}}</p> //全变大写

<p>{{str2|lowercase}}</p> //全变小写

<p>{{num|number}}</p> //字符数字转变成num,不接收有非数字情况 parseInt 遇到字符就终止转换后续

<p>{{student|orderBy:\'age\':false}}</p> //orderBy排序 true 降序 false 生序


【自定义过滤器】
1、由于过滤器是一个方法,所以需要返回一个方法,并且传入一个参数(管道符前面的属性)

app.filter("firstUppcase", function(){ return function(input){ return input[0].toUpperCase() + input.slice(1); } })

【依赖注入】
1、是不是留意过angular.module("app", []) 或者自定义控制器时也有这样写法,这里的"[]"就是指该模块或者控制器需要依赖的服务是什么

2、依赖注入分为
行内注入(开发推荐使用): app.controller("Controller2", ["$scope", "$http", function($scope, $http){...}])

推断注入(不推荐): app.controller("Controller2", function($scope, $http){...})

这里的参数是ng提供的通过自身寻找ng是否存在这种服务的一种方法

缺点:在代码进行压缩的时候,函数的参数可能会被压缩成a,b,但用行内注入,后面跟上是一个数组,代码压缩过程不会把数组内容进行压缩

【服务】
1、常见内置服务

$location 地址栏
$timeout $interval 定时器服务
$filter 过滤器服务(不要在视图直接用过滤器处理数据)--> $filter(\'uppercase\')
$log 控制台服务
$http 网络服务


【$location服务】
1、就是对window.location里面的方法进行封装

$localtion.ablUrl() 获取绝对路径
$localtion.url() 获取锚点后面的url
$localtion.protocol() 获取协议
$localtion.port() 端口
$localtion.path() 当前路径
$localtion.hash 获取hash值(就是锚点后面的锚点)
$localtion.search 查询字符串(就是?后面的参数)转换成对象

【定时器服务】($timeout,$interval)
1、写法
$timeout(function(){},time) $interval同理

2、内置方法
$timeout.cancel(timer) 清除定时器 timer指要清除的定时器


【$http服务】(仿ajax和跨域)
1、格式(success/error位置与ajax不一样)2、AJAX格式

$http({ url:"./mphp.php", //请求地址 method:"get/post", params/data:{name:"xmg", age:"10"}, //当请求方式为post,请求头格式改用form提交,参数提交方式 data:"name=xmg&&age=10",原因是ng默认没有把 //form格式(SOAP对象形式传递)转换成标准json数据传递(RESTFUL(json串格式)) header:{‘Content-Type’: ‘application/x-www-form-urlencoded’ }, //使用post传递数据要设置请求头 }).success(function(){ }).error(function(){})

3、jsonp格式

$http({ url:url, method:"jsonp", params:{ callBack:\'JSON_CALLBACK\' } }).success(function (res) { alert(res); }).error(function(res){ console.log(res); });

注意事项:
a、当使用jsonp 并传入参数时。内部会帮你做一些处理
b、帮你自动创建一个function 名称是ng它自动帮你取的一个名称。angular_callback_.0
c、会帮你创建一个script标签 src="http://localhost/day5/jsonp.php?callBack=angular_callback_.0"
d、请示完毕时,执行完毕时,会把结果。给success之后,自动删除创建的标签跟函数

【当访问的地址没有处理跨域问题】
1.思路
$http->url没有帮处理跨域。
$http->php->url
php->$http

解释:
通过访问本地的PHP文件再去访问外域地址,因为解决跨域必须要通过后台服务器处理,所以要借助本地的PHP去处理跨域问题
a、创建本地PHP文件,通过file_get_contents("外域地址");访问,(原因后台没有跨域问题)
b、PHP文件返回访问回来的数据给前台
c、前台通过ajax请求访问本地的PHP文件回来的数据


【$watch】(三个参数,第三个参数是true/false,当第一个参数是监听对象发生作用)
0、当第一个参数是监听对象,那么监听的一直是一个地址,无论值是否改变,都不会更新新值旧值,如果想监听对象中值得变化,就要在第三个值填true

1、$watch是一个scope的函数,用于监听模型(ng-model)变化,当你的模型部分发生变化时它会通知你

function的参数now和old是改变后的值和改变前的值,通过监听这两个值得变化可以很好的做一些时刻改变的页面

2、用法: $scope.$watch("username", function(now, old){...}); 这里的username就是ng-model监听的值

3、性能问题
太多的$watch将会导致性能问题,$watch如果不再使用,我们最好将其释放掉。

$watch函数返回一个注销监听的函数,如果我们想监控一个属性,然后在稍后注销它,可以使用下面的方式:

var watch = $scope.$watch(\'someModel.someProperty\', callback); watch(); //执行返回的函数取消监视


【自定义服务】(一般用第二种方式service)
1、factory

app.factory(\'formatePar\',[\'\',function(){return}]);

2、service

app.service(\'formatePar\',[\'\',function(){this.fun = ...}]);

3、value(相当于全局定义常量)

app.value(\'version\',\'1.0\');

【配置块】
1、在每一个服务当中都会有一个provider来对指定的功能进行配置,改变一些系统的默认行为。

2、用法config() --> 直接在对应服务后面加Provider eg: $filterProvider

app.config([\'$logProvider\',function ($logProvider) { $logProvider.debugEnabled(false); }]);

【运行块】
1、一进入ng解析阶段,程序一进来就会执行

2、用法run() ($rootScope为跟作用域,类似在view层的ng-init)

app.run([\'$http\',\'$rootScope\',function ($http,$rootScope){...})


【hashchange】
1、window自带监测地址栏锚点的变化情况

【锚点后面地址更新不刷新原理】

http://runoob.com/#/first http://runoob.com/#/second http://runoob.com/#/third

1、当我们点击以上的任意一个链接时,向服务端请的地址都是一样的 (http://runoob.com/)。 因为 # 号之后的内容在向服务端请求时会被浏览器忽略掉。所以我们就需要在客户端实现 # 号后面内容的功能实现。

【路由】(在1.2版本之后很多功能独立出来包括路由)
0、API:$routeProvider.when(\'/index/:id\') (控制锚点参数更换模板,冒号后面为参数固定格式)
$routeParams (获取锚点后面的参数,要通过注入控制器)

1、在angular当中路由就是锚点用来做单页面应用程序的切换。锚点的变化,我们又称为路由的变化。

2、用路由做单页面的基本操作

a、在创建模块时,注入路由模块
var app = angular.module(\'app\',[\'ngRoute\']);

b、配置路由

app.config([\'$routeProvider\',function ($routeProvider) { /*当锚点为指定值时, 帮你处理相应的逻辑 * 路由规定,在路径之前, 加上一个"/" * */ $routeProvider.when(\'/index\',{ template:"<h1>首页</h1>" }) .when(\'/music\',{ template:"<h1>音乐</h1>" }) .when(\'/singer\',{ template:"<h1>首页</h1>" }).otherwise({ redirectTo:\'/index\' }) }]);

c、在view层通过ng-view设置占位符:把模板放到哪个位置

<div class="content" ng-view></div>


【SPA和tab栏的区别】
0、尽管都是无刷新更新页面,但运行机理不同

1、tab栏是把所有的内容固定在dom树上(同步冗余)

SPA是通过异步获取数据添加到对应的节点上

【修饰符\'@\'和修饰符\'=\'】
1、在自定义指令当中,通过scope属性中的对象暴露出一个接口让外界的父级控制器可以传入一个常量或者变量进行控制子级的变量
用法:
scope:{
子级的变量名: "@暴露给外界的名字"
}

<body ng-app="app" ng-controller="xmgController"> <input type="text" ng-model="name"> <div tag msg="{{name}}"></div> //这里的tag就是子级控制器控制范围,msg就是暴露出来的接口 </body>

2、为什么要暴露接口?
答:其实不暴露接口子级可以控制父级,父级也可以控制子级的变量,但是这样只能通过父子级相同属性名才可以控制,而通过修饰符的方法暴露一个接口,就可以灵活的让不同父级控制器去控制子级的属性,而不必要全部相同的属性名(父级只要通过接口传递即可),做法更灵活

3、\'@\'、\'=\'的区别?
答:\'@\'只能通过父级传递数据给子级呈现,属于单向传递, 而\'=\'属于双向传递,谁修改属性都会互相影响


【广播】(查NG参考手册)
1、通过指令父级呼唤子级干事,或者子级呼唤父级干事

2、发送广播时,一定要等指令加载完毕之后,才去发送广播


【$q服务】(有类似回调,查NG参考手册)
1、用于创建延时任务


【PhpStrome】
1、类似WebStrome,但内置php服务器,可以直接打开Php文件进行访问,前提要配置php服务

【PHP基本写法】

$_GET[\'name\']; //接收get请求过来的name
$_POST[\'name\']; //接收post请求过来的name
echo //输出

$array = [\'name\'=>\'xmg\',\'age\'=>10]; //PHP写json写法
json_encode($array); //转成标准json格式
file_get_contents("file.json") //PHP接收json文件(拿外域地址数据)

echo $fn."()"; //$fn为前端传过来的函数体,通过PHP语法.拼接括号才能进行调用

 

【用ng配合gulp完成的项目webApp注意点】(模块化开发体验)

零、移动端刷新】
1、ctrl+r 强刷新

一、rem操作】
0、添加<meta name="viewport" content="width=device-width maximum-scale=1.0 minimum-scale=1.0 user-scalable=no">

1、修改视口比例需要在js代码中添加

var font = window.screen.width / 20 + "px"; //获取不同窗口的宽度,取20的比例
document.getElementsByTagName("html")[0].style.fontSize = font; //把比例赋值给html根标签

二、像素转为rem格式】
0、一般引入一个把所用到rem的地方都定义的类,在index.less中通过 @import \'url.less\'引入

1、unit指把数值以什么单位输出,用法unit(5,rem) --> 5rem

/*把像素转成rem*/
.fs(@px){
font-size: unit(@px/37.5,rem);
}

三、src的js文件夹】
1、一般定义config、controller、directive、service四个文件夹去存放对应的函数,在问最外层创建app.js定义模块

四、src中的view文件夹】
1、把每一个整体的页面分拆成一个个小的零件,如头部有专门的只负责传文字数据,有专门的模板去展示

五、自定义指令注意事项】
1、app.directive(\'listView\', function(){...})

--> 在html定义的属性或者标签名字为list-view才生效

六、应用程序可扩展性】(应用场景$http)(httpTool.js)
1、原因:自己的项目不能由第三方插件牵着走,当第三方插件有一些关键地方有作更新的时候,我们自己的项目很多地方就会要重新修改,如1.5.2版本的$http,success/error改为then/catch,当你的项目有100个地方用到网络请求的时候你就要改100个地方,程序可扩展性低

2、做法:利用angular提供给我们的自定义服务,自定义一个自己的网络请求服务,尽管第三方插件改动了一些关键地方,你只要修改你自定义服务里面的一个地方即可对整个项目进行修改

七、ui.router注意地方】
1、在模板位置添加ui-sref指定路由名称相当于定义锚点

2、当要改变选中路由的样式用ui-sref-active="类名";这个属性去控制

八、获取头部信息用参数$attr.nav】
1、在html nav="内容"设置标签和内容,在自定义指令通过link: function($scope,$jqLite,$attrs){console.log($attr.nav)} //获取内容,达到解耦合操作

九、子页面返回主页面再次请求数据问题】(不能返回就重复请求相同数据)
1、解决办法: ui.router的子路由方法,

a、在主页面显示主路由通过<div ui-view></div>接收4个页面模板

b、4个页面模板中接收内容数据的地方在设置一个<div ui-view></div>去接收list-view模板还是detail模板

b处这样做的原因:正常思路设置这样一个路由会导致主页面<div ui-view></div>对这两个路由进行来回切换,一旦切换后就会把其控制器和模板一并覆盖,导致每次返回都会重新获取一次数据

$stateProvider.state(\'home\',{
url:\'/home\',
templateUrl:"../view/home_tpl.html",
controller:"homeController"
}).state(\'detail\',{
url:\'/detail/:id\',
template:"../view/template/detail_tpl.html",
controller:"detailController"
});

c、设置路由(设置命名空间管理子路由home.list、home.detail)

$stateProvider.state(\'home\',{
url:\'/home\',
templateUrl:"../view/home_tpl.html",
controller:"homeController"
}).state(\'home.list\',{
url:\'/list\',
template:"<div list-view></div>", //由于home_tpl模板已经用<div ui-view></div>子路由占位,只能通过这样去添加到子路由上显示
controller:"homeController"
}).state(\'home.detail\',{
url:\'/detail/:id\',
templateUrl:\'../view/template/detail_tpl.html\',
controller:"detailController"
})
$urlRouterProvider.otherwise(\'home\');

d、在homeController添加$state.go(\'home.list\');
原因:在加载子路由模板第一个路由指向是列表,所以要在对应控制器中指向home.list列表的命名空间第一次跳转

十、控制jsonp白名单sce】
1、有时候跨域拿数据,后台会返回err信息,信息内容Error: [$sce:insecurl] ,这是ng的$http跨域拿数据时候$sce要设置可信任的网站才允许访问

2、操作

angular.module(\'app\')
.config([\'$sceDelegateProvider\',function ($sceDelegateProvider) {

$sceDelegateProvider.resourceUrlWhitelist([
\'self\', //自身必写
\'http://localhost/api/**\' //需要跨域的网址
]);

}]);

十一、切换路由控制器也会切换,但定义的$scope.dataList的属性还是继续保留】
1、$scope.dataList得到的后台数据可以继续再点击其他路由继续使用

十二、数据返回详情页content数据为标签】(绕)
1、数据返回详情页content数据为标签格式,所以不能直接通过ng-bind绑定,要通过创建自定义标签detail,在自定义标签link方法中jq操作获取内容,其内容通过html标签传来的属性detail="{{detailData}}"中获取,这里的detailData是后台$scope.detailData定义的