65.9K
CodeProject 正在变化。 阅读更多。
Home

第 2 部分:AngularJS 中的数据绑定

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.79/5 (55投票s)

2014年8月17日

CPOL

6分钟阅读

viewsIcon

229990

downloadIcon

5212

在本文中,我们将尝试理解 AngularJS 中的数据绑定。

引言

在前一篇文章 第一部分:AngularJS 简介 中,我们通过一个示例应用程序了解了一些介绍性内容和几个指令,以理解 AngularJS 的基础知识。所以我认为我们对 AngularJS 有些熟悉了,现在是时候深入了解它了。让我们继续本教程的这一部分,我们将尝试理解 AngularJS 最基本也是最令人印象深刻的功能,即 **数据绑定**。

背景

数据绑定是任何现有或即将出现的软件开发技术中最有用和最强大的功能。它实际上是一个在应用程序的视图和业务逻辑之间建立连接的过程。

基本上,我们将针对 AngularJS 应用程序介绍单向数据绑定和双向数据绑定。但是,在我们跳到该部分之前,我们将尝试了解一些关于 AngularJS 中作用域 (scopes) 的知识。

Angular 世界中的作用域

首先,让我们尝试了解 **作用域 (scope)**。我在上一篇文章中留下了这个话题,所以让我们继续,因为它与 AngularJS 应用程序有很大关系。**作用域** 是任何 AngularJS 应用程序的核心基础。由于它们在任何 AngularJS 应用程序中都随处可见,因此了解它们及其工作方式非常重要。在 AngularJS 中,**作用域** 是那些包含将在渲染视图时使用的数据和功能的对象的集合。应用程序的作用域引用应用程序模型,因此您可以将作用域视为 **视图模型**。

作用域是应用程序状态的真实来源。由于这种实时绑定,我们可以依赖 $scope 在视图修改它时立即更新,我们也可以依赖视图在 $scope 更改时
更新。

作用域的功能

  1. 提供观察者来监视所有模型更改
  2. 提供将模型更改传播到应用程序以及传播到系统外部其他关联组件的能力
  3. 作用域可以嵌套,以便它们可以隔离功能和模型属性
  4. 提供一个表达式进行评估的执行环境

关于作用域还有很多东西要了解,我们将在以后的文章中逐渐讨论作用域的生命周期,并了解它在浏览器内部如何处理请求/响应,当我们更深入地学习时。

基本数据绑定/单向数据绑定

单向数据绑定是一种将值从数据模型取出并插入 HTML 元素的方法。无法从视图更新模型。

AngularJS 提供了一些预定义的内置数据绑定指令,如下所示:

  • ng-bind – 绑定 HTML 元素的内部 Text 属性
  • ng-bind-template - 几乎与 ng-bind 指令相似,但允许使用多个模板
  • ng-non-bindable - 声明一个内容区域,其中将跳过数据绑定
  • ng-bind-html - 使用 HTML 元素的内部 HTML 属性创建数据绑定
  • ng-model - 创建双向数据绑定

让我们尝试通过编程方式理解一些指令,这将向您展示如何在实际应用场景中使用它们。我在上一篇文章 第一部分:AngularJS 简介 中创建了一个模块,我将使用它。我还会扩展同一个控制器。

这是我们的 app.js 文件

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

下面是我们的 maincontroller.js,我将其命名为“BookStore”。

app.controller("BookStore", function($scope)
     { 
        $scope.items = [
            {ISBN:"5674789", Name: "Asp.Net MVC", Price: 560, Quantity: 20},
            {ISBN:"4352134",Name: "AngularJS", Price: 450, Quantity: 25},
            {ISBN:"2460932",Name: "Javascript", Price: 180, Quantity: 15}
        ];
}); 

现在是我们的 html 页面,它将在您的浏览器中显示。

 <html ng-app="MyApp">
   <head>
      <title>Basic Binding App</title>
      <script src="angular.min.js"></script>
      <link rel="stylesheet" type="text/css" href="main.css" />
      <script src="app.js" type="text/javascript"></script>
      <script src="maincontroller.js" type="text/javascript"></script>
   </head>
   <body>
      <div ng-controller="BookStore">
         <table class="mytable">
            <tr>
               <td>
                  <span>Below output is produced from AngularJS's <strong>{{}}</strong> directive.</span>
               </td>
            </tr>
            <tr ng-repeat="item in items">
               <td>
                  <p> <b>{{item.Name}}</b> is in our stock.</p>
               </td>
            </tr>
         </table>
         <table class="mytable">
            <tr>
               <td>
                  <span>Below output is produced from AngularJS's <strong>ng-bind</strong> directive.
                  </span>
               </td>
            </tr>
            <tr ng-repeat="item in items">
               <td>
                  <p> <b><span ng-bind="item.Name"></span></b> is in our stock.</p>
               </td>
            </tr>
         </table>
         <table class="mytable">
            <tr>
               <td>
                  <span>Below output is produced from AngularJS's <strong>ng-non-bindable</strong> 
                        directive.</span>
               </td>
            </tr>
            <tr ng-repeat="item in items">
               <td>
                  <div ng-non-bindable>
                     <p> <b>{{item.Name}}</b> is in our stock.</p>
                  </div>
               </td>
            </tr>
         </table>
      </div>
   </body>
</html>

上面的示例说明了用于数据绑定的两个指令,即 **ng-bind** 和 **ng-non-bindable**。我们将在下一节介绍 **ng-model**,届时我们将讨论 AngularJS 中的双向绑定。我没有使用 ng-bind-templateng-bind-html,但当我们学习 AngularJS 中的模板化内容时,我们会深入研究它们。

这是运行 BasicBinding.html 时的最终输出。

从输出中,您可以看到当我们使用 {{ }} 时,输出符合预期,因为这是 AngularJS 处理模型绑定的默认方式。在第二部分,我们使用了数据绑定指令 **ng-bind**,第三部分我们使用的是 ng-non-bindable,它允许我们跳过对定义它的特定区域进行数据绑定。还有一个 ng-repeat-directive,它帮助我们遍历集合。我使用的集合可以通过某种 Web-Api 调用来实现,这些调用将提供一些 JSON 数据,您可以直接用于绑定。

双向数据绑定

简而言之,双向数据绑定是指当模型发生变化时,视图会反映出这种变化,反之亦然。AngularJS 中的双向绑定是通过 ng-model 指令创建的。实际上,双向绑定只能应用于允许用户提供数据值的元素,这意味着 inputtextareaselect 元素。

现在让我们看看如何在任何应用程序中实现双向绑定。添加一个新的 html 页面,就像我下面创建的一样。

<html ng-app="MyApp">
<head>
<title>Books</title>
 <script src="angular.min.js"></script>
    <link rel="stylesheet" type="text/css" href="main.css" />
    <script src="app.js" type="text/javascript"></script>
    <script src="maincontroller.js" type="text/javascript"></script>
</head>
<body>
<div>
        <div ng-controller="BookStore">
            <br />
            <div style="padding-top:15px;">
            <table border="1" class="mytable">
                    <tr>
                        <td>ISBN</td>
                        <td>Name</td>
                        <td>Price</td>
                        <td>Quantity</td>
                        <td>Total Price</td>
                        <td>Action</td>
                    </tr>
                
                
                    <tr ng-repeat="item in items">
                        <td>{{item.ISBN}}</td>
                        <td>
                           <span ng-hide="editMode">{{item.Name}}</span>
                           <input type="text" ng-show="editMode" 
                           ng-model="item.Name" />
                        </td>
                        <td>
                           <span ng-hide="editMode">{{item.Price}}</span>
                           <input type="number" ng-show="editMode" 
                           ng-model="item.Price"  />
                        </td>
                        <td>
                           <span ng-hide="editMode">{{item.Quantity}}</span>
                           <input type="number" ng-show="editMode" 
                           ng-model="item.Quantity"  /></td>
                        <td>{{(item.Quantity) * (item.Price)}}</td>
                        <td>
                             <span> <button type="submit" ng-hide="editMode" 
                             ng-click="editMode = true; editItem(item)" >Edit</button></span>
                             <span> <button type="submit" ng-show="editMode" 
                             ng-click="editMode = false">Save</button></span>
                             <span><input type="button" value="Delete" 
                             ng-click="removeItem($index)" /></span>
                        </td>
                    </tr>
                
            </table></div>
            <br />
            <div style="font-weight:bold">Grand Total: {{totalPrice()}}</div>
            <br />
        </div>
    </div>
</body>
</html>

现在扩展我们的控制器并实现一些功能,以在表格中显示项目,并允许用户执行编辑、保存和删除表格中的数据。由于在此应用程序中,我们没有使用任何 Web 服务或 Web API 将数据发布到服务器,因此我没有编写通过 Ajax 请求收集和发布数据到服务器的功能。随着我们前进,我们将尝试扩展使用某种 Web API 将数据发布到服务器的应用程序。

app.controller("BookStore", function($scope)
	 { 
		$scope.items = [
			{ISBN:"5674789", Name: "Asp.Net MVC", Price: 560, Quantity: 20},
			{ISBN:"4352134",Name: "AngularJS", Price: 450, Quantity: 25},
			{ISBN:"2460932",Name: "Javascript", Price: 180, Quantity: 15}
		];
                $scope.editing = false;
		
		$scope.totalPrice = function(){
			var total = 0;
			for(count=0;count<$scope.items.length;count++){
				total += $scope.items[count].Price*$scope.items[count].Quantity;
			}
			return total;
		}
		
		$scope.removeItem = function(index){
			$scope.items.splice(index,1);
		}
		$scope.editItem = function(index){
			 $scope.editing = $scope.items.indexOf(index);
			   
		}
		 $scope.saveField = function(index) {
        if ($scope.editing !== false) {
			$scope.editing = false;
        }       
    };         
    };
	}
	);

现在让我们编写一个函数来将从视图收集的项目添加到我们的表中。

$scope.addItem = function(item) {
			$scope.items.push(item);
			$scope.item = {};
		     }

为了使用此功能,我们需要一些东西来获取用户的输入。所以现在,我将添加 HTML 标签来获取输入。您可以看到我使用了 ng-model="item.ISBN" ,这实际上将为我们提供双向绑定功能。

<h2>Add New Book</h2>
<div style="border: 1px solid blue;">
   <table>
      <tr>
         <td>ISBN: </td>
         <td>
            <input type="text" ng-model="item.ISBN" />
         </td>
      </tr>
      <tr>
         <td>Name: </td>
         <td>
            <input type="text" ng-model="item.Name" />
         </td>
      </tr>
      <tr>
         <td>Price(In Rupee): </td>
         <td>
            <input type="number" ng-model="item.Price" />
         </td>
      </tr>
      <tr>
         <td>Quantity: </td>
         <td>
            <input type="number" ng-model="item.Quantity" />
         </td>
      </tr>
      <tr>
         <td colspan="2">
            <input type="Button" value="Add to list" ng-click="addItem(item)" />
         </td>
      </tr>
   </table>
</div> 

代码编写完毕。是时候看看我们的应用程序最终是什么样子了。这是您可以执行 CRUD 操作的结果。

注意:没有验证或任何错误检查。我故意留下了它们,因为我们将在 AngularJS 教程系列的验证部分,即第四部分,进行讲解。

关注点

现在我们了解了 AngularJS 所遵循的数据绑定方法,并且我们在示例应用程序中看到了如何在应用程序中实现它来执行基本的 CRUD 操作。我希望您从本教程部分学到了有价值的东西。您可以下载完整的应用程序代码并在您自己的机器上运行它。

在本教程系列的下一部分中,我们将介绍:

  • AngularJS 中的事件处理AngularJS 第三部分
  • AngularJS 第四部分:验证
  • AngularJS 第五部分:序列化
  • AngularJS 第六部分:模板化
  • AngularJS 第七部分:模块
  • AngularJS 第八部分:依赖注入
  • AngularJS 第九部分:自动化测试
  • AngularJS 第十部分:SPA 路由/历史记录
  • AngularJS 第十一部分:指令 - AngularJS 提供的一项功能
  • AngularJS 第十二部分:CSS 集成以创建精美的界面

历史

  • 2014 年 8 月 17 日:第一版
© . All rights reserved.