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传输的包装器。

  • 相关阅读:
    spring mvc给参数起别名
    聊聊分布式定时任务中间件架构及其实现--转
    Batch Normalization的算法本质是在网络每一层的输入前增加一层BN层(也即归一化层),对数据进行归一化处理,然后再进入网络下一层,但是BN并不是简单的对数据进行求归一化,而是引入了两个参数λ和β去进行数据重构
    终端安全工具 gartner 排名
    When Cyber Security Meets Machine Learning 机器学习 安全分析 对于安全领域的总结很有用 看未来演进方向
    DNS隧道之DNS2TCP实现——dns2tcpc必须带server IP才可以,此外ssh可以穿过墙的,设置代理上网
    DNS隧道之DNS2TCP使用心得教程——是可以用来穿透qiang的,ubuntu下直接apt install dns2tcp
    DNS隧道工具汇总——补充,还有IP over DNS的工具NSTX、Iodine、DNSCat
    Data Mining and Machine Learning in Cybersecurity PDF
    ES failed to notify ClusterStateListener java.lang.IllegalStateException: environment is not locked
  • 原文地址:https://www.cnblogs.com/snoy/p/6498414.html
Copyright © 2011-2022 走看看