AngularJS 简介及基础用法(双向数据绑定、依赖注入、模块对象、相关指令、动态练习)

AngularJS框架

  • AngularJS介绍
  • 第一个Angular程序
  • 四个重要概念
    • 1. 双向数据绑定
    • 2. 依赖注入
    • 3. MVC模式
    • 4. MVVM模式
  • 三个重要对象
    • 1. 作用域对象
    • 2. 控制器对象
    • 3. 模块对象 ※
  • 两个页面语法
    • 1. 表达式 ※
    • 2. 指令 ※
  • 练习一:我的笔记 ※
  • 练习二:我的备忘录 ※


本人是个新手,写下博客用于自我复习、自我总结。
如有错误之处,请各位大佬指出。
学习资料来源于:尚硅谷


AngularJS介绍

jQuery是JS的函数库,主要用来封装简化DOM操作。而AngularJS是Google开源的前端JS结构化框架,它的主体不再是DOM,而是页面中动态的数据。学习它可为后续学习React和VUE框架打下良好基础。

AngularJS做什么项目? 它用来构建单页面(SPA)Web应用或Web App应用。

单页面应用(SPA):single page application 特点:

  • 将所有的活动局限于一个页面。
  • 当页面中有部分数据发生了变化不会去刷新整个页面,而是局部刷新。
  • 利用的ajax技术。

AngularJS特性和优点:

  • 双向数据绑定
  • 声明式依赖注入
  • 解耦应用逻辑, 数据模型和视图
  • 完善的页面指令
  • 定制表单验证
  • Ajax封装

用到的资源:

接下来用到的是Angular1.x的版本,它也有2.x和4.x版本,4.x只是在2.x的基础上添加了一些很小的部分。选择1.x版本是因为,它的语法是JS,而2.x和4.x的语法是typescript。

AngularJS 简介及基础用法(双向数据绑定、依赖注入、模块对象、相关指令、动态练习)_第1张图片


第一个Angular程序

先看用jQuery实现的:


<html>
<head lang="en">
<meta charset="UTF-8">
<title>title>
head>
<body>

	<input type="text" id="name">
	<p>
		您输入的内容是:<span id="contentSpan">span>
	p>

	<script type="text/javascript" src="../../js/jquery/jquery-1.11.1.js">script>
	<script type="text/javascript">
		$(function() {
			$('#name').keyup(function() {
				var name = this.value;
				$('#contentSpan').html(name);
			})
		})
	script>
body>
html>

Angualar实现的:(可以明显看出比jQuery还精简)


<html>
<head lang="en">
<meta charset="UTF-8">
<title>title>
head>
<body ng-app>

	<input type="text" ng-model="username">
	<p>
		您输入的内容是:<span>{{username}}span>
	p>
	<script src="../../js/angular-1.2.29/angular.js">script>
	
body>
html>

说明:

  • ng-app(指令) : 告诉angular核心它管理当前标签所包含的整个区域,并且会自动创建$rootScope根作用域对象
  • ng-model : 将当前输入框的值与谁关联(属性名:属性值), 并作为当前作用域对象($rootScope)的属性
  • {{}} (表达式) : 显示数据,从作用域对象的指定属性名上取

1、表达式:通常有一个返回值,可以放在任何需要值的地方,比如函数调用的参数,一个变量名,一个运算。

2、语句:通常表示一个完整的执行单位,一段完整的js可执行的代码,有的语句也可以用表达式来执行,叫做表达式语句。

3、区别:语句用分号结尾,有些语句我们没有加分号,比如console.log虽然我们没有加分号,但也是语句,因为js引擎会自动解析并且加上分号。

AngularJS 简介及基础用法(双向数据绑定、依赖注入、模块对象、相关指令、动态练习)_第2张图片


四个重要概念

1. 双向数据绑定

  • 数据绑定: 数据从一个位置自动流向另一个位置(这个操作由框架来完成)
    • View–>Model
    • Model–>View
  • View(视图): 也就是我们的页面(主要是Angular指令和表达式)
  • Model(模型):作用域对象(当前为$rootScope), 它可以包含一些属性或方法
  • 单向数据绑定: 只支持一个方向
    • View–>Model : ng-init
    • Model–>View : {{name}}
  • 双向数据绑定:数据可以从View(视图层)流向Model(模型),也可以从Model流向View
    • Model<–>View : ng-model
    • angular是支持双向数据绑定的

说明:

  • 当改变View中的数据, Model对象的对应属性也会随之改变: ng-model指令 数据从View==>Model
  • 当Model域对象的属性发生改变时, 页面对应数据随之更新: {{}}表达式 数据从Model==>View
  • ng-model是双向数据绑定, 而{{}}是单向数据绑定
  • ng-init 用来初始化当前作用域变量。

现在通过该例应该对第一个AngularJS的程序的结构和用法有所了解了。也就是说:
通过设置ng-app(指令) ,它就会帮我们自动创建一个$rootScope根作用域对象。
通过设置ng-model 就可以将当前输入框的值当作新的属性值,传给对应的属性名(它是当前作用域对象($rootScope)的属性),从而修改这个属性名的属性值。
通过设置ng-init可以用来初始化当前作用域变量。
当我们想使用这个属性值的时候,使用{{属性名}}就可以显示数据。当然是从作用域对象的指定属性名上取。

当代码运行起来的时候,就会发现因为设置了ng-init,所以输入框和输出结果都会显示这个初始值。这其中,我们无法通过修改输出结果,即{{属性名}}来修改属性值,所以它是单向数据绑定(只能从Model流向View)。而我们显然可以通过修改输入文本框来修改属性值,即View流向Model(从页面上输入送到了作用域对象),所以ng-model是双向数据绑定(即能显示属性值,又能修改属性值)。而ng-init的值的变化也只能依靠其他方法的修改,所以它也是单向数据绑定(只能从View流向Model)。


<html>
<head lang="en">
<meta charset="UTF-8">
<title>02_(双向)数据绑定title>
head>
<body ng-app="" ng-init="name='tom'">
	
	<input type="text" ng-model="name">
	<p>姓名1:{{name}}p>
	<input type="text" ng-model="name">
	<p>姓名2:{{name}}p>

	<script type="text/javascript" src="../../js/angular-1.2.29/angular.js">script>
body>
html>

AngularJS 简介及基础用法(双向数据绑定、依赖注入、模块对象、相关指令、动态练习)_第3张图片
AngularJS 简介及基础用法(双向数据绑定、依赖注入、模块对象、相关指令、动态练习)_第4张图片


2. 依赖注入

  • 依赖对象:完成某个特定的功能需要某个对象才能实现,这个对象就是依赖对象。
  • 依赖对象会被别人(调用者)自动注入进入,注入的方式;
    • 内部自建:不动态
    • 全局变量:污染全局环境
    • 形参:这种最好
  • 依赖注入:依赖的对象以形参的形式被注入进来使用,这种方式就是依赖注入。
  • angular的 ‘$scope’对象就是依赖对象,并且是依赖注入的形式进行使用。
  • 形参名不能随便定义。形参必须是特定的名称, 否则Angular无法注入抛异常
    (只是针对当前这种写法)
  • 再比如,回调函数的event就是依赖对象,回调函数有形参就是依赖注入。

说明:在接下来的代码中,涉及到控制器对象。它是用来控制AngularJS应用数据的实例对象,是我们View与Model之间的桥梁。当我们使用了ng-controller指令,我们需要指定控制器的构造函数,这个形参必须是$scope。这里$scope就是依赖对象,被angular动态注入。然后Angular就会自动new此函数创建控制器对象。每定义一个ng-controller指令, 内部就会创建一个新的作用域对象($scope), 并自动注入构造函数中,在函数内部可以直接使用$scope对象。这就是依赖注入。


<html>
<head lang="en">
<meta charset="UTF-8">
<title>title>
head>
<body ng-app="">
	
	<div ng-controller="MyController">
		<input type="text" placeholder="" ng-model="firstName"> 
		<input type="text" placeholder="" ng-model="lastName">
		<p>输入的姓名为: {{firstName+'-'+lastName}}p>
		<p>输入的姓名2为: {{getName()}}p>
	div>
	<div>
		{{firstName}}
		
	div>
	
	<script type="text/javascript" src="../../js/angular-1.2.29/angular.js">script>
	<script type="text/javascript">
		function MyController($scope) {//必须是$scope, $scope就是依赖对象, 被angular动态注入的
			$scope.firstName = 'KB';
			$scope.lastName = 'Brent';

			//给域对象指定方法
			$scope.getName = function() {
				return $scope.firstName + "  " + $scope.lastName;
			};

			//声明式和命令式的区别
			//1.命令式:命令程序执行的时候每一步都是按照自己的指令,更注重执行的过程
			//2.声明式:更注重执行的结果。
			//命令式
			var arr = [ 1, 2, 3, 4, 5 ];
			var newArr = [];
			for (var i = 0; i < arr.length; i++) {
				var num = arr[i] * 2;
				newArr.push(num);
			}
			console.log(newArr);

			//声明式
			var newArr2 = arr.map(function(item) {
				return item * 2;
			});
			console.log(newArr2);
			//命令式更注重的执行的过程
			//声明式更注重的执行的结果
			//声明式是对命令式的局部包装
		}
	script>
	
body>
html>

3. MVC模式

  • M: Model, 即模型, 在angular中:
    • 为scope
    • 储存数据的容器
    • 提供操作数据的方法
  • V: View, 即视图, 在angular中:
    • 为页面
    • 包括: html/css/directive/expression
    • 显示Model的数据
    • 将数据同步到Model
    • 与用户交互
  • C: Controller, 即控制器, 在angular中:
    • 为angular的Controller
    • 初始化Model数据
    • 为Model添加行为方法

4. MVVM模式

  • M: Model, 即数据模型, 在angular中:
    • 为scope中的各个数据对象
  • V: View, 即视图, 在angular中:
    • 为页面
  • VM: ViewModel, 即视图模型, 在angular中:
    • 为scope对象
    • 在angular中controller不再是架构的核心,在MVVM中只是起辅助作用,用来辅助$scope对象,即VM层

三个重要对象

1. 作用域对象

  • 一个js实例对象,ng-app指令默认会创建一个根作用域对象($rootScope)
  • 这个对象的属性、方法, 页面都可以直接引用、操作

2. 控制器对象

  • 用来控制AngularJS应用数据的实例对象,是我们View与Model之间的桥梁
  • 当我们使用了ng-controller指令,我们需要指定控制器的构造函数(必须定义一个$scope的形参),然后Angular就会自动new此函数创建控制器对象
  • 每定义一个ng-controller指令, 内部就会创建一个新的作用域对象($scope), 并自动注入构造函数中,在函数内部可以直接使用$scope对象

<html>
<head lang="en">
<meta charset="UTF-8">
<title>title>
head>
<body ng-app="" ng-init="age=12">
	
	<div ng-controller="MyController">
		<input type="text" placeholder="" ng-model="firstName"> 
		<input type="text" placeholder="" ng-model="lastName">

		<p>输入的姓名为: {{firstName+'-'+lastName}}p>
		<p>输入的姓名2为: {{getName()}}p>
	div>

	<div>
		{{firstName}}
		
	div>

	<script type="text/javascript" src="../../js/angular-1.2.29/angular.js">script>
	<script type="text/javascript">
		function MyController($scope) {//必须是$scope
			// alert(this instanceof MyController);//说明是new调用
			$scope.firstName = 'KB';
			$scope.lastName = 'Brent';

			//给域对象指定方法
			$scope.getName = function() {
				return $scope.firstName + "  " + $scope.lastName;
			};

			console.log($scope.age);
		}
	script>
body>
html>

3. 模块对象 ※

  • 也是一个对象
  • 创建模块对象: angular.module('模块名', [依赖的模块])
    如: var module = angular.module('模块名',[]);
    (只要不涉及第三方模块,[]里就不用添加任何东西)
  • 通过模块添加控制器:
    • module.controller('MyController', function($scope){//操作$scope的语句})
  • angular的整体设计也是多模块的
    • 核心模块: angular.js
    • 扩展模块: angular-router.js, angular-message.js, angular-animate.js

说明:
在上段代码中,要生成作用域对象,是需要提前构造一个构造函数的,开发中不这么用,同时新版本也不支持这么用,所以现在选择模块对象。(这里选用angular-1.5.5版本)

angular.module可在全局位置创建、注册、获取Angular模块。所有模块(angular核心或第三方)都必须使用这个机制注册才能在应用中生效。

当我们获取到了模块,就可以通过module.controller('MyController', function($scope){//操作$scope的语句})的方式来添加控制器了。


<html>
<head lang="en">
<meta charset="UTF-8">
<title>title>
head>
<body ng-app="MyApp">

	<div ng-controller="MyCtrl">
		<input type="text" ng-model="empName">
		<p>员工名:{{empName}}p>
	div>

	<div ng-controller="MyCtrl1">
		<input type="text" ng-model="empName">
		<p>员工:{{empName}}p>
	div>

	<script type="text/javascript" src="../../js/angular-1.5.5/angular.js">script>
	<script type="text/javascript">
		//    console.log(angular,typeof angular);
		//    //创建当前应用的模块对象
		//      var module = angular.module('MyApp',[]);
		//      module.controller('MyCtrl',function ($scope) {
		//            $scope.empName = 'Tom';
		//      });
		//    module.controller('MyCtrl1',function ($scope) {
		//        $scope.empName = 'Jack';
		//    })

		//方法链调用
		//    angular.module('MyApp',[])//模块对象的方法执行完返回的就是模块对象本身
		//            .controller('MyCtrl',function ($scope) {//$scope写法问题(js代码压缩时会把所有的局部变量压缩成abcd等)
		//                $scope.empName = 'Tom';
		//            }).controller('MyCtrl1',function ($scope) {
		//                $scope.empName = 'Jack';
		//            })
		/*
		上面写法的问题:
		    1、形参只能写固定的变量名$scope;
		    2、一旦文件压缩,将不能使用,会报错。
		 */
		//改进
		angular.module('MyApp', [])
			.controller('MyCtrl',[ '$scope', function(a) { 
				a.empName = 'tom'
			} ])
			.controller('MyCtrl1', [ '$scope', function(b) {
				b.empName = 'Jack';
			} ])
	script>
body>
html>

两个页面语法

1. 表达式 ※

  • 语法: {{js表达式}}
  • 作用: 从作用域对象中读取对应的属性数据来显示数据
  • 注意: 表达式中引用的变量必须是当前域对象有的属性(包括其原型属性)
  • 不支持if/for/while
  • 支持三目表达式
  • 它能操作的数据:
    • 基本类型数据: number/string/boolean
    • undefined, Infinity, NaN, null解析为空串: “”, 不显示任何效果
    • 对象的属性或方法
    • 数组

<html>
<head lang="en">
<meta charset="UTF-8">
<title>title>
head>
<body ng-app="">
	

	<p>{{1}}p>
	<p>{{'尚硅谷'}}p>
	<p>{{true}}p>
	<p>{{undefined}}p>
	<p>{{'atguigu'+3}}p>
	<p>{{4+3}}p>

	<p ng-init="a=3;b=4">{{a+b}}p>

	<p ng-init="p={name:'Tom',age:12};arr=[true, 3, 'atguigu']">{{p.name}}---{{p.age}}----{{arr[2]}}p>

body>
<script type='text/javascript' src="../../js/angular-1.5.5/angular.js">script>
html>

2. 指令 ※

  • 什么是指令 : Angular为HTML页面扩展的,自定义标签属性或标签。
  • 作用:与Angular的作用域对象(scope)交互,扩展页面的动态表现力。
  • 常用的指令:
    • ng-app: 指定模块名,angular管理的区域
    • ng-model: 双向绑定,输入相关标签
    • ng-init: 初始化数据
    • ng-controller: 指定控制器构造函数名,内部会自动创建一个新的子作用域(外部的)
    • ng-bind: 解决使用{{}}显示数据闪屏(在很短时间内显示{{}})
    • ng-repeat: 遍历数组显示数据, 数组有几个元素就会产生几个新的作用域
      * $index, $first, $last, $middle, $odd, $even
    • ng-show: 布尔类型, 如果为true才显示
    • ng-hide: 布尔类型, 如果为true就隐藏
    • ng-class: 动态引用定义的样式 {aClass:true, bClass:false}
    • ng-style: 动态引用通过js指定的样式对象 {color:‘red’, background:‘blue’}
    • ng-click: 调用作用域对象的方法(点击时) 可以传$event
    • ng-mouseenter: 鼠标移入监听, 值为函数调用, 可以传$event
    • ng-mouseleave: 鼠标移出监听, 值为函数调用, 可以传$event

<html>
<head lang="en">
<meta charset="UTF-8">
<title>title>
<style>
	ul{
		list-style: none;
	}
style>
head>


<body ng-app="myApp">

	<div ng-controller="MyCtrl" ng-init="age=12">
		<div>
			<h2>价格计算器(自动)h2>
			数量:<input type="number" ng-model="count1"> 
			价格:<input type="number" ng-model="price1">
			<p>总计:{{count1 * price1}}p>
		div>

		<div>
			<h2>价格计算器(手动)h2>
			数量:<input type="number" ng-model="count2"> 
			价格:<input type="number" ng-model="price2">
			<button ng-click="getTotalPrice()">计算button>
			<p>总计:{{totalPrice}}p>
		div>

		
		<h3>人员信息列表h3>
		<ul>
			<li ng-repeat="person in persons">
			偶数行:{{$even}},奇数行:{{$odd}},中间的:{{$middle}},
			最后一个:{{$last}},第一个:{{$first}},第{{$index + 1}}个,
			{{person.name}}----{{person.age}}
			li>
		ul>

		
		
		<p ng-bind="count2">{{'asdfdsfds'}}p>
		<p>{{count2}}p>
		
		
		<button ng-click="switch()">切换button>
		<p ng-show="isLike">我喜欢p>
		<p ng-hide="isLike">喜欢我p>

	div>
	<script type='text/javascript' src='../../js/angular-1.5.5/angular.js'>script>
	<script type='text/javascript'>
    /*
     * ng-app: 指定模块名,angular管理的区域
     * ng-model: 双向绑定,输入相关标签
     * ng-init: 初始化数据
     * ng-click: 调用作用域对象的方法(点击时)
     * ng-controller: 指定控制器构造函数名,内部会自动创建一个新的子作用域(外部的)
     * */
    //创建模块对象
    angular.module('myApp', [])
            .controller('MyCtrl', ['$scope', function ($scope) {

                $scope.count1 = 1;
                $scope.price1 = 20;
                $scope.count2 = 1;
                $scope.price2 = 20;
                $scope.totalPrice = $scope.count1 * $scope.price1;
                $scope.getTotalPrice = function () {
                    $scope.totalPrice =  this.count2 * this.price2;
                };

                $scope.persons = [
                    {name : 'kobe', age : 39},
                    {name : 'anverson', age : 41},
                    {name : 'weide', age : 38},
                    {name : 'tim', age : 40},
                    {name : 'curry', age : 29}
                ];
                $scope.isLike = true;
                $scope.switch = function () {
                    $scope.isLike = !$scope.isLike;
                }
            }])
script>
body>
html>

<html>
<head lang="en">
<meta charset="UTF-8">
<title>title>
head>

<style>
.evenB {
	background-color: grey;
}

.oddB {
	background-color: green;
}

ul{
	list-style: none;
}

style>
<body ng-app="myApp" ng-controller="MyController">

	<div style="width: 100px; height: 100px; background-color: red"
		ng-mouseover="over()" ng-mouseleave="leave()" ng-style="myStyle">
	div>
	<div>
		<ul>
			<li ng-repeat="p in persons" ng-class="{evenB:$even, oddB:$odd}">
				{{p.name}}---{{p.age}}
			li>
		ul>
	div>

	<script type='text/javascript' src="../../js/angular-1.5.5/angular.js">script>
	<script type="text/javascript">
		angular.module('myApp', [])
			.controller('MyController',function($scope) {
					$scope.over = function() {
						$scope.myStyle = {
							background : 'blue'
						};
					};
					$scope.leave = function() {
						$scope.myStyle = {
							background : 'green'
						};
					};

					$scope.persons = [ {
						name : 'Tom',
						age : 12
					}, {
						name : 'Tom2',
						age : 13
					}, {
						name : 'Tom3',
						age : 14
					}, {
						name : 'Tom4',
						age : 15
					}, {
						name : 'Tom5',
						age : 16
					} ];
				});
	script>
body>
html>

练习一:我的笔记 ※


<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<style>
textarea {
	resize: none;
}
style>
head>
<body ng-app="noteApp" ng-controller="NoteController">

	<h2>我的笔记h2>
	<textarea cols="30" rows="10" ng-model="message">textarea>
	<div>
		<button ng-click="save()">保存button>
		<button ng-click="read()">读取button>
		<button ng-click="delete()">删除button>
	div>
	<p>剩余字数:{{getCount()}}p>

	<script type="text/javascript" src="../../js/angular-1.5.5/angular.js">script>
	<script type="text/javascript" src="app.js">script>
body>
html>

app.js

angular.module('noteApp', [])
    .controller('NoteController', function ($scope) {
    	
        $scope.message = '';
        //定义获取剩余字数的方法
        $scope.getCount = function () {
            //判断输入数据的长度
            if(this.message.length > 100){
                $scope.message = $scope.message.slice(0, 100);
            }
            //返回剩余字数的个数
            return 100 - $scope.message.length;
        };

        //定义保存的方法
        $scope.save = function () {
            alert('note is saved');
            //将数据保存到sessionStorage中
            sessionStorage.setItem('note_key', JSON.stringify($scope.message));
            //将输入内容清空
            $scope.message = '';
        };
        
        //定义读取的方法
        $scope.read = function () {
            $scope.message = JSON.parse(sessionStorage.getItem('note_key') || '[]');//对读取null做了处理
        };

        // 定义删除的方法
        $scope.delete = function () {
            $scope.message = '';
        };

    });

练习二:我的备忘录 ※


<html>
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body ng-app="todoApp">

	<div ng-controller="TodoControl">
		<h2>我的备忘录h2>
		<div>
			<input type="text" ng-model="newTodo">
			<button ng-click="add()">新增button>
		div>
		<div ng-repeat="todo in todos">
			<input type="checkbox" ng-model="todo.isChecked"> <span>{{todo.todo}}span>
		div>
		<button ng-click="delete()">删除选中的记录button>
	div>
	
	<script type="text/javascript" src="../../js/angular-1.5.5/angular.js">script>
	<script type="text/javascript" src="app.js">script>
body>
html>

app.js

angular.module('todoApp', [])
	.controller('TodoControl', function ($scope) {
		//初始化数据
		$scope.todos = [
			{todo : '吃饭', isChecked : false},
			{todo : '睡觉', isChecked : false},
			{todo : '打豆豆', isChecked : false}
		];

		//定义添加todo的方法
		$scope.add = function () {
			//判断添加的内容是否为空
			if(!$scope.newTodo){
				alert('输入的内容不能空');
				return
			}
			// 组合新的todo对象
			var todo = {
				todo : $scope.newTodo,
				isChecked : false
			};
			// 将新的对象添加到todos中
			$scope.todos.unshift(todo);
			//添加完将输入的内容清空
			$scope.newTodo = '';
		};

		//定义删除  todo 的方法
		$scope.delete = function () {
			//将$scope.todo的数据暂时保存
			var oldTodo = $scope.todos;
			//将$scope.todos的数据清空
			$scope.todos = [];
			//进行遍历
			oldTodo.forEach(function (item, index) {
				//将没被选中的todo添加到 $scope.todos 数组中
				if(!item.isChecked){
					$scope.todos.push(item);
				}
			});
		}
	});

你可能感兴趣的:(#,AngularJS,+,NodeJS,+,JS模块化)