angular.js:
教程可以作为跳板,因为vue也参考了angular的设计。
angular.js是google开源的前端js结构化框架
第一次学习结构化框架,它和函数库有什么区别呢?
比如jQuery中,安装之后,可以在编写js中有一个$符帮助我们去寻找特定的方法,方便记忆和使用(能够提高效率),在jQuery中所有的都是属于函数调用(对内容封装,给出api)。
angular.js的特性和优点:
双向数据绑定
声明式依赖注入
解除耦合应有逻辑,数据模型和视图。(耦合度,会让开发比较困难,在不知情的情况下,容易牵一发而动全身)
完善的页面指令
定制表单验证
Ajax封装
与jQuery比较:
jQuery让开发更加方便了;{js函数库,封装简化dom操作}
angular:js结构化框架,主体不再是dom而是页面中动态的数据;(它相当于在页面和内存中建立连接,关注数据的动态变化)
angular能做什么项目:构建单页面(SPA)web应用,web app应用;应用(饿了么,淘宝,知乎周报等);
单页面应用:
single page application'特点:
1.活动只局限在一个页面
2.当页面中有部分数据发生了变化不会刷新整个页面而是局部刷新
3.利用ajax技术,路由。
angular:语法1.x是javascript写的,新版使用typescript写的;(有依赖关系)
相当于属性一样的标记(监管动态数据,而不是dom操作)
ng-app告诉angular核心它管理当前标签所包含的整个区域,并且创建$rootScope根作用域对象
ng-model将当前输入框的值与谁相关联(属性名:属性值),并作为当前作用域对象($rootScope)的属性;
{{}}(表达式):显示数据,从作用域对象的指定属性名上取;
1.表达式:通常有一个返回值,可以放在任何需要值得地方,比如函数调用的参数,一个是变量名,一个运算
2.语句:通常表示一个完整的执行单位,一段完整的js代码,有的语句可以使用表达式来执行,叫做表达式语句
3.区别:语句用分号结尾,有些语句我们没有加分号,比如console.log()虽然没有加分号,但也是语句;js引擎会自动加分号
4.特例:if语句就不用加分号,可也是一个完整的语句;
双向数据绑定:
1.数据绑定:
数据从一个地方A转移到另一个地方B,而且让这个操作由框架来完成
2.双向数据绑定:数据可以从视图view流向model也可以从model流向view
view:也就是当前页面;(主要是angular指令和表达式)
model:作用域对象($rootScope),它可以包含一些属性或方法
当改变view中的数据,model对象的对应属性,也会随之改变,ng-model指令数据从view流向model
当model域对象属性发生变化时,页面对应随之更新{{}}表达式,数据从model中流向view
3.ng-init初始化当前作用域变量;单向数据流动
作用域对象和控制器对象:
ng-controller:指定控制器构造函数,Angular会自动new此函数创建控制器对象
同时Angular还有创建一个新的作用域对象$scope,它是$rootScope的子对象。(只限于这个ng-controller作用域,但是在这种作用域中,可以向全局的作用域中获取对象。)
在控制器函数中声明$scope形参,Angular会自动将$scope传入
依赖对象:
完成某个特定的功能,需要某个对象才能实践,这个对象就是依赖对象。
依赖注入:依赖的对象以形参的 形式被注入进来使用,这种方式就是依赖注入(声明式)。
angular的$scope就是依赖对象,并且是依赖注入的形式进行使用,
!形参必须是特定的名称,否则Angular无法注入抛出异常。
回调函数的event的就是依赖对象
回调函数有形参就是依赖注入;
依赖注入:
声明式依赖注入:更加注重执行的结果
对命令结构进行局部包装
命令式依赖注入:更加注重执行的过程
没有包装需要一步一步的解答
模块对象和控制器对象(为什么要使用这个对象,就是为了能够改变轻松的改变页面):
可以通过创建模块对象
ng-app可以指定一个区域的名字;
创建方式;
ng-app="myApp"
var myModule=angular.module("myApp",[])
生成作用域对象:
ng-controler="MyController"
myModule.controller("MyController",function($scope){})
链式调用:
angular.module('myApp',[])
.controller('MyController',function($scope){
$scope.empName-'kobe';
})
.controller(MyController2",function($scope){
$scope.empName='kobe2';
})
链式调用说明每一个函数有返回值,这个返回值是模块对象;
由于angular在压缩的时候会将$scope压缩为任意字母所以传参的时候可以使用数组传递的方式,防止angular的$scope被压缩;
链式调用:
angular.module('myApp',[])
.controller('MyController',['$scope',function($scope){
$scope.empName-'kobe';
}])
这种方式叫做显示声明依赖;(第二个$scope可以写任何形参,angular.module没有依赖)
表达式:
表达式中的可以调用javascripe代码,如果不加''的字符被认为是变量
常用的指令:
ng-click点击事件:ng-click="回调函数"
ng-repeat:遍历数组显示元素;
有点像for in循环
<li ng-repeat="person in persons">
{{person.username}}--{{person.age}}
</li>
其中person是取自数组的一个单位
$index显示下标,遍历的时候的下标
$first
$last
$middle中间的为true(除了第一个和最后一个)
$odd奇数为true
$even偶数为true
返回一个boolean值
这个方法会产生多个作用域,数组有多少元素就有多少个作用域
ng-bind:解决表达式闪屏的问题。当网速加载文档比较慢的时候,就会出现写在html中的代码被解析出来,导致网页中展现太多的代码,(由于浏览器加载的时候是从上向下解析的所以,上面的angular标记会率先解析出来,从而影响用户体验,而且可能影响到浏览器的渲染)
ng-bind="这个标签中塞的内容"(这个方法的原理是,浏览器解析的时候不会先读取启动不认识的标签属性,而是等待文档加载之后才会将这个属性中的值,塞到标签中去)
ng-show
ng-hide里面放置boolean类型,如果是true则执行,否则不执行
ng-class:动态引用定义的样式
ng-class={属性名的类:boolean值}{$odd,$even返回值是boolean值,可以将这个放到上面}
ng-style:动态的引用通过js的样式对象内部的属性值要使用''
ng-style={
backgroud:"red";
}
ng-mouseenter="方法"
ng-mouseleave="方法"
1.localstorage永久存储
生命周期:永久保存只要浏览器还在,不被手动清除;
大小:5M甚至更大
setItem('key',value);
getItem('key');
removeItem('key');
2.sessionstorage会话存储
生命周期:页面打开到关闭
大小:5M
setItem('key',value);
getItem('key');
removeItem('key');
3.cookie
作用:用于保存浏览器和服务器端进行通信
特点:
大小:4kb
每次发送请求都携带,导致占用带宽
保存在浏览器端
cookie容易被截获(现在就有一些浏览的时候,之后会被推送广告就是因为cookie被截获了)
cookie的生命周期:
会话cookie:浏览器打开到关闭;
人为设置cookie:人为设置时间;
练习1:剩余字数功能实现;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>剩余字数功能的实现</title>
<style type="text/css">
textarea{
resize: none;
}
</style>
</head>
<body ng-app='myApp'>
<div ng-controller='myController'>
<h2>我的笔记</h2>
<textarea rows="10" cols="30" ng-model='message'>
</textarea>
<div id="">
<button type="button" ng-click='save()'>保存</button>
<button type="button" ng-click='read()'>读取</button>
<button type="button" ng-click='delete()'>删除</button>
</div>
<p>剩余的字数:{{getCount()}}</p>
</div>
<script src="../../source/angular-1.5.5/angular.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
angular.module('myApp',[]).controller('myController',['$scope',function($scope){
//为什么要在这里给它定义一个字符串,原因是在文档读取的时候没有给message赋值和定义类型,如果刚开始就直接调用{{getCount()}},就会报错,而100-undefined.length就更错了
$scope.message='';
$scope.getCount=function(){
var x=$scope.message.length;
if(x<=100){
return 100-$scope.message.length;
}
else{
// 使用slice截取0到100的子串的内容将它覆盖
$scope.message=$scope.message.slice(0,100);
return 0;
}
}
$scope.save=function(){
// 保存的时候最好将内容转换成JSON字符串这样安全一点,读的时候在转换回来
if($scope.message){
localStorage.setItem("message",JSON.stringify($scope.message));
console.log('保存成功');
}else{
console.log('无内容');
}
}
$scope.read=function(){
var read1=localStorage.getItem("message");
// console.log(read1);
if(read1){
console.log('读取成功成功');
// 只有read1中有值时才能被转化,否则会报错,返回空串不行。
$scope.message=JSON.parse(read1);
}else{
console.log("无内容");
}
}
$scope.delete=function(){
if($scope.message){
console.log('删除成功');
$scope.message='';
}
else{
if(!localStorage.getItem("message")){
console.log("无内存数据");
}
else if(confirm("是否删除内存?")){
localStorage.removeItem("message");
console.log('删除内存成功');}
}
}
}])
</script>
</body>
</html>
练习2:数据动态显示
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>数据的动态显示</title>
</head>
<body ng-app="myApp">
<div ng-controller="myController">
<h2>我的备忘录</h2>
<div>
<input type="text" ng-model='newTodo'/>
<button type="button" ng-click='add()'>添加</button>
</div>
<div ng-repeat="todo in todos">
<!-- ng-model是双向的,所以在选中时就会变成true -->
<input type="checkbox" ng-model='todo.isChecked'/>
<span>{{todo.name}}</span>
</div>
<button type="button" ng-click="delete()">删除所选的记录</button>
</div>
<script src="../../source/angular-1.5.5/angular.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
angular.module('myApp',[])
.controller('myController',["$scope",function($scope){
$scope.newTodo='';
$scope.todos=[
{name:'吃饭',isChecked:false},
{name:'逛街',isChecked:true},
{name:'拉屎',isChecked:false}
]
$scope.add=function(){
if($scope.newTodo){
// $scope.todos.push($scope.newTodo);这样不行啊,因为添加的是一个对象,而这里面是一个字符串,所以要对信息进行收集整理;
var oTodo={name:$scope.newTodo,isChecked:false};
// $scope.todos.push(oTodo);末尾添加最后数据多不好看,最好放在最前面
$scope.todos.unshift(oTodo);
console.log($scope.todos)
}
else{
alert("请输入具体的行为!嘤嘤嘤~~");
}
}
$scope.delete=function(){
if(!confirm("是否拜拜日常行为?点击是就再也见不到了哦")){return;}
// $scope.todos.forEach(function(item,index){
// // 这样的方法只能删除一个数据,而forEach中不能使用循环判定固定数据
// if(item.isChecked){
// $scope.todos.splice(index,1);
// // 采用递归调用直至删除完毕,采用递归必须有结束条件不然循环多次啊
// // $scope.delete();这个方式就失去提示的机会了
// $scope.delete();
// }
// })
// 创建新的引用
var otodos=$scope.todos;
// 重新引入数组将新的数组放到对应位置
$scope.todos=[];
otodos.forEach(function(item,index){
if(!item.isChecked){
// 注意插入的顺序
$scope.todos.push(item);
}
})
}
}])
</script>
</body>
</html>