zoukankan      html  css  js  c++  java
  • Angular开发者指南(二)概念概述

    template(模板):带有附加标记的模板HTML
    directives(指令):使用自定义属性和元素扩展HTML
    model(模型):用户在视图中显示的数据,并与用户进行交互
    scope(作用域):存储模型的上下文,以便控制器,指令和表达式可以访问它
    expressions(表达式):访问范围中的变量和函数
    compiler(编译器):解析模板并实例化指令和表达式
    filter(过滤器):格式化表达式的值以显示给用户
    view(视图):用户看到的内容(DOM)
    Data Binding(数据绑定):在模型和视图之间同步数据
    controller(控制器):视图后面的业务逻辑
    Dependency Injection:创建并连接对象和函数
    injector(注入器):依賴注入容器
    module(模块):一个用于应用程序不同部分的容器,包括控制器,服务,过滤器,配置Injector的指令
    service (服务):可重用的业务逻辑独立于视图
    第一个例子:数据绑定
    在下面的示例中,我们将构建一个表单来计算不同货币的发票成本。
    让我们从数量和成本的输入字段开始,其值相乘以产生发票总额:

    <div ng-app ng-init="qty=1;cost=2">
      <b>Invoice:</b>
      <div>
        Quantity: <input type="number" min="0" ng-model="qty">
      </div>
      <div>
        Costs: <input type="number" min="0" ng-model="cost">
      </div>
      <div>
        <b>Total:</b> {{qty * cost | currency}}
      </div>
    </div>
    

    这看起来像正常的HTML,有一些新的标记。 在AngularJS中,像这样的文件称为模板。 当AngularJS启动你的应用程序时,它使用编译器从模板解析和处理这个新的标记。 加载,转换和渲染的DOM然后称为视图。
    第一种新的标记是指令。 它们对HTML中的属性或元素应用特殊的行为。 在上面的例子中,我们使用ng-app属性,它链接到一个自动初始化我们的应用程序的指令。 AngularJS还定义了一个为元素添加额外行为的输入元素的指令。 ng-model指令存储/更新输入字段的值到/自变量。
    访问DOM的自定义指令:在AngularJS中,应用程序应该访问DOM的唯一位置是指令内。 这很重要,因为访问DOM的工件难以测试。 如果你需要直接访问DOM,你应该为它写一个自定义指令。
    第二种新的标记是双花括号{{expression | filter}}:当编译器遇到这个标记时,它将用标记的估计值替换它。 模板中的表达式是一个类似JavaScript的代码片段,它允许AngularJS读取和写入变量。 请注意,这些变量不是全局变量。 就像JavaScript函数中的变量存在于作用域中一样,AngularJS为表达式可访问的变量提供了一个作用域。 存储在作用域上的变量中的值在文档的其余部分中称为模型。 应用于上面的示例,标记指示AngularJS“获取从输入小部件获取的数据并将它们相乘”。
    上面的示例还包含一个过滤器。 过滤器格式化表达式的值以显示给用户。 在上面的示例中,过滤器货币将数字格式化为看起来像金钱的输出。
    在示例中重要的是,AngularJS提供活动绑定:每当输入值更改时,表达式的值都会自动重新计算,并使用其值更新DOM。 这背后的概念是双向数据绑定。
    添加UI逻辑:控制器

    invoice1.js

    angular.module('invoice1', [])
    .controller('InvoiceController', function InvoiceController() {
      this.qty = 1;
      this.cost = 2;
      this.inCurr = 'EUR';
      this.currencies = ['USD', 'EUR', 'CNY'];
      this.usdToForeignRates = {
        USD: 1,
        EUR: 0.74,
        CNY: 6.09
      };
    
      this.total = function total(outCurr) {
        return this.convertCurrency(this.qty * this.cost, this.inCurr, outCurr);
      };
      this.convertCurrency = function convertCurrency(amount, inCurr, outCurr) {
        return amount * this.usdToForeignRates[outCurr] / this.usdToForeignRates[inCurr];
      };
      this.pay = function pay() {
        window.alert('Thanks!');
      };
    });
    

    index.html

    <div ng-app="invoice1" ng-controller="InvoiceController as invoice">
      <b>Invoice:</b>
      <div>
        Quantity: <input type="number" min="0" ng-model="invoice.qty" required >
      </div>
      <div>
        Costs: <input type="number" min="0" ng-model="invoice.cost" required>
        <select ng-model="invoice.inCurr">
          <option ng-repeat="c in invoice.currencies">{{c}}</option>
        </select>
      </div>
      <div>
        <b>Total:</b>
        <span ng-repeat="c in invoice.currencies">
          {{invoice.total(c) | currency:c}}
        </span><br>
        <button class="btn" ng-click="invoice.pay()">Pay</button>
      </div>
    </div>
    
    

    首先,有一个包含控制器的新JavaScript文件。更准确地说,该文件指定将用于创建实际控制器实例的构造函数。控制器的目的是将变量和功能暴露给表达式和指令。
    除了包含控制器代码的新文件,我们还向HTML添加了ng-controller指令。这个指令告诉AngularJS,新的InvoiceController负责具有指令的元素和所有元素的子元素。语法InvoiceController作为凭证告诉AngularJS实例化控制器并将其保存在当前作用域中的变量invoice 中。
    我们还更改了页面中的所有表达式,以便在控制器实例中读取和写入变量,方法是在它们前面加上invoice 。 。可能的货币在控制器中定义,并使用ng-repeat添加到模板。由于控制器包含一个总函数,我们还可以使用{{invoice.total(...)}}将该函数的结果绑定到DOM。
    再次,这种绑定是活的,即,当函数的结果改变时,DOM将被自动更新。用于支付发票的按钮使用指令ngClick。这将在每次点击按钮时评估相应的表达式。
    在新的JavaScript文件中,我们还创建了一个模块,我们在其中注册控制器。我们将在下一节中讨论模块。
    下图显示了在我们介绍控制器之后,一切是如何协同工作的:
    图片描述

    独立于视图的业务逻辑:服务service
    现在,InvoiceController包含我们示例的所有逻辑。 当应用程序增长时,将与视图无关的逻辑从控制器移动到服务中是一个好的做法,因此它也可以由应用程序的其他部分重用。 稍后,我们还可以更改该服务以从网络(例如网络)载入汇率。 通过调用Yahoo Finance API,而无需更改控制器。
    让我们重构我们的例子,并将货币转换转换为另一个文件中的服务:

    finance2.js

    angular.module('finance2', [])
    .factory('currencyConverter', function() {
      var currencies = ['USD', 'EUR', 'CNY'];
      var usdToForeignRates = {
        USD: 1,
        EUR: 0.74,
        CNY: 6.09
      };
      var convert = function(amount, inCurr, outCurr) {
        return amount * usdToForeignRates[outCurr] / usdToForeignRates[inCurr];
      };
    
      return {
        currencies: currencies,
        convert: convert
      };
    });
    
    

    invoice2.js

    angular.module('invoice2', ['finance2'])
    .controller('InvoiceController', ['currencyConverter', function InvoiceController(currencyConverter) {
      this.qty = 1;
      this.cost = 2;
      this.inCurr = 'EUR';
      this.currencies = currencyConverter.currencies;
    
      this.total = function total(outCurr) {
        return currencyConverter.convert(this.qty * this.cost, this.inCurr, outCurr);
      };
      this.pay = function pay() {
        window.alert('Thanks!');
      };
    }]);
    

    index.html

    <div ng-app="invoice2" ng-controller="InvoiceController as invoice">
      <b>Invoice:</b>
      <div>
        Quantity: <input type="number" min="0" ng-model="invoice.qty" required >
      </div>
      <div>
        Costs: <input type="number" min="0" ng-model="invoice.cost" required >
        <select ng-model="invoice.inCurr">
          <option ng-repeat="c in invoice.currencies">{{c}}</option>
        </select>
      </div>
      <div>
        <b>Total:</b>
        <span ng-repeat="c in invoice.currencies">
          {{invoice.total(c) | currency:c}}
        </span><br>
        <button class="btn" ng-click="invoice.pay()">Pay</button>
      </div>
    </div>
    

    我们将convertCurrency函数和现有货币的定义移动到新文件finance2.js中。但是控制器如何保持现在分离的功能?
    这是依赖注入发挥作用的地方。依赖注入(DI)是一种软件设计模式,它处理对象和函数如何创建以及如何获得它们的依赖。 AngularJS中的所有内容(指令,过滤器,控制器,服务,...)都是使用依赖注入创建和连接的。在AngularJS中,DI容器称为注入器。
    要使用DI,需要一个地方,所有应该一起工作的东西都注册。在AngularJS中,这是模块的目的。当AngularJS启动时,它将使用具有由ng-app指令定义的名称的模块配置,包括该模块所依赖的所有模块的配置。
    在上面的示例中:模板包含指令ng-app =“invoice2”。这告诉AngularJS使用invoice2模块作为应用程序的主模块。代码片段angular.module('invoice2',['finance2'])指定invoice2模块依赖于finance2模块。通过这个,AngularJS使用InvoiceController以及currencyConverter服务。
    现在AngularJS知道应用程序的所有部分,它需要创建它们。在上一节中,我们看到控制器是使用构造函数创建的。对于服务,有多种方式指定如何创建它们(请参阅服务指南)。在上面的例子中,我们使用一个匿名函数作为currencyConverter服务的工厂函数。此函数应返回currencyConverter服务实例。
    回到最初的问题:InvoiceController如何获得对currencyConverter函数的引用?在AngularJS中,这是通过简单地定义参数的构造函数。这样,注入器能够以正确的顺序创建对象,并且将先前创建的对象传递到依赖于它们的对象的工厂中。在我们的示例中,InvoiceController有一个名为currencyConverter的参数。通过这个,AngularJS知道控制器和服务之间的依赖关系,并以服务实例作为参数来调用控制器。
    在上一节和本节之间的示例中,最后一件事情是改变了,现在我们将一个数组传递给module.controller函数,而不是一个简单的函数。数组首先包含控制器需要的服务依赖关系的名称。数组中的最后一个条目是控制器构造函数。 AngularJS使用这个数组语法来定义依赖关系,以便DI也可以在缩小代码后工作,这很可能会将控制器构造函数的参数名称重新命名为更短的。
    图片描述

    访问后端
    让我们通过从Yahoo Finance API获取汇率来完成我们的示例。 以下示例说明如何使用AngularJS完成此操作:

    invoice3

    angular.module('invoice3', ['finance3'])
    .controller('InvoiceController', ['currencyConverter', function InvoiceController(currencyConverter) {
      this.qty = 1;
      this.cost = 2;
      this.inCurr = 'EUR';
      this.currencies = currencyConverter.currencies;
    
      this.total = function total(outCurr) {
        return currencyConverter.convert(this.qty * this.cost, this.inCurr, outCurr);
      };
      this.pay = function pay() {
        window.alert('Thanks!');
      };
    }]);
    

    finance3.js

    angular.module('finance3', [])
    .factory('currencyConverter', ['$http', function($http) {
      var YAHOO_FINANCE_URL_PATTERN =
            '//query.yahooapis.com/v1/public/yql?q=select * from ' +
            'yahoo.finance.xchange where pair in ("PAIRS")&format=json&' +
            'env=store://datatables.org/alltableswithkeys';
      var currencies = ['USD', 'EUR', 'CNY'];
      var usdToForeignRates = {};
    
      var convert = function(amount, inCurr, outCurr) {
        return amount * usdToForeignRates[outCurr] / usdToForeignRates[inCurr];
      };
    
      var refresh = function() {
        var url = YAHOO_FINANCE_URL_PATTERN.
                   replace('PAIRS', 'USD' + currencies.join('","USD'));
        return $http.get(url).then(function(response) {
          var newUsdToForeignRates = {};
          angular.forEach(response.data.query.results.rate, function(rate) {
            var currency = rate.id.substring(3,6);
            newUsdToForeignRates[currency] = window.parseFloat(rate.Rate);
          });
          usdToForeignRates = newUsdToForeignRates;
        });
      };
    
      refresh();
    
      return {
        currencies: currencies,
        convert: convert
      };
    }]);
    

    index.html

    <div ng-app="invoice3" ng-controller="InvoiceController as invoice">
      <b>Invoice:</b>
      <div>
        Quantity: <input type="number" min="0" ng-model="invoice.qty" required >
      </div>
      <div>
        Costs: <input type="number" min="0" ng-model="invoice.cost" required >
        <select ng-model="invoice.inCurr">
          <option ng-repeat="c in invoice.currencies">{{c}}</option>
        </select>
      </div>
      <div>
        <b>Total:</b>
        <span ng-repeat="c in invoice.currencies">
          {{invoice.total(c) | currency:c}}
        </span><br>
        <button class="btn" ng-click="invoice.pay()">Pay</button>
      </div>
    </div>
    
    

    我们的financeConverter服务的财务模块现在使用$ http,AngularJS提供的内置服务访问服务器后端。 $ http是XMLHttpRequest和JSONP传输的包装器。

  • 相关阅读:
    Python·安装扩展包的几种方法
    Arduino系列硬件资源介绍
    树莓派USB摄像头的使用
    树莓派frp服务器和客户端配置教程
    树莓派frp内网穿透
    用Windows远程桌面连接树莓派的方法
    控制窗体的位置和大小
    树霉派更换软件镜像源
    I2C的库函数应用示例
    I2C总线的Arduino库函数
  • 原文地址:https://www.cnblogs.com/snoy/p/6498414.html
Copyright © 2011-2022 走看看