angular数据绑定与监控(学习笔记)

本文详细介绍了Angular中的数据双向绑定,包括基于单一模型的界面同步、对模型的二次解析,以及数组和对象结构的绑定。通过ng-repeat指令处理数组数据,同时讲解了如何处理含有重复值的数组和多维数组。此外,文章还讨论了数据监控的深度监控方法,样式的数据绑定,状态控制如ng-show和ng-if,以及数据联动的实现。最后,总结了数据绑定在不同场景的应用及其核心——数据驱动视图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据的双向绑定


angular实现了双向绑定机制,所谓双向绑定,就是从界面的操作能实时反映到数据,数据的变更能实时展现到界面.


基于单一模型的界面同步

ng-model 指令:
可以将输入域的值与 AngularJS 创建的变量绑定。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>
<div ng-app="myApp" >
<span style="white-space:pre">	</span>名字: <input ng-model="name">
<br/>{{name}}</div>
<script>
var app = angular.module('myApp', []);
</script>


</body>
</html>


在angular中,变量和表达式都依附在一种叫做作用域(scope)的东西上.每个angular应用默认会有一个根作用域($rootScope),如果在界面中绑定未定义的变量,当它被赋值的时候,就会自动创建到对应的作用域上.

"{{}}"这种符号,称为插值表达式,这里面的内容将会被动态解析.除了"{{}}"angular还提供了ng-bind来实现一样的功能.

对模型的二次解析

有的时候,我们需要在界面上显示性别,男/女,但是在数据库里面存的是0或者1,那么我们就要对它进行一些转换.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
<div>{{formatGender(tom.gender)}}</div>
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
		$scope.tom = {
    name: "Tom",
    gender: 1,
    genderText: "男"
};	
	$scope.formatGender = function(gender) {
    if (gender == 0){
        return "女";
	}
    if (gender == 1){
        return "男";
    }
};	
	
});
</script>

</body>
</html>

我们这里利用表达式使用函数的方法对数据进行格式化,其实只是作用于视图层,不会影响到真实数据模型.

注意:

1:在绑定表达式里面,只能使用自定义函数,不能使用原生函数.

<div>{{Math.abs(-1)}}</div>

以上是错误的例子,如果确实需要调用原生函数,可以用一个自定义函数作包装,在自定义函数里面可以随意使用各种原生对象.


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
<div>{{abs(-1)}}</div>
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.abs = function(number) {
    return Math.abs(number);    
};
});
</script>
</body>
</html>

2:上面这个格式化数据的例子只是为了说明可以这么用,但不表示这是最佳方案.angular为这类需求提供了filter方案,可以在"{{}}"表达式中使用管道操作符来格式化数据.

{{expression | filterName : parameter1 : ...parameterN}}

数组与对象结构的绑定

有的时候,我们需要把一个数组的数据展示出来,这可以使用ng-repeat指令来处理,它相当于一个循环.

单一数组数据

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<button ng-click="add()">Add Item</button>
<ul>
    <li ng-repeat="item in arr1">{{item}}</li>
</ul>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.arr1 = [1, 2, 3];

$scope.add = function() {
    $scope.arr1.push($scope.arr1.length + 1);
};
});
</script>

</body>
</html>


这样就可以把数组的内容展示到界面上.数组中的数据变化时,也能实时更新到界面上来.

但有时候,我们会遇到数组里有重复元素的情况,这时候,ng-repeat代码就不能起作用,原因是angular默认需要在数组中使用唯一索引,如果这遇到这情况,那就可以指定它使用序号作为索引即可.

含有重复值的数组数据

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
<button ng-click="add()">Add Item</button>
<ul>
    <li ng-repeat="item in arr1 track by $index">{{item}}</li>
</ul>
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.arr1 = [1,1,1,1, 2, 3];

$scope.add = function() {
    $scope.arr1.push($scope.arr1.length + 1);
};
});
</script>


</body>
</html>


多维数组

可以用多层循环方式迭代出来:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
<ul>
    <li ng-repeat="childArr in arr3 track by $index">
        {{$index}}
        <ul>
            <li ng-repeat="item in childArr track by $index">{{item}}</li>
        </ul>
    </li>
</ul>
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.arr3 = [
    [11, 12, 13],
    [21, 22, 23],
    [31, 32, 33]
];
});
</script>


</body>
</html>

数组元素是对象

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">

<table class="table table-bordered">
    <thead>
    <tr>
        <th>Name</th>
        <th>Age</th>
    </tr>
    </thead>
    <tbody>
    <tr ng-repeat="child in arr4">
        <td>{{child.name}}</td>
        <td>{{child.age}}</td>
    </tr>
    </tbody>
</table>
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.arr4 = [{
    name: "Tom",
    age: 5
}, {
    name: "Jerry",
    age: 2
}];
});
</script>


</body>
</html>

遍历对象属性

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
<ul>
    <li ng-repeat="(key, value) in obj">{{key}}: {{value}}</li>
</ul>
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.obj = {
    a: 1,
    b: 2,
    c: 3
};
});
</script>


</body>
</html>


如果单纯想要值,也可以不用这么麻烦,直接用数组的写法即可,就算有对象值重复,也不用像数组那样需要指定$index做索引,因为它是对象的key来做索引的,这是不会重复的.你见过两个同名的属性?


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
<ul>
    <li ng-repeat="key in obj"> {{key}}</li>
</ul>
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.obj = {
    a: 1,
    b: 2,
    c: 3
};
});
</script>


</body>
</html>


数据监控

有时候,我们不是直接把数据绑定到界面上,而是先要赋值到其他变量上,或者针对数据的变更,做出一些逻辑的处理,这时候就要用到监控.

简单监控的例子

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
	<button ng-click="changeA()">click me</button>
	//{{a}}
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.a = 1;

$scope.$watch("a", function(newValue, oldValue) {
    alert(oldValue + " -> " + newValue);
});

$scope.changeA = function() {
    $scope.a++;
};
});
</script>


</body>
</html>

对作用域上的变量添加监控后,就可以在变量变更时候得到通知了.如果说新赋值的变量和原先的相同,这个监控就不会被执行.

以上这种方式可以监控到最直接的赋值,包括各种基本类型,以及复杂类型的引用赋值,比如说下面这个数组被重新赋值了,就可以被监控到:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
	<button ng-click="changeArr()">click me</button>
	{{a}}
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.arr = [0];

$scope.$watch("arr", function(newValue) {
    alert("change:" + newValue.join(","));
});

$scope.changeArr = function() {
    $scope.arr = [7, 8];
};
	
});
</script>


</body>
</html>


但这种监控方式只能处理引用相等的判断,对于一些更复杂的监控,需要更细致的处理。比如说,我们有可能需要监控一个数组,但并非监控它的整体赋值,而是监控其元素的变更:

$scope.$watch("arr", function(newValue) {
    alert("deep:" + newValue.join(","));
}, true);

$scope.addItem = function() {
    $scope.arr.push($scope.arr.length);
};


注意,这里我们在$watch函数中,添加了第三个参数,这个参数用于指示对数据的深层监控,包括数组的子元素和对象的属性等等。


样式的数据绑定

以上我们提到的例子,都是跟数据同步,数据展示相关,但数据绑定的功能远不止于此.

我们再来一个例子:

有个数据表,点中其中某条,这条就改变样式.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
<style>
	ul{list-style:none}
	.active{
		color:red
	}
	</style>
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
	
<ul class="list-group">
    <li ng-repeat="item in items" ng-class="{true:' active', false: ' '}[item==selectedItem]" ng-click="select(item)">
        {{item.title}}
    </li>
</ul>
	
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {

	    $scope.items = [];

    for (var i=0; i<10; i++) {
        $scope.items.push({
            title:i
        });
    }

    $scope.selectedItem = $scope.items[0];//默认为第一项

    $scope.select = function(item) {
        $scope.selectedItem = item;//一点击就把传入的item赋值给selectedItem
    };
	
	
	
});
</script>



</body>
</html>

本例中我们使用一个循环来迭代数组中的元素,并且使用一个变量selectedItem用于标识选中项.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">	
<input type="number" ng-model="x" ng-init="x=12"/>
<div ng-style="{'font-size': x+'pt'}">
    测试字体大小
</div>
	
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
	
});
</script>
</body>
</html>

除了使用ng-class,还可以用ng-style来对样式进行控制.


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
<style>
	ul{list-style:none}
	.active{
		color:red
	}
	</style>
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
	
<input type="number" ng-model="x" ng-init="x=12"/>
<div ng-style="{'font-size': x+'pt'}">
    测试字体大小
</div>
	
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {

	
	
});
</script>



</body>
</html>


状态控制

有时候,我们除了控制普通的样式,还可以控制某个界面元素的显示隐藏,我们用ng-class或者ng-style,当然也可以控制元素的显示隐藏,但angular给我们提供了一种快捷方式,那就是ng-show/ng-hide.


利用数据绑定,我们可以很容易实现原有的一些显示隐藏功能.

<button ng-show="selectedItem">有选中项的时候可以点我</button>
<button ng-hide="selectedItem">没有选中项的时候可以点我</button>

流程控制


除了使用ng-show/ng-hide来控制元素的显示隐藏,还可以使用ng-if.

所谓的show和hide,意味着DOM元素已经存在,只是控制了是否显示,而if则起到了流程控制的作用,只有符合条件的DOM元素才会被创建,否则不创建。


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
	
  <ul>
        <li ng-if="condition==1">if 1</li>
        <li ng-if="condition==2">if 2</li>

        <li ng-show="condition==1">show 1</li>
        <li ng-show="condition==2">show 2</li>
    </ul>

    <button ng-click="change()">change</button>
	
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
   $scope.condition = 1;

    $scope.change = function() {
        $scope.condition = 2;
    };
	
});
</script>



</body>
</html>


这个例子初始时候,就创建了3个li,其中一个被隐藏(show2),点击按钮,仍然是3个li,其中,if1被销毁了,if2被创建出来了,show1被隐藏了,show2显示出来了.



所以,我们看到ng-if的节点是动态创建出来的,与此类似,还有ng-switch指令:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
	
    <div ng-switch="condition">
        <div ng-switch-when="A">A</div>
        <div ng-switch-when="B">B</div>
        <div ng-switch-default>default</div>
    </div>
    <button ng-click="a()">A</button>
    <button ng-click="b()">B</button>
    <button ng-click="c()">C</button>
	
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
   $scope.condition = "";

    $scope.a = function() {
        $scope.condition = "A";
    };

    $scope.b = function() {
        $scope.condition = "B";
    };

    $scope.c = function() {
        $scope.condition = "C";
    };
	
});
</script>



</body>
</html>


数据联动

最典型的例子就是省市县三级联动.


我们来看这样一个例子:

有两个表,第一个的数据变动,对第二个的数据产生过滤.


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
<span style="white-space:pre">	</span><style>
<span style="white-space:pre">		</span>.active{color:red}
<span style="white-space:pre">	</span></style></head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
    <ul class="list-group">
        <li ng-repeat="province in provinceArr" ng-class="{true:'list-group-item active', false: 'list-group-item'}[province==selectedProvince]" ng-click="selectProvince(province)">
            {{province}}
        </li>
    </ul>
    <ul class="list-group">
        <li ng-repeat="city in cityArr" ng-class="{true:'list-group-item active', false: 'list-group-item'}[city==selectedCity]" ng-click="selectCity(city)">
            {{city}}
        </li>
    </ul>

	
</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
    $scope.provinceArr = ["江苏", "云南"];
    $scope.cityArr = [];

    $scope.$watch("selectedProvince", function(province) {//监听<span style="font-family: Arial, Helvetica, sans-serif;">selectedProvince值的</span>变化
        // 真正有用的代码在这里,实际场景中这里可以是调用后端服务查询的关联数据
        switch (province) {
            case "江苏": {
                $scope.cityArr = ["南京", "苏州"];
                break;
            }
            case "云南": {
                $scope.cityArr = ["昆明", "丽江"];
                break;
            }
        }
    });

    $scope.selectProvince = function(province) {
        $scope.selectedProvince = province; //选中给样式
    };

    $scope.selectCity = function(city) {
        $scope.selectedCity = city;//选中给样式
    };
	
});
</script>



</body>
</html><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
<span style="white-space:pre">	</span><style>
<span style="white-space:pre">		</span>.active{color:red}
<span style="white-space:pre">	</span></style>
<span style="white-space:pre">	</span></head>
<body>


<div ng-app="myApp" ng-controller="myCtrl">
    <ul class="list-group">
        <li ng-repeat="province in provinceArr" ng-class="{true:'list-group-item active', false: 'list-group-item'}[province==selectedProvince]" ng-click="selectProvince(province)">
            {{province}}
        </li>
    </ul>
    <ul class="list-group">
        <li ng-repeat="city in cityArr" ng-class="{true:'list-group-item active', false: 'list-group-item'}[city==selectedCity]" ng-click="selectCity(city)">
            {{city}}
        </li>
    </ul>


<span style="white-space:pre">	</span>
</div>


<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
    $scope.provinceArr = ["江苏", "云南"];
    $scope.cityArr = [];


    $scope.$watch("selectedProvince", function(province) {//监听selectedProvince值的变化
        // 真正有用的代码在这里,实际场景中这里可以是调用后端服务查询的关联数据
        switch (province) {
            case "江苏": {
                $scope.cityArr = ["南京", "苏州"];
                break;
            }
            case "云南": {
                $scope.cityArr = ["昆明", "丽江"];
                break;
            }
        }
    });


    $scope.selectProvince = function(province) {
        $scope.selectedProvince = province; //选中给样式
    };


    $scope.selectCity = function(city) {
        $scope.selectedCity = city;//选中给样式
    };
<span style="white-space:pre">	</span>
});
</script>






</body>
</html>


如果绑定到下拉框上,代码更简单

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<select class="form-control col-md-6" ng-model="selectedProvince" ng-options="province for province in provinceArr"></select>
<select class="form-control col-md-6" ng-model="selectedCity" ng-options="city for city in cityArr"></select>
<span style="white-space:pre">	</span>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
    $scope.provinceArr = ["江苏", "云南"];
    $scope.cityArr = [];

    $scope.$watch("selectedProvince", function(province) {//监听selectedProvince值的变化
        // 真正有用的代码在这里,实际场景中这里可以是调用后端服务查询的关联数据
        switch (province) {
            case "江苏": {
                $scope.cityArr = ["南京", "苏州"];
                break;
            }
            case "云南": {
                $scope.cityArr = ["昆明", "丽江"];
                break;
            }
        }
    });

<span style="white-space:pre">	</span>
});
</script>

</body>
</html>

从这个例子,我们看到,相比传统前端开发方式那种手动监听事件,手动更新DOM的方式,使用angular数据绑定做数据联动真的太容易了.如果把这个例子改造成三级联动,只需要对selectedCity也做一个监控就可以了.


小结

刚刚我们已经看到数据绑定的各种使用场景了,数据绑定一切的核心就是数据.数据变更导致页面的更新,如果我们想要更新界面,只需修改数据即可.






来自

https://github.com/xufei/blog/issues/14






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值