Angular的学习

  • Angular的特性.
  • MVC : 在前端引入了MVC的设计模式
  • 模块化开发
  • 自动的双向数据绑定
    *语义化标签(自定义标签)
  • 依赖注入
  • 其核心就是通过指令扩展了HTML,通过表达式绑定数据到HTML
  • Angular不推崇DOM操作
  • ng最主要是用来实现spa应用 - SPA (单页面应用程序)

我们了解了Angular的特性,再来着手学习可能会对这些特性有更深刻的体会

MVC设计模式

1.现实生活中的MVC

  • 现实生活中的分工合作案例 – 大饭店

    • 采购:负责原材料采购.
    • 小工: 打杂,洗菜,洗碗.
    • 厨师: 切菜 炒菜
    • 服务员:端菜 迎宾
    • 收银员: 收钱.
    • 采购:指挥协调其它人员工作.
  • 在一些街边小饭馆其实这些事情完全是交给一个人去做 –> 老板

    • 所有的事情都是这1个人去做.
  • 对比一下这两种经营方式的区别

    • 大饭店: 正规,分工合作,各司其职,效率高.
    • 小饭馆: 不正规,慌乱.效率低下.
  • 同样的事情两种实现方式

    • 都是将客人点的菜展示到餐桌上.
    • 不同的单位使用了不同的流程.
    • 大饭店: 每个人负责1个流程.高效并且可维护程度极高. 挂了1个 人,不影响其它人.只换这1个人就可以.
    • 小饭馆: 1个人负责整个流程,效率低下并且可维护程度极低,老板挂了,饭馆就得关门.
      由此可见,分工是多么的重要
    1. 代码中的MVC

      • 实际上,我们写网站的过程,和开饭店的原理和流程极其相似,我们写网站是将数据展示到页面上.

      • 目前,我们写代码都是一股脑的将所有的代码写在一起,这样去写固然没有什么问题,因为你终究还是将效果实现了.

      • 但是这样做的后果是可怕的,随着项目越来越大,你的代码将变得非常难以维护.

  • 为了让我们的代码更加容易的维护,也为了使得我们的代码层次更加分明

  • 我们将我们的代码分为三部分

    • M - Model 数据 数据实体,用来保存页面要展示的数据.
    • V - View 视图 负责显示数据的,一般其实就是指的html页面.
    • C - Controller 控制器 控制整个业务逻辑,负责处理数据,比如数据的获取,以及数据的过滤,进而影响数据在视图上的展示.
      这样,这3部分各司其职,分工合作,我们的代码就会变得更有层次并容易维护.
      这样的程序设计模式,我们就叫做MVC设计模式.
  • MVC是由后端而来,由于受到前端技术的限制便有了一些细节的调整,

  • 进而出现了很多MVC的衍生版(子集)如MVVM、MVW、MVP、MV*等。

模块化

  1. 使用AngularJS构建应用(App)时是以模块化(Module)的方式组织的,即将整个应用划分成若干模块,每个模块都有各自的职责,最终组合成一个整体。

  2. 采用模块化的组织方式,可以最大程度的实现代码的复用,可以像搭积木一样进行开发。

1. 定义应用

通过为任一HTML标签添加ng-app属性,可以指定一个应用,表示此标签所包裹的内容都属于应用(App)的一部分。通俗的理解就是: ng-app属性标签被Angular管理,包括其中的子标签.Angular会认为这是一个应用,将其作为一个应用来看待。

2. 定义模块

AngularJS提供了一个全局对象angular,调用该全局对象的module()方法可以创建一个模块.该方法返回一个模块对象.这个模块对象就是AngularJS用来管理应用的对象.
<!DOCTYPE html><!--为html标签定义ng-app属性 代表整个文档都被ng管理--><html lang="en" ng-app="myApp"><head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.js"></script></head><body><script>//调用全局对象angular的module方法创建一个模块.//第一个参数: 模块要管理的标签范围,写上ng-app属性的值.//第二个参数: 模块依赖,数组,如果不需要依赖,就直接写一个空数组就可以.//返回值:返回的app对象,我们可以认为这个对象就是ng用来管理这个模块的.var app = angular.module('myApp',[])</script></body></html>

### 3. 定义控制器 接下来我们可以通过app模块对象来创建控制器. 调用app模块对象的controller方法,就可以创建控制器.

var app = angular.module('myApp',[])//调用app的controller方法创建控制器.//第一个参数: 要将创建的控制器关联到指定的View上,字符串.//第二个参数: 这是一个数组,数组的其中一个元素是'$scope',//     数组的最后一个元素必须是1个function 参数是$scope//      先把$scope写死,后面学了服务就知道$scopeapp.controller('demoCtrl',['$scope',function ($scope) {}]);
  • 但是这个时候,我们只是创建了控制器,并没有将控制器和视图关联起来.
  • 视图是用来负责显示数据的,控制器是来处理数据模型,并将数据模型给视图展示.
  • 视图就是我们的html页面. 所以我们可以指定1个html元素(视图)与这个控制器相关联.
    为这个html元素指定1个ng-controller属性.值为创建controller的第1个参数的值.
<div ng-controller="demoCtrl"> <!-- 这个时候,创建的控制器,就与这个视图关联起来了. --><dl><dt></dt><dd></dd></dl></div>

* 这个时候,创建的控制器,就与这个视图关联起来了 * 在控制器中就可以处理制造数据.视图中就可以显示模型数据了.

数据模型

控制器负责处理制造模型数据.
视图负责显示控制器制造的模型数据.
那么控制器如何制造数据呢?

  app.controller('demoCtrl',['$scope',function ($scope) {//我们可以认为,$scope就是一个数据模型.//这是一个对象,//这个对象可以在控制器中访问,也可以在与控制器关联的视图中直接访问.//那么这个时候,控制器中可以将制造的数据放在这个$scope对象中.$scope.name = '小明';$scope.info = '我的名字叫小明,今年18岁';}]);

这个时候,控制器已经负责将数据模型构建完毕,那么视图中如何展示这些数据呢?

<!--这个视图与我们创建的控制器相关联,在这个视图中,可以直接访问与之相关联的控制器构建的$scope对象,需要注意的是:在视图中,如果要绑定显示$scope对象中的数据的值a. 使用 {{}} 符号b. 在这其中直接写上$scope对象中的数据的值{{name}} 不需要写$scope.name而是直接写namec. 这样在ng渲染的时候,就会将{{name}}显示成$scope.name的值<div ng-controller="demoCtrl"><dl><dt>{{name}}</dt><dd>{{info}}</dd></dl><div>-->

最后,视图中就显示出来数据了

Angular的基本结构

  • Angular的基本结构和工作流程

    1. 指定Angular管理的范围 ng-app
    2. 创建模块 angular.module()
    3. 创建角色

      • 3.1 创建控制器 app.controller()
      • 3.2 指定与控制器关联的视图 ng-controller
    4. 控制器制造数据模型并附到 scope scope scope.xx = yy;

    5. 在视图中显示模型数据 {{}}

下面举个例子来对Angular的结构有更清晰的认知

<!DOCTYPE html>
<!-- 1.指定整个html文档都被ng管理-->
<html lang="en" ng-app="ngApp">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.js"></script></head>
<body><!-- 将视图与控制器相关联 --><table ng-controller="stuList"><tr><td>编号</td><td>姓名</td><td>性别</td><td>年龄</td></tr><tr ng-repeat="stu in students"><!-- 遍历数组,并循环生成html --><td>{{stu.id}}</td><td>{{stu.name}}</td><td>{{stu.gender}}</td><td>{{stu.age}}</td></tr></table>
<script>//2.创建模块var app = angular.module('ngApp',[]);//3.创建MVC角色. 控制器,视图app.controller('stuList',['$scope',function ($scope) {//制造数据模型,并绑定到$scope中.$scope.students = [{id:1,name:'小明',gender:'男',age:18},{id:2,name:'小花',gender:'女',age:16},{id:3,name:'小强',gender:'男',age:14},{id:4,name:'小东',gender:'男',age:19},{id:5,name:'小常',gender:'女',age:20}];}]);
</script>
</body>
</html>

Angular指令

  • HTML在构建应用(App)时存在诸多不足之处
  • AngularJS通过扩展一系列的HTML属性或标签来弥补这些缺陷
  • 所谓指令就是AngularJS自定义的HTML属性或标签
  • 这些指令都是以ng-做为前缀的,例如ng-app、ng-controller、ng-repeat等

1. 内置指令

  • ng-app 指定应用根元素 也就是ng管理的范围.可以使用全局对象angular的module方法根据该属性的值创建模块对象.
  • ng-controller 指定与控制器关联的视图.
  • ng-show 控制元素及其子元素是否显示 true->显示 false->不显示
  • ng-hide 控制元素及其子元素是否隐藏 true->隐藏 false->不隐藏
  • ng-if 控制元素及其子元素是否创建 true->创建 false->删除.
  • ng-src 增强图片路径. src=”“虽然能显示,但是会报错.报错的原因.
  • ng-href 增强href路径
  • ng-class 值为对象 {red:true} 表示会添加1个red类名到元素身上. {red:false}不会将red类名添加到元素身上.
  • ng-include 将外部文件包含进来.一般用在页面的公共部分.被请求的页面是以ajax的方式请求的. ng-inlcude=“‘path’”需要注意的是,给该属性赋值的时候,属性本身的值应该使用双引号引起来,但是其中的路径还要使用单引号引起来.
  • ng-disable 是否禁用表单元素
  • ng-readonly 是否只读
  • ng-checked 原生的checked属性带有歧义,ng补充1个新的指令ng-checked 其值bool类型 true选中 false不选中.
  • ng-selected 是否选中
    后续还会介绍其他内置指令

2. 自定义指令

  • AngularJS不仅提供了功能强大的内置指令.还提供了一套允许我们自定义指令的机制.
  • 如果我们觉得ng提供的指令不够强大和好用,我们完全可以定义我们自己的指令.
  • 模块对象app,提供了一个directive方法,这个方法就可以让我们自定义指令.

    • 该方法需要两个参数

      第1个参数 指令的名称 - 指令名称不能包含符号,如果指令名称是tag,那么直接使用tag就行. 如果指令是hmTag,那么要使用hm-tag

      第2个参数 回调函数

      在ng解析这个指令的时候,就会自动去执行这个回调函数.
      这个回调函数必须要按照要求返回1个对象.
      restrict: ECMA E:Element C:Class M:Mark A:Attribute 自定义指令
      replace: bool值,是否替换原有标签.
      template: 模板,自定义指令将被替换成什么.
      templateUrl:加载外部文件 给一个需要加载的文件的路径.
      

<!DOCTYPE html>
<html lang="en" ng-app="hmApp">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.js"></script>
</head>
<body>
<div hm-tag></div> <!--加了这个自定义指令的标签中,就会被自动渲染自定义指令对应的template -->
<script>var app = angular.module('hmApp',[]);app.directive('hmTag',function () {return {restrict:'EA',replace:false,template:'<h1>我是中国人,我爱自己的祖国</h1>'};});
</script>
</body>
</html>

数据单向绑定

  • 所谓的数据的单向绑定,
  • 指的就是在控制器中制造数据模型,
  • 并将数据模型显示在视图上的过程.
  • 数据单向绑定的步骤
    1. 先在控制器中制造数据
    2. 在视图中使用绑定符号{{}}将控制器制造的数据模型显示
<!DOCTYPE html>
<html lang="en" ng-app="hmApp">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.js"></script>
</head>
<body>
<div ng-controller="demoCtrl"><h1>{{data.name}}</h1><ul><li ng-repeat="item in data.courses">{{item}}</li></ul>
</div>
<script>var app = angular.module('hmApp',[]);app.controller('demoCtrl',['$scope',function ($scope) {$scope.data = {name:"小明",courses:['html','css','js']};}]);
</script>
</body>
</html>```需要特别说明的是ng-bind指令和{{}}符号的效果是一样的.
{{}}符号是ng-bind指令的简写形式.所以,上面的代码也可以这样写.```js<div ng-controller="demoCtrl"><h1 ng-bind="data.name"></h1><!-- ng-bind指令与{{}}符号完全等价 --><ul><li ng-repeat="item in data.courses" ng-bind="item"></li></ul></div>

虽然ng-bind与{{}}使用效果是一样的,
但是在更多的地方我们仍然使用{{}}的场景更多一些

比如 : 这样的情况使用{{}}就方便的很多了.

“`js

大家好,我叫{{name}},我今年岁{{age}}了

“`

### 解决闪烁的问题

  • 虽然{{}}符号和ng-bind指令作用是一样的.但是他们在效果上有一些些区别
  • 使用{{}}符号有可能会出现闪烁现行(当吧ng文件的引入放在页面后面的时候)
  • 出现闪烁的原因
    • 浏览器先渲染html页面.遇到ng指令不认识 原因输出.
    • 而后,ng开始工作,渲染绑定数据.
    • 所以,中间有这么一个闪烁的过程.
      解决闪烁问题
    • 第一种方式: 将ng文件的引入放在head标签中.
    • 第二种方式: 为标签添加1个ng-cloak指令.就可以解决.
      ng-cloak的原理.
    • ng会自动的生成1段css代码,将这个标签隐藏.
    • 当数据绑定工作完成之后,再显示这个标签.

数据双向绑定

  • ng-model指令可以作用于表单元素.
    该指令的作用

    • 声明1个变量.该属性的值就是声明的变量.
    • 这个变量的值和表单元素的值是相互影响的.
    • 表单元素的值发生变化,这个变量的值也会跟着发生变化.
    • 这个变量的值发生变化,表单元素的值也会跟着发生变化.
    • 这样的数据绑定,就叫做双向数据绑定.
 <body><div ng-controller="demoCtrl"><input type="text" ng-model="val"> <!-- 使用ng-model指令声明的变量val,被文本框的值绑定 文本框的值改变会影响val的值,val的值得改变也会影响文本框的值, 这个时候,文本框的值和变量val是一个双向绑定的关系.--><h1>{{val}}</h1><button ng-click="show()">按钮</button> <!-- 按钮点击的时候,执行控制器绑定在$scope上的show方法,这个方法中直接修改了val变量的值, 你会发现文本框中的数据也会跟着一起改变.这就是双向数据绑定--></div><script>var app = angular.module('hmApp',[]);app.controller('demoCtrl',['$scope',function ($scope) {$scope.show = function () {$scope.val = 199;}}]);</script></body>

ng-init指令

数据模型的初始化,我们一般是放在控制器中.
为 scope对象附加属性的方式来追加.然后在视图中就可以直接绑定数据.实际上,Angular还提供了一种更为简便的方式来初始化模型数据.就是使用ng−init属性.使用ng−init初始化的变量在控制器中通过 scope对象附加属性的方式来追加. 然后在视图中就可以直接绑定数据. 实际上,Angular还提供了一种更为简便的方式来初始化模型数据.就是使用ng-init属性. 使用ng-init初始化的变量在控制器中通过scope仍然可以访问

“`js

{{name}} {{age}}

var app = angular.module('hmApp',[]);

“`

对于一些复杂的数据模型,比如数组、对象明显在controller中初始化就方便的很多.

Angular事件处理

1 ng-click

原生js中如果需要绑定点击事件,在html元素中使用onclick属性,
指定该属性的值为一个函数调用.
那么这个函数就是全局的函数,会造成全局污染.

“`js

function login(){
.......
}

登录

“`

Angular为了解决这个问题,使用了1个ng指令ng-click
这是Angular中的点击指令,为其赋值一个函数,不同的是,这个函数需要在控制器中绑定到$scope对象中.
那么这个函数就不再是一个全局的函数,就不存在全局污染的问题了.

  <div ng-controller="demoCtrl"><!-- 指定按钮的ng-click为login--><button ng-click="login()">按钮</button></div><script>var app = angular.module('hmApp',[]);app.controller('demoCtrl',['$scope',function ($scope) {//在控制器中为$scope绑定login函数.这样在视图中就可以调用$scope.login = function () { alert("正在登录,请稍后.....");}}]);</script>

2 ng-moueover

其实原理是一样的,这是ng的指令 用来绑定鼠标移入事件.

  <div ng-controller="demoCtrl"><button ng-click="login()">按钮</button><input type="text" ng-mouseover="mover()"></div><script>var app = angular.module('hmApp',[]);app.controller('demoCtrl',['$scope',function ($scope) {$scope.login = function () {alert("正在登录,请稍后.....");};$scope.mover = function () {console.log("鼠标移入了.....");}}]);</script>

其他事件指令

其实到这里我们可以总结出一些规律了
Angular的事件指令是在原生指令属性的基础之上把on去掉替换为ng-
onclick –> ng-click
onmouseover –> ng-mouseover
onkeyup –> ng-keyup
……

数据处理

1 ng-repeat

用于循环生成标签,并绑定数据.
可以遍历数组.

 <!DOCTYPE html><html lang="en" ng-app="hmApp"><head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.min.js"></script></head><body><div ng-controller="processDataView"><ul><!-- ng-repeat指令代表重复生成这个标签.值代表遍历数组中的每一个元素 并绑定显示 --><li ng-repeat="item in lessons">{{item}}</li></ul></div><script>var app = angular.module('hmApp',[]);app.controller('processDataView',['$scope',function ($scope) {$scope.lessons = ['html','css','js','jQuery'];}])</script></body></html>

可以遍历对象

  <!DOCTYPE html><html lang="en" ng-app="hmApp"><head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.min.js"></script></head><body><div ng-controller="processDataView"><ul><li ng-repeat="item in lessons"></li></ul><table><tr><!--遍历对象,item迭代变量直接就是每一个属性的值--><td ng-repeat="item in student">{{item}}</td><!--如果希望得到属性名称和属性值 可以像下面这样如果是数组,key拿到的就是下标          --><td ng-repeat="(key,item) in student">{{key}}:{{item}}</td></tr></table></div><script>var app = angular.module('hmApp',[]);app.controller('processDataView',['$scope',function ($scope) {$scope.lessons = ['html','css','js','jQuery'];$scope.student = {name:"杰克",age:18,gender:"男"};}])</script></body></html>

ng-switch

该指令的作用与js的switch-case非常相像
判断变量的值,如果变量的之与列出的任意1个值相等,则执行其中的逻辑.
语法规则

   <!-- 判断变量item的值 可以直接简写为ng-switch --><li ng-repeat="item in list" ng-switch on="item"><span ng-switch-when="html">我喜欢html</span><p ng-switch-when="ccs">哈哈css</p><a ng-switch-when="js" href="#">哦js</a><span ng-switch-when="jQuery">like jQuery</span><span ng-switch-default>啦啦啦,没有匹配到</span></li><!-- 在重复li标签时 到底嵌套那1个 根据when的值匹配来决定 当没有任何匹配的时候 就是default-->

也可以下面这样使用

  <!DOCTYPE html><html lang="en" ng-app="hmApp"><head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.min.js"></script></head><body><div ng-controller="demoCtrl" ng-switch="name"><div ng-switch-when="rose">Rose</div><div ng-switch-when="jack">Jack</div><div ng-switch-when="lily">Lily</div><div ng-switch-when="poly">Poly</div><div ng-switch-default>默认选项</div></div><script>var app = angular.module('hmApp',[]);app.controller('demoCtrl',['$scope',function ($scope) {$scope.name = "jack";}]);</script></body></html>

Angular作用域

1.相互独立的视图/控制器,他们的作用域($scope)也是相互独立,互不影响的.

 <!DOCTYPE html><html lang="en" ng-app="hmApp"><head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.min.js"></script></head><body><div ng-controller="demoCtrl1"></div><!--在与第2个控制器关联的视图上,无法访问与第1个视图相关联的控制器的数据--><div ng-controller="demoCtrl2"></div><div ng-controller="demoCtrl3"></div><script>var app = angular.module('hmApp',[]);app.controller('demoCtrl1',['$scope',function ($scope) {$scope.name = "杰克";//为第1个控制器/视图的$scope绑定了一个数据.//这个数据只能在与当前控制器相互关联的视图上访问.//不能在与别的控制器关联的视图上访问.}]);app.controller('demoCtrl2',['$scope',function ($scope) {}]);app.controller('demoCtrl3',['$scope',function ($scope) {}]);</script></body></html>

2.父子关系的视图所对应的控制器,在子视图/控制器中

可以访问父视图/控制器中$scope的数据.
* 子视图中可以访问父视图中的数据.
* 父视图不能访问子视图中的数据.
* 如果访问的变量在视图中有定义,那么优先访问子视图自己的,
如果该变量子视图自己没有定义,
这个时候再去尝试查找父视图中是否有定义这个数据.


<!DOCTYPE html>
<html lang="en" ng-app="hmApp">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.min.js"></script>
</head>
<body>
<div ng-controller="fatherCtrl"><div ng-controller="sonCtrl"><span>在子视图中访问父视图作用域中的数据: </span><!--当视图存在父子关系的时候,子视图可以访问父视图的数据--></div>
</div>
<script>var app = angular.module('hmApp',[]);app.controller('fatherCtrl',['$scope',function ($scope) {$scope.name = "杰克";}]);app.controller('sonCtrl',['$scope',function ($scope) {}]);
</script>
</body>
</html>    

3.根作用域

  • 我们可以使用ng-init指令来初始化一个变量,在父级元素上.
  • 那么这个父级元素下所有的子视图都可以访问.
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.min.js"></script>
</head>
<body><div ng-app="hmApp" ng-init="name='jack'"><div ng-controller="demoCtrl1"></div><div ng-controller="demoCtrl2"></div><div ng-controller="demoCtrl3"></div></div><script>var app = angular.module('hmApp',[]);app.controller('demoCtrl1',['$scope',function ($scope) {}]);app.controller('demoCtrl2',['$scope',function ($scope) {}]);app.controller('demoCtrl3',['$scope',function ($scope) {}]);</script>
</body>
</html>

过滤器

在AngularJS中使用过滤器格式化展示数据,
在“{{}}”中使用“|”来调用过滤器,使用“:”传递参数。

1.内置过滤器

日期过滤器 {{now|date:’yyyy-MM-dd hh:mm:ss’}}

货币符号过滤器 {{price|currency}}

  • 默认是美元符号
  • 如果想要显示其它货币符号
{{price|currency:'¥'}}
这样显示的就是人民币符号

保留指定位数的小树

  {{price|currency:'¥':2}}这样显示的就是人民币符号 并四舍五入保留两位小数

转换为大写

  {{info|uppercase}}将info的值转换为大写显示

转换为大写

  {{info|lowercase}}将info的值转换为大写显示

截取数组/字符串中指定位数的元素.

  {{arr|limitTo:n}}正数从左往右截取n个元素负数从右往左截取n个元素arr可以是1个数组也可以是一个字符串.字符串的话就截取每一个字符.

处理数字的过滤器number可以控制小数的位数

{{num|number:2}} 保留2位小数输出.

json过滤器 将对象转换为json字符串

{{obj|json}} 将obj对象转换为json字符串输出.实际上,不使用json过滤器它也会这么做.

orderBy过滤器

 {{students|orderBy:'score'}} 将student数组中的对象以score属性为参照进行排序 默认是升序.{{students|orderBy:'score':true}} 降序

filter 过滤器

 {{students|filter:{score:90} }} 过滤出数组中对象分数等于90的对象.特别注意: 参数对象必须和后面的大括弧有一个空格.

自定义过滤器

模块对象提供了一个filter方法,允许我们自定义过滤器.
该方法的参数说明

  • 第一个参数: 过滤器名称
  • 第二个参数: 回调函数 - 当执行我们自定义的过滤器的时候,就会自动来执行这个回调函数.

    <div ng-controller="demoCtrl">{{name|highven}}
    </div><script>var app = angular.module('hmApp', []);app.controller('demoCtrl', ['$scope', function ($scope) {$scope.name = "jack";}])app.filter('highven',function () {console.log("我被执行了");});
    </script>

通过调试发现,回调函数确实被执行了,但是报错了.报错的原因是我们没有按照要求来写这个回调函数的参数和返回值.
要求这个回调函数必须返回一个函数.
返回的这个函数就是过滤器,来处理过滤数据的.
这个返回的函数
* 第1个参数: 需要处理过滤的数据.
* 后面的参数: 处理数据的时候,自己还需要的另外的参数
* 返回值: 处理完毕后返回的数据,被显示出来.

<!-- 就会将name传递给自定义过滤器返回的函数处理 最终显示函数的返回值 -->
<span>{{name|highven}}</span>
<script>app.filter('highven',function () {return function(data){return data+"哈哈";}});
</script>

自定义过滤器案例:将一个英文句子中首个单词的首字母大写.

  app.filter('firstBig',function () {return function (data) {return data[0].toUpperCase()+data.slice(1);//slice从指定位置提取字符串 没有第2个参数就一直提到最后.}});

依赖注入

Angular内部封装了很多的模块,我们作为开发者在进行开发的时候,直接拿来使用就行,
也就是说,如果我们要使用别人封装好的模块,就必须要先引入别人的模块.
没有这个模块,可能就实现不了这个功能.
也就是我们依赖于这个模块.
比如jQuery是我们依赖的.

理解依赖注入
* 依赖关系: 就是模块之间的依赖关系.比如bootstrap依赖于jQuery,它们之间的关系就是依赖关系.

  • 依赖解决: 建立这种依赖关系的方案.比如之前我们使用1个script.src来解决依赖关系.

  • 注入: 是解决依赖的另外一种方式. 你可以形象的理解,A依赖于B,那么就像打针一样,把B注入 到A中,那么A中就可以使用B了.它们的依赖关系就建立成功了.

  • 所以,依赖注入是建立依赖关系的一种方式.

1.行内式注入

在视图中之所以能够访问到控制器绑定到 scope中的值,完全是因为 scope中的值,完全是因为scope的存在.
实际上, scope是Angular的一个模块.这个模块在视图中可以直接访问使用.但是在控制器的回调函数中,无法直接访问使用这个 scope是Angular的一个模块.这个模块在视图中可以直接访问使用. 但是在控制器的回调函数中,无法直接访问使用这个scope模块.
所以,这个回调函数必须要依赖$scope模块.
创建控制器的时候.第2个参数是一个数组.
数组的最后一个元素是控制器的回调函数.
前面的元素其实就是表明回调函数要依赖Angular的那些模块.

app.controller('demoCtrl', ['$scope', function ($scope) {}])
  • 第1个元素. ‘ scope′表明控制器要依赖 scope' 表明控制器要依赖scope这个模块.
  • 回调函数的参数: Angular会将$scope模块通过函数的形参注入到函数的内部,
    让函数去使用.
  • 实际上,回调函数的形参是可以任意的,
    这里之所以取得和模块的名字一样,是为了让我们的代码看起来更加具备可读性.

  • Angular提供的模块还有很多,我们也可以将其注入到控制器中.

app.controller('demoCtrl', ['$scope','$http' function ($scope,$http) {}])
表明,控制器要依赖$scope模块和$http模块.
那么这个时候,Angular会将这两个模块通过函数的形参`按照顺序`注入.

这样的注入方式,我们就叫做行内式注入

<body><div ng-controller="demoCtrl"><!-- 之所以能在这里访问控制器中绑定到$scope的name数据.完全是因为$scope的存在.实际上,$scope是ng的一个模块,这个模块是直接可以在视图中访问的.但是在控制器的回调函数中,无法直接访问使用这个$scope模块那么就需要将这个$scope模块注入到控制器的回调函数中--><span></span></div><script>var app = angular.module('hmApp', []);/** 第二个参数是一个数组.*      数组的第一个元素, '$scope'表示控制器要依赖 $scope 这个模块.*      Angular会通过回调函数的参数将$scope模块注入到回调函数内部.*      供控制器回调函数内部使用.*      这个时候,回调函数内部就可以通过形参拿到$scope这个模块.*      将其与视图共享之,传递数据之.*/app.controller('demoCtrl', ['$scope', function ($scope) {$scope.name = "杰克";}])</script></body>
  1. 推断式注入

    推断式注入的写法很简单,第2个参数直接写1个回调函数就可以.

    app.controller('demoCtrl', function ($scope) {$scope.name = "杰克";
    });
    

    Angular在注入的时候,会根据回调函数的参数名称进行推断.
    如果参数名称是 scope,那么就会将 scope,那么就会将scope这个模块进行注入
    如果参数名称是 http,那么就会将 http,那么就会将http这个模块进行注入
    所以,使用这种注入方式,回调函数的形参必须要和Angular的模块名称一致.否则将无法注入.
    推断式注入的缺点: 当进行代码压缩的时候,就会出问题,因为代码压缩会将形参替换.那么这个时候Angular就无法正常注入了.
    所以,我们推荐使行内式注入

Angular服务

服务,可以理解为就是一个对象或者函数,对外提供特定的功能.
其实你完全可以认为它就是一个模块,不同的模块提供不同的功能.
当我们要使用某1个模块的时候,将其注入到控制器中便可以使用

log服务

作用:在控制台输出调试信息. $log是1个对象.
调试信息分为如下几个级别.
* error 错误信息
* debug debug信息
* info 打印信息
* log 正常打印日志
* warn 警告信息

分别调用$log对象的这几个方法就可以输出对应格式的信息.
注意: 要正确调整浏览器控制台log过滤

$timeout服务

作用:在指定的时间做事情,$timeout是一个函数.

js
<body>
<div ng-controller="demoCtrl">
<!--所以,这里的name也要等到3秒钟后才会显示出来.-->
<p>我的名字叫做{{name}}</p>
</div>
<script>
var app = angular.module('hmApp', []);
app.controller('demoCtrl', ['$scope','$timeout', function ($scope,$timeout) {
$scope.now = new Date();
//表示3秒钟后为name赋值
$timeout(function () {
$scope.name = "小明";
},3000);
}]);
</script>
</body>

$interval服务

作用:每隔指定的时间就做指定的事情.

 <body><div ng-controller="demoCtrl"><!--所以,这里的数据每一秒钟就变化一次--><p>现在时间是:{{now|date:'yyyy-MM-dd HH:mm:ss'}}</p></div><script>var app = angular.module('hmApp', []);app.controller('demoCtrl', ['$scope','$interval', function ($scope,$interval) {$interval(function () {$scope.now = new Date();},1000);//每隔一秒钟就为now重新赋值.}]);</script></body>

interval函数,返回1个数据.调用 interval函数,返回1个数据.调用interval.cancel(返回值)可以停止计时器

 <body><div ng-controller="demoCtrl"><p>现在时间是:{{now|date:'yyyy-MM-dd HH:mm:ss'}}</p><button ng-click="stop()">停止</button></div><script>var app = angular.module('hmApp', []);app.controller('demoCtrl', ['$scope','$interval', function ($scope,$interval) {var stop = $interval(function () {$scope.now = new Date();},1000);$scope.stop = function () {$interval.cancel(stop);}}]);</script></body>

$filter服务

作用:格式化数据 filter这是1个函数狭义的解释:在控制器中格式化数据.过滤器在视图中格式化数据,而 filter这是1个函数 狭义的解释:在控制器中格式化数据.过滤器在视图中格式化数据,而filter在控制器中格式化数据.
用法实际上,和过滤器用法非常相像.并且$filter服务支持自定义过滤器

var item = $filter('过滤器名称'); //返回值是1个函数.var val = item(待格式化的数据,过滤器参数...);//返回值就是过滤器格式化后的数据

案例演示 :

 <body><div ng-controller="demoCtrl"><ul><li><span>现在时间是:{{now}}</span></li><li><span>{{intro}}</span></li></ul></div><script>var app = angular.module('hmApp', []);app.controller('demoCtrl', ['$scope','$filter',function ($scope,$filter) {//传入date 返回的函数就是和处理日期相关的函数var date = $filter('date');//第1个参数: 待处理的日期数据//第2个参数: 过滤器参数//返回值:被处理过的数据$scope.now = date(new Date,'yyyy-MM-dd HH:mm:ss');var uCase = $filter('uppercase');$scope.intro = uCase('this is itcast!');}]);</script></body>

$http服务

1.$http服务基本使用

作用:用于向服务器发送异步请求 这是1个函数.
参数:传入1个符合条件的对象.
* url:请求地址
* method:请求方式get/post
* data:{} 当请求方式为post的时候 使用data传递数据.
* params:{} 当请求方式为get的时候,使用params传递数据.
* headers:{} 设置请求头信息
* .then()函数传入两个回调函数.
* 第1个回调,当请求成功后执行,参数info。通过info.data拿到返回的数据
* 第2个回调,当请求失败后执行.

案例演示

<body><div ng-controller="demoCtrl"><table><tr><th>姓名</th><th>年龄</th></tr><tr ng-repeat="stu in data"><td>{{stu.name}}</td><td>{{stu.age}}</td></tr></table></div><script>var app = angular.module('hmApp', []);app.controller('demoCtrl', ['$scope','$http',function ($scope,$http) {$http({url:'example.php',method:'get'}).then(function (info) {$scope.data = info.data;},function () {});}]);</script></body>

2. $http服务传递数据的 格式

当请求类型是get时,向服务器传递的数据必须要放在params中,以对象的形式.
get请求发送的数据格式是 queryString类型的

 <div ng-controller="loginCtrl">用户名: <input type="text" ng-model="uName"><br>密码: <input type="password" ng-model="pwd"><br><button ng-click="login()">登录</button></div><script>app.controller('loginCtrl', ['$scope', '$http',function ($scope,$http) {$scope.login = function () {$http({url:'login.php',method:'get',params:{uName:$scope.uName,pwd:$scope.pwd}}).then(function (info) {}).catch(function () {});}}]);</script>

当请求类型是post时,向服务器发送的数据必须要放在data中.
设置发送数据的类型.
data要以键值对的字符串形式.
客户端以post方式向服务器发送数据时.必须要指定发送数据的类型.
因为不同的数据格式在服务器处理的方式是不一样的.
常见的数据格式
application/json –> 这种格式叫做formdata
application/x-www-form-urlencoded –> 这种格式叫做payload
jQuery的Ajax默认的数据类型就是application/x-www-form-urlencoded
AngularJS的$http默认支持的是application/json

$http跨域

基于浏览器的同源策略,Ajax异步是无法实现跨域请求的.
实现跨域请求的解决方案
* src属性是天然支持跨域的.
* 所以,我们可以利用script标签的src属性来跨域请求数据.
* 如果使用script标签的src属性来跨域请求,会将请求回来的数据作为js代码执行.

3.1 AngularJS的跨域

AngularJS已经帮我们封装好了一切.

  $http({url:'',//请求地址method:'jsonp',  //jsonp就可以(只支持不带有 .  的callback接口)params:{//传递额外数据.}}).then(function(info){}).catch(function(){});

自定义服务

1. 使用factory自定义服务

模块对象有一个方法叫做factory允许我们自定义服务.
该方法需要两个参数

  • 第1个参数,服务名称.
  • 第2个参数,是1个数组,前面的元素写依赖,最后一个元素是回调函数.

<script>var app = angular.module('hmApp', []);//第1个参数:自定义服务名称//第2个参数:数组,依赖 最后1个回调函数.app.factory('highven',[function () {console.log('这是我们自定义的服务!');}]);//在控制器中如果要使用我们自定义的服务,一样的方式注入就可以使用.//这样在注入的时候,就会执行我们自定义服务的回调函数.//拿到的就是这个回调函数的返回值.app.controller('demoCtrl', ['$scope','highven', function ($scope,highven) {}]);
</script>

这么写会报错,原因是回调函数我们没有按照AngularJS的要求来写返回值.
语法上,自定义服务的回调函数允许返回任意的值,但是既然是1个服务,1个模块,就应该返回1个功能,所以一般情况下,自定义服务的回调函数我们返回1个函数或者1个对象


var app = angular.module('hmApp', []);
//                     我们自定义服务依赖于另外一个服务
app.factory('highven',['$filter',function ($filter) {return {now:function () {var date = $filter('date');var time = date(new Date,'yyyy-MM-dd HH:mm:ss');return time;},format:function (format) {return $filter('date')(new Date,format);}}
}]);
//在控制器中如果要使用我们自定义的服务,一样的方式注入就可以使用.
//这样在注入的时候,就会执行我们自定义服务的回调函数.
//注入的自定义服务,就是自定义服务回调函数返回的数据.
app.controller('demoCtrl', ['$scope','highven',function ($scope,highven) {highven.now();highven.format('HH:mm:ss');
}]);

2. 使用service自定义服务

模块对象有1个方法叫做service,也能自定义服务.
该方法有两个参数
* 第1个参数,自定义服务的名称
* 第2个参数,数组,依赖,最后1个是回调函数.
与factory不同的是,service不需要手动返回数据.
直接用this,为返回的对象添加属性或者方法.
所以,service与factory的区别就像构造函数与工厂方法的区别

<body><div ng-controller="demoCtrl"><ul><li>现在时间是:</li><li>现在时间是:</li></ul></div><script>var app = angular.module('hmApp', []);app.service('highven',['$filter',function ($filter) {this.now = function () {return $filter('date')(new Date,'yyyy-MM-dd HH:mm:ss');};this.format = function (format) {return $filter('date')(new Date,format);}}])app.controller('demoCtrl', ['$scope','highven',function ($scope,highven) {$scope.time = highven.now();$scope.now = highven.format('HH:mm:ss')}]);</script></body>

配置块

在AngularJS执行流程中的配置和运行这一流程,允许开发者对AngularJS的模块进行自定义的配置.
这样就可以让后续ng的执行按照我们的意愿来.
模块对象提供了一个config方法,允许我们ng模块进行配置.
* 需要1个参数 这个参数是1个数组
* 数组中,写上开发者需要配置的模块Provider.最后是1个回调函数.给回调函数注入模块.
* 在回调函数中,对模块进行配置.
每一个服务,都对应一个Provider,比如 log模块对应 log模块对应logProvider, http对应 http对应httpProvider ……
在通过config方法配置模块的时候,其实是通过模块对应的Provider来进行配置的.

  //将要配置的Provider注入到函数中,进行配置.//这个Provider提供了相应的方法对模块进行配置.app.config(['$logProvider',function($logProvider){$logProvider.debugEnabled(false);}]);

1.配置$filter

每一个Provider都有自己的方法,我们不可能记住,也记不住.
所以,建议大家勤查AngularJS官方API

  <!DOCTYPE html><html lang="en" ng-app="hmApp"><head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.min.js"></script></head><body><div ng-controller="demoCtrl">{{info|bigFirst}}</div><script>var app = angular.module('hmApp', []);app.config(['$logProvider',function ($logProvider) {$logProvider.debugEnabled(false);}]);app.config(['$filterProvider',function ($filterProvider) {//新增过滤器.$filterProvider.register('bigFirst',function () {return function (input) {return input[0].toUpperCase()+input.slice(1);}});}]);app.controller('demoCtrl', ['$scope','$log', function ($scope,$log) {$scope.info = "this is itcast!";}]);</script></body></html>

2.配置$http跨域白名单

app.config(['$sceDelegateProvider', function ($sceDelegateProvider) {// 设置白名单$sceDelegateProvider.resourceUrlWhitelist(['http://api.map.baidu.com/telematics/v3/weather']);}])$http({url:'http://api.map.baidu.com/telematics/v3/weather',method:'jsonp',params:{ak:'0A5bc3c4fb543c8f9bc54b77bc155724',location:'深圳市',output:'json'}}).then(function (info) {console.log(info)});

运行块

AngularJS中的模块(服务)我们都是以注入的方式来使用的.
实际上,AngularJS中的模块是可以独立运行的.
模块对象提供了一个run方法,可以直接运行某些服务.不需要依赖控制器.
* 需要1个参数,这是1个数组.
* 在数组中写上要运行的模块,最后一个是1个回调函数.顺序注入.
* 在这个回调中的代码就会在配置运行阶段执行.
常见的模块.
* http可以在一启动的时候,就发起ajax异步请求∗ http 可以在一启动的时候,就发起ajax异步请求 * rootscope 为这个服务追加数据,就相当于追加到了根作用域中. 相当于ng-init
* $log
* ……

案例:

<body><div ng-controller="demoCtrl"></div><script>var app = angular.module('hmApp', []);app.run(['$log','$http','$rootScope',function ($log,$http,$rootScope) {//在这里可以脱离控制器使用模块对象.//$rootScope 模块代表根作用域,往其中追的数据就相当于是追在了根作用域中.$rootScope.name = "杰克";//在所有的作用域中都可以访问.}])app.controller('demoCtrl', ['$scope', function ($scope) {}]);</script></body>

AngularJS的路由

1. AngularJS路由的简单使用

实现单页面的原理
* 通过hashchange事件监听到锚点的变化,进而可以实现为不同的锚点显示不同的视图,单页面应用就是基于这一原理实现的。
AngularJS对这一实现原理进行了封装,将锚点的变化封装成路由(Route)。

 在1.2版前路由功能是包含在AngularJS核心代码当中,之后的版本将路由功能独立成一个模块,angular-route.js

将angular-route.js引入到当前项目中.

  <head><meta charset="UTF-8"><title>Title</title><script src="lib/angular.min.js"></script><script src="lib/angular-route.js"></script></head>

然后创建模块应用,需要注意的是,我们现在创建的模块应用要依赖于ngRoute模块.

  <script>var app = angular.module('hmApp', ['ngRoute']);//新创建的模块要依赖于 ngRoute 模块app.controller('demoCtrl', ['$scope', function ($scope) {}])</script>

只要app模块运行了,那么ngRoute模块就会被自动运行.
但是,ngRoute需要进行配置后才可以正常工作
ngRoute的服务名叫做 route,其配置对象应该为 route,其配置对象应该为routeProvider
* 默认情况下,锚链接必须以#!开头.
* 然后调用$routeProvider的when方法进行配置
* 第1个参数: 匹配到的hash值.hash值从#!后开始.
* 第2个参数: 匹配到以后,做什么事情.templateUrl要请求的资源路径.

app.config(['$routeProvider',function ($routeProvider) {$routeProvider.when('/home',{templateUrl:'data/home.json'}).when('/my',{templateUrl:'data/my.json'}).when('/find',{templateUrl:'data/find.json'});
}]);

然后指定1个ng-view,表示将请求来的资源加到这个元素下.

<div class="container" ng-controller="demoCtrl"><ul><li><a href="#!/home">首页</a></li><li><a href="#!/my">我的音乐</a></li><li><a href="#!/find">发现音乐</a></li></ul><div class="content" id="content" ng-view></div></div>

路由配置

when方法的第2个参数说明
* templateUrl,代表要请求的资源的路径.模板路径.
* template, 字符串形式的模板.
* controller,模板与控制器建立联系,建立起联系后,就可以使用控制器操作视图了.
* redirectTo,挑转到其它路由.
* otherwise方法,如果所有的when都匹配不上,就otherwise

 app.config(['$routeProvider',function ($routeProvider) {$routeProvider.when('/home',{templateUrl:'data/home.json'}).when('/my',{templateUrl:'data/my.json'}).when('/find',{templateUrl:'data/find.json'}).otherwise({//所有when都无法匹配的时候.});}]);

3.配置$locationProvider

hashPrefix方法,用来配置锚点值的前置符号.默认是叹号!

当然我们可以自定义这个前置符号.

  app.config(['$locationProvider',function ($locationProvider) {$locationProvider.hashPrefix('');//不设置前置 #/index//$locationProvider.hashPrefix('@');设置前置 #@/index}]);

为什么默认哈希前置设置为!

  • 如果网站内容是通过Ajax异步请求的.搜索引擎是看不到内容的.
  • 如今单页面应用比较受追捧,搜索引擎进行了升级.其也能够获得ajax异步的数据.比如Google
  • 但是有个前提,通过地址上某些符号来分辨哪些网站是ajax异步的.谷歌认为#!是异步的.

4. 路由参数

QueryString参数不影响路由.
使用$routeParams服务,可以获取路由参数.

http://localhost/index.html#/home?id=1&user=jack

在控制器视图加载的时候,就会执行控制器代码,在这个控制器中可以注入$routeParams服务,取到QueryString参数

  <script>var app = angular.module('hmApp',['ngRoute']);app.config(['$routeProvider','$locationProvider',function ($routeProvider,$locationProvider) {$locationProvider.hashPrefix('');$routeProvider.when('/login',{templateUrl:'./login.html'}).when('/register',{templateUrl:'./register.html'}).when('/list',{templateUrl:'./list.html',controller:'listCtrl'}).otherwise({});}]);app.controller('listCtrl',['$scope','$routeParams',function ($scope,$routeParams) {//在控制器被加载的时候,加载这个视图传递的QS参数,可以通过$routeParams服务拿到.$scope.lessons = ['html','css','js','java'];console.log($routeParams);}]);</script>

5.路由参数的另外一种形式

写在when方法的第一个参数上使用:参数的形式

when('/register/:id',{templateUrl:'./register.html',controller:'regCtrl'
})

那么在传递的时候, 使用这样的格式 index.htlm#/register/4,控制器拿到的参数就是{id:”4”}
再比如使用如下的when参数

when('/register/page/:page',{templateUrl:'./register.html',controller:'regCtrl'
})

那么在传递的时候, 使用这样的格式 index.htlm#/register/page/4,控制器拿到的参数就是{page:”4”}
需要注意的是,参数必须使用冒号:

比如:

when('/list/page/:page/name',{templateUrl:'./register.html',controller:'regCtrl'
})

那么在传递的时候, 使用这样的格式 index.htlm#/list/page/4/name,控制器拿到的参数就是{page:”4”}
如果希望没有值也能匹配到.加问号


when('/register/page/:page?',{  //可以写1个问号,表示后面没有数据的话也可以匹配到.templateUrl:'./register.html',controller:'regCtrl'
})

jQuery Lite

  • AngularJS不建议我们进行DOM操作.因为DOM的更新会随着数据模型的变* 化而自动变化.
  • 但是总会在某些时候,我们还是希望操作DOM的.
  • AngularJS为我们封装了一个轻量版的jQuery.
  • 调用全局对象angular的一个element方法,可以将1个原生的DOM对象转换为一个jQuery对象.
  • 然后可以使用这个jQuery对象的方法进行DOM操作.
  • 需要注意的是,这仅仅是Angular提供的一个轻量级的jq,所以仅仅是包装了jq常用的方法.
    • 如果我们的页面上引入了jQuery库,那么angular.element() 完全等价于 jQuery().
    • 如果我们的页面上没有引入jQuery库,那么就会使用ng内置的的一个迷你版本的jQuery,叫做jqLite。
    • jqLite中只提供了常用的方法. 比如animate方法就没有.

Angular的学习相关推荐

  1. angular基础学习

    angular基础学习 核心 一. angular环境搭建 1. 安装前准备: 1.1 安装nodejs 1.2 安装 cnpm, 尽量不要使用 1.3 使用npm/cnpm命令安装angular/c ...

  2. 为什么选择angular?-学习笔记

    使用angular的原因: Angular是一款优秀的前端JS框架,已经被用于Google的多款产品当中. 它有一下的特性: 良好的应用程序结构: 双向数据绑定: 指令: HTML模版: 可嵌入,注入 ...

  3. Angular.js学习-入门

    官方文档 https://angular.io/guide/quickstart 一.Angular.js是什么? Angular.js是一款为了克服HTML在构建应用上的不足而设计的优秀的前端JS框 ...

  4. Angular入门学习笔记

    Angualr入门扫盲必备 声明:这篇是我学习angualr的笔记,可以转载,但必须注明来源作者 kone 并附上本文链接 A:环境,工具 1:先确保安装了nodejs和npm Nodejs npm ...

  5. Angular 4 学习笔记1

    文章目录 一张图说明Angular程序架构 Angular开发环境搭建 项目文件夹和各部分关系 引入npm命令安装的外部模板 使用指令生成组件 启动项目指令 数据绑定 将css类绑定到html标签上 ...

  6. angular+ionic学习之项目构建

    前端时间学习了ionic5+angular12,做一次学习记录,对这阶段学习做一个总结. 安装ionic 本地全局安装 npm install -g ionic 或 // 用tabobao镜像装会快些 ...

  7. Angular 4 学习笔记 从入门到实战 打造在线竞拍网站 基础知识 快速入门 个人感悟

    最近搞到手了一部Angular4的视频教程,这几天正好有时间变学了一下,可以用来做一些前后端分离的网站,也可以直接去打包web app. 先上个效果图: 环境&版本信息声明 运行ng -v @ ...

  8. 3、Angular JS 学习笔记 – Controllers [翻译中]

    2019独角兽企业重金招聘Python工程师标准>>> 理解控制器 在Angular中,一个控制器是一个javascript构造函数用于填充Angular作用域. 当一个控制器通过使 ...

  9. 4、Angular JS 学习笔记 – 创建自定义指令 [翻译中]

    2019独角兽企业重金招聘Python工程师标准>>> 创建自定义指令 注意:本指南是针对已经熟悉AngularJS基础的开发者.如果您只是想要开始,建议您先去看教程.如果你在寻找指 ...

最新文章

  1. 如何正确的使用单例模式
  2. html图片怎么设置悬浮效果,图片漂浮效果js实现
  3. 大话设计模式—责任链模式
  4. 【重版】朴素贝叶斯与拣鱼的故事
  5. Gartner:CIO需破解建立数字化领导力的四大障碍
  6. 3gpp协议_春天工作室lt;3GPP规范翻译系列gt;1:TS37340协议翻译(导读)第一部分...
  7. Linux:文件权限数字形式
  8. sed 多行替换,多行模式处理字符串;一次替换
  9. [回炉计划]当输入xxxxhub的时候,居然是这样
  10. python爬取去哪里_详解Python 爬取13个旅游城市,告诉你五一大家最爱去哪玩?
  11. 《微观经济学》 第十章
  12. 微信小程序开发制作 | 小程序开发者工具功能介绍
  13. c#开发初学者之mvc及架构分层
  14. 新建Mavlink消息
  15. 解决Linux Telnet乱码问题
  16. 深度学习自学(二十六):ICCV2019
  17. Android工具类 全国省市的Json文件
  18. 抖音测试美甲软件,几款抖音最火美甲图片 最新网红美甲图案
  19. mqtt 发送消息过多_eclipse mqttclient 性能MQTT(32202): 正在发布过多的消息
  20. 陈年不说,我就来说吧—关于凡客最近的裁员和期权内幕

热门文章

  1. Redis缓存穿透解决方案
  2. 机器视觉系统完整的工作过程
  3. c语言自动导入数据类型,c语言数据类型
  4. STM32——通用定时器
  5. 使用python读取excel进行处理,并将结果存储在新的excel
  6. Mysql动态生成列
  7. NDK学习笔记:RtmpPusher之利用rtmpdump推h264/aac码流
  8. WebApp 之 manifest.json
  9. Centos7安装aeneas ffmpeg实现字幕音视频自动强制对齐
  10. 关于Cisco路由交换机的产品介绍