ng-show/ng-hide/ng-if:true/false
ng-checked/ng-disabled/ng-readonly/ng-selected
单一页面程序【SPA】体会:现在请你打开网易云的官网https://music.163.com,播放一首你最喜欢的歌曲,然后点击一下”我的音乐“,不知道这个过程你是否会想到这个问题:唉?我都点击一个资源了,页面并没有跳转也没有任何刷新的迹象,页面的头部没有改变,更重要的是你最喜欢的歌依旧没有任何停顿的在播放。不用我说你可能觉得这很简单,这不就是用ajax去做的吗?这有什么难的!没错,这个过程确实是用ajax去做的,那你该问这个Angular有个毛关系?关系不关系我们接着看!如果你足够细心,会发现当你点击“我的音乐”时,浏览器是没有刷新的,但是浏览器的地址栏却发生了一些细微的变化,在地址栏中出现了像是锚点的东西,不过我们的锚点不是常常指向一个dom元素的id吗?细看这个锚点后面的东西有些像一个路径,下面我们来扯一扯window对象的一个锚点切换事件你大概就略有所悟了。
<script> (function (window) { // 每当锚点改变触发以下事件 window.addEventListener('hashchange', function (e) { console.log(e); console.log(window.location); var hash = window.location.hash; // 网易锚点后的链接 switch (hash) { case '#/my/': // ajax do somethings break; case '#/friend': // ajax do somethings break; case '#/download': // ajax do somethings break; } }) })(window) </script>
说白了,还是使用ajax去请求后台,只不过是换了一种方式,使用锚点的方式触发了。
来自百度百科的介绍:https://baike.baidu.com/item/SPA/17536313
API:https://docs.angularjs.org/api
一个测试不同技术的模板:https://github.com/tastejs/todomvc-app-template
Angular解放了传统JavaScript中频繁的DOM操作;
官网地址:https://docs.angularjs.org/tutorial/step_00
插件:AngularJS Batarang自己去goole商店下载,可用来查看Angular一些数据渲染
首先:所有需要ng管理的代码必须被包裹在一个有ng-app指令的元素中,ng-app是ng的入口,表示当前元素的所有指令都会被angular管理(对每一个指令进行分析和操作)。
<body> <!--所有需要ng管理的代码必须被包裹在一个有ng-app指令的元素中,ng-app是ng的入口, 表示当前元素的所有指令都会被angular管理(对每一个指令进行分析和操作)--> <div ng-app ng-init="_name='毛毛'"> <!--ng-init表示初始化一个默认值--> <!--在ng中定义一个模型--> <input type="text" ng-model="name"> <!--在ng中使用定义的模型--> <p>你好,{{name}}</p> </div> <script src="../node_modules/angular/angular.js"></script> </body>
HTML页面中ng-xxx的属性称之为指令(Directive);
ng-app指令告诉AngularJS,<div>元素是AngularJS程序管理的边界;
ng-model:是双向数据绑定的指令,效果就是将当前元素的value属性和模型中的name建立绑定关系。
{{name}}表达式就是把应用程序变量name绑定到某个段落的innerHTML
<!--如果ng-app中有模块名,则表示我这个div将由myApp这个模块管理,否则由angular管理--> <!--ng-controller中指明我这个模块将由AppController控制--> <div ng-app="myApp" ng-controller="AppController"> <!--在ng中定义一个模型--> <input type="text" ng-model="user.name"> <!--在ng中使用定义的模型--> <p>你好,{{user.name}}</p> <button ng-click="show()">点击</button> </div> <script src="../node_modules/angular/angular.js"></script> <script> (function () { var myApp = angular.module("myApp",[]);// 第二个参数数组表示可能引用的模块 // 存在不能混淆压缩的问题 myApp.controller("AppController",function($scope) { // $scope这个参数名称固定!代表上图中存储区块对象 $scope.user = {}; $scope.user.name = '毛毛'; $scope.show = function() { console.log($scope.user.name); } }); })() </script>
注册控制器存在的问题:在上面说了$scope是一个固定写死的参数,一旦更改名称,angular将不能识别注入!这就存在一个问题就是js压缩问题,我们都知道生产环境中可以使用未压缩的js文件,但是上线常常使用标识符混淆的压缩方式压缩代码,一旦使用标识符混淆,$scope就会被改变,angular又不能注入了。angular为了解决这个问题,声明了一种标准的写法:
// 标准写法: myApp.controller("AppController",['$scope',function(a) { // 字符串'$scope'固定写法 a.user = {}; a.user.name = '毛毛'; a.show = function() { console.log(a.user.name); } }]);
使用数组的方式,要求数组的最后一个元素是一个function,之前的元素对应该function中的参数,由于数组中存储的function参数是字符串类型而不是一个变量,就不会存在混淆压缩被替换的问题。
ng-xxx的属性本身并不是标准中定义的属性,很多情况下语法检验(W3C)是无法通过的
HTML5允许扩展的(自制的)属性,以data-开头,在AngularJS中可以使用data-ng-xx来让网页对HTML5有效,这和直接在元素中使用ng-xx效果相同
最好只出现一个ng-app,如果出现多个ng-app就需要手动引导,或模块带入方式实现
在下面讲到表达式的时候,在表达式中存在一个闪烁问题,解决这个问题我们还可以使用ng-bind中绑定数据,而不是直接在标签文本内部使用。
你可以在其中绑定一些基本的数据,但是并不建议你去绑定html,因为这将带来不安全的操作,可能存在一些脚本攻击【假如你绑定的是某个用户评论的内容,该内容是一段js脚本用来获取你本地cookie信息模拟你登陆,窃取一些东西】。所以默认的你在ng-bind中所有的文本标签<,>将会被替换为<>,防止你绑定的数据是一个脚本。如果你非要去绑定一个标签内容,并想呈现标签的效果,你就要使用ng-bind-html,使用该标签你要求你使用angular提供的一种校验库sanitize,用以校验你绑定的内容是否安全。【即使这样,还是不推荐你去绑定html】
<body ng-app ng-init="h='shif'"> <p>{{h}}</p> <p ng-bind="h"></p><!--不会出现闪烁问题--> <script src="../../node_modules/angular/angular.js"></script> </body>
<body ng-app="myApp" ng-init="exam='<h1>shif</h1>'"> <p ng-bind-html="exam"></p> <script src="../../node_modules/angular/angular.js"></script> <script src="../../node_modules/angular-sanitize/angular-sanitize.js"></script> <script> (function () { var myApp = angular.module("myApp",["ngSanitize"]) })(); </script> </body>
<body ng-app="myApp"> <ul ng-controller="ULController"> <li ng-repeat="item in data"> <span>id:{{$id}}</span> <span>index:{{$index}}</span> <span>first:{{$first}}</span> <span>last:{{$last}}</span> <span>middle:{{$middle}}</span> <span>even:{{$even}}</span> <span>odd:{{$odd}}</span> <span>{{item.name}}</span> </li> </ul> <script src="../../node_modules/angular/angular.js"></script> <script> (function () { angular.module('myApp', []).controller('ULController', ['$scope', function ($scope) { $scope.data = [{name: '毛毛'}, {name: '吉吉'}, {name: '咪咪'}, {name: '可可'}]; }]) })(); </script>
如果遍历的元素存在重复的,则需要track by 一个不重复的量:
<li ng-repeat="item in data track by $index">
ng-class中可以写入一个对象,如下例中对象的key值表示现有的css样式属性名,对象的value为true或者false,表示是否起作用。ng-class还可以绑定model。
<style> .red { color: red; } .green { color: yellow; } </style> </head> <body ng-app="myApp" ng-init="nnm='red'"> <div ng-controller="ULController"> <ul> <li ng-repeat="item in data"><!--隔行换色--> <span class="{{$even?'red':'green'}}">{{item.name}}</span> </li> </ul> <ul> <li ng-repeat="item in data"><!--隔行换色--> <span ng-class="{red:$even,green:$odd}">{{item.name}}</span> </li> </ul> <span ng-class="nnm">{{ 10+20 }}</span> <!--还可以绑定一个模型--> </div> <script src="../../node_modules/angular/angular.js"></script> <script> (function () { angular.module('myApp', []).controller('ULController', ['$scope', function ($scope) { $scope.data = [{name: '毛毛'}, {name: '吉吉'}, {name: '咪咪'}, {name: '可可'}]; }]) })(); </script>
ng-show/ng-hide/ng-if:true/false
<body ng-app="myApp" ng-init="nnm='red'"> <div ng-controller="ULController"> <div class="hong" ng-show="show"></div> <div class="hong" ng-hide="show"></div> <div class="hong" ng-if="if"></div> </div> <script src="../../node_modules/angular/angular.js"></script> <script> (function () { angular.module('myApp', []).controller('ULController', ['$scope', function ($scope) { $scope.show = true; $scope.hide = false; $scope.if = false; }]) })(); </script>
ng-href/ng-src指令用于解决当链接类型的数据绑定时造成的加载BUG
<body ng-app ng-init="url = '../images/123.png'"> <img src="{{url}}" alt=""> // 在angular没起作用之前就开始发送了请求,所有控制台会报一个错 <img ng-src="{{url}}" alt=""> <script src="../../node_modules/angular/angular.js"></script> </body>
<div ng-app="myApp" ng-controller="AppController"> <div ng-repeat="item in exam"> <div ng-switch="item.name"> <p ng-switch-when="Liu">刘</p> <p ng-switch-when="Li">李</p> <p ng-switch-when="Wang">王</p> <p ng-switch-default>赵</p> </div> </div> </div> <script src="../../node_modules/angular/angular.js"></script> <script> (function () { angular.module('myApp',[]).controller('AppController',['$scope',function ($scope) { $scope.exam = [{name:'Li'},{name:'Liu'},{name:'Zhao'},{name:'Wang'}] }]); })(); </script>
ng-checked/ng-disabled/ng-readonly/ng-selected
<!-- 双向绑定的,任意一个选中则全部选中 --> <input type="checkbox" ng-model="checked"><br/> <input type="checkbox" ng-model="checked"> <input type="checkbox" ng-model="checked"> <input type="checkbox" ng-model="checked">
<!-- ng-model双向绑定的,ng-checked时模型到视图的绑定(单项),第一个选中全选中,其他选中只选中自己 --> <input type="checkbox" ng-model="checked"><br/> <input type="checkbox" ng-checked="checked"> <input type="checkbox" ng-checked="checked"> <input type="checkbox" ng-checked="checked">
<head> <meta charset="UTF-8"> <title>自定义指令</title> <link rel="stylesheet" href="../../node_modules/bootstrap/dist/css/bootstrap.css"> </head> <body ng-app="myApp" ng-init="nnm='red'"> <div ng-controller="ULController"> <breadcrumb data="{{data}}"></breadcrumb> </div> <script src="../../node_modules/angular/angular.js"></script> <script> (function () { var myApp = angular.module('myApp', []); myApp.controller('ULController', ['$scope', function ($scope) { $scope.data = ['blogs','home','doc','index']; }]); /*自定义指令*/ myApp.directive('breadcrumb',[function () { return { scope:{ // data:'@' // 不能直接引用到该元素的data属性,因为直接拿到的是一个字符串,不是对象 }, // template:'<h1>xasx</h1>', templateUrl:'./template.html',// 模板的地址 replace:true, // 是否是以替代的方式替换之前元素 link:function (scope,element,attributes) { scope.data = JSON.parse(attributes.data); // console.log(scope.data); } } }]) })(); </script>
<nav aria-label="breadcrumb"> <ol class="breadcrumb"> <li class="breadcrumb-item" ng-repeat="item in data track by $index"> <a href="#" ng-if="$last == false ? true:false">{{item}}</a> <span ng-if="$last">{{item}}</span> </li> </ol> </nav>
<body ng-app="Login"><!--这是angular管理的一个模块--> <table border="1" ng-controller="LoginController"><!--该模块的这一部分dom由LoginController控制--> <tr> <td>用户名:</td> <td><input type="text" ng-model="user.name"></td><!--双向绑定$scope中的数据模型--> </tr> <tr> <td>密码:</td> <td><input type="password" ng-model="user.password"></td><!--双向绑定$scope中的数据模型--> </tr> <tr> <td></td> <td><input type="button" value="登陆" ng-click="login()"></td><!--绑定$scope中的方法--> </tr> <tr> <td colspan="2">{{message}}</td> </tr> </table> <script src="../node_modules/angular/angular.js"></script> <script> var loginApp = angular.module("Login",[]); loginApp.controller("LoginController",['$scope',function ($scope) { // 数据 $scope.user = { name:'', password:'', }; $scope.message = ''; // 行为数据 $scope.login = function() { // ajax do somethings console.log($scope.user); }; // 监视数据的行为,第一个参数为要监视的模型,第二个参数为一个function $scope.$watch('user.name',function (now,old) { // now表示模型的当前值,old表示模型的上一次值 console.log(now,old); if(now) { if (now.length < 7) { $scope.message = '输入的用户名不合法!'; } else { $scope.message = ''; } }else { $scope.message = '请输入用户名!'; } }) }]) </script>
<body> <div ng-app ng-init="_name='毛毛'"> <input type="text" ng-model="_name"> <p class="ng-cloak">你好,{{_name}}</p> </div> <script src="../node_modules/angular/angular.js"></script> </body>
依旧是最开始的例子,在goole里测试由于goole的缓存可能看不到,这个例子在火狐里面你就会发现,每次刷新时页面先出现“你好,{{_name}}”,然后又迅速的变成了“你好,毛毛”,查其原因,当然是由浏览器解析dom的顺序导致的,由于我们是在后面导出angular的,所以浏览器按照顺序解析会先出现“你好,{{_name}}”,然后当解析到angularJS时才将表达式里的内容替换掉的。当你把angularJS文件的引用放到最开始,就不会出现这个问题(如果你刷新的速度足够快,还是会出现闪烁问题)。
Angular为了解决这个问题提供了一个属性标签ng-cloak,将存在表达式的标签上添加该属性,并且还要把angularJS文件的引用放在前面才行。
当然还有另外一种解决方案使用css方式去控制,我们依旧使用angularJS提供的指令标签ng-cloak,然后写一段css代码:
<head> <meta charset="UTF-8"> <title>Angular</title> <style> [ng-cloak] { display: none; } </style> </head> <body> <div ng-app ng-init="_name='毛毛'"> <input type="text" ng-model="_name"> <p ng-cloak>你好,{{_name}}</p> </div> <script src="../node_modules/angular/angular.js"></script> </body>
使用属性选择器先将该元素隐藏,等加载angularJS时,由angularJS渲染表达式,最后将标签显现出来。
//数字 {{ 100 + 100 }} //字符串 {{ 'hello' + 'world' }} //对象 {{ user.name }} 数组 {{ data[0] }} //三元表达式 {{ flag == true ? data[1] : data[2] }}