AngularJS

作者: 欢欣的膜笛 | 来源:发表于2021-02-20 18:03 被阅读0次

AngularJS 是什么

  • 概念:
    • AngularJS主要用于构建单页面Web应用,是一种构建动态Web应用的结构化框架。
  • 核心功能:
    • 模块化、双向数据绑定、语义化标签、依赖注入(行内注入、推断式注入)、$http等。

AngularJS模块(使用angular.module()方法来声明模块)

  • 优点:
    • 保持全局命名空间的清洁;
    • 编写测试代码更容易,并能保持其清洁,以便更容易找到互相隔离的功能;
    • 易于在不同应用间复用代码;
    • 使应用能够以任意顺序加载代码的各个部分。

实现模型-视图的双向绑定

  • 数据绑定就是数据与视图的一一对应关系,模板引擎为单向绑定,AngularJS为双向绑定
  • 通过model建立数据模型,视图上的数据就会对应存储在angular程序里,视图上的数据变化会同步到model,model的数据改变也会同步到视图
  • 脏检查机制(dirty-checking)是实现双向数据绑定的重要基础。
  • 脏检查机制:Angular将双向绑定转换为一堆watch表达式,然后递归这些表达式检查是否发生过变化,如果变了则执行相应的watcher函数(指view上的指令,如ng-bind,ng-show等或是{{}})。等到model中的值不再发生变化,也就不会再有watcher被触发,一个完整的digest循环就完成了。
  • 脏检查机制的触发:Angular中在view上声明的事件指令,如:ng-click、ng-change等,会将浏览器的事件转发给scope上相应的model的响应函数。等待相应函数改变model,紧接着触发脏检查机制刷新view。从第一轮到所有数据稳定称为一个完整的digest循环。当循环结束后,才把模型的变化结果更新到dom中去,防止频繁的dom操作。
    <input type="text" ng-model="msg"> 
    <!-- 视图——>模型 -->

    <h1 ng-bind="msg"></h1>
    <!-- 模型——>视图 -->

    <h1>{{msg}}</h1>
    <!-- 模型——>视图 -->

引入第三方路由模块 ngRoute 配置路由实现单页面开发

  • SPA(Single Page Application)指的是通过单一页面展示所有功能,通过Ajax动态获取数据然后进行实时渲染,结合CSS3动画模仿原生App交互。
    //配置路由
    var Yike = angular.module('Yike',['ngRoute','Controllers']);
    Yike.config(['$routeProvider',function($routeProvider){
        $routeProvider.when('/today',{
            //今日一刻
            templateUrl:'./views/today.html',
            controller:'TodayCtrl'
        }).when('/settings',{
            //设置
            templateUrl:'./views/settings.html',
            controller:'SettingsCtrl'
        }).otherwise({
            redirectTo:'/today'
        });
    }]);

理解MVC、MVVM开发模式

  • MVC(Model View Controller,模型(数据保存)视图控制器):一种软件架构设计模式,它将表现从用户交互中分离出来。通常来讲,模型中包含应用的数据和与数据进行交互的方法,视图将数据呈献给用户,而控制器则是二者之间的桥梁。
    • View 传送指令到 Controller
    • Controller 完成业务逻辑后,要求 Model 改变状态
    • Model 将新的数据发送到 View,用户得到反馈
  • MVP(Model-View-Presenter):把MVC中的Controller换成了Presenter(呈现),目的就是为了完全切断View跟Model之间的联系,由Presenter充当桥梁,做到View-Model之间通信的完全隔离。各部分之间的通信,都是双向的。
  • MVVM(Model-View-ViewModel):将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。唯一的区别是,它采用双向绑定(data-binding):View和Model之间没有联系,通过ViewModel进行交互,而且Model和ViewModel之间的交互是双向的,因此视图的数据的变化会同时修改数据源,而数据源数据的变化也会立即反应到View上。如js框架Knockout、AngularJS等。

使用directive自定义指令、验证表单字段

    app.directive('tag',function(){
        return {
            //指令调用方式:E:element,C:class,M:mark,A:attribute
            restrict:"ECMA",
            //为true时M显示,不写或为false不显示。是否替换原始标签
            replace:true,
            //指令内容
            template:'<h1>你好 angular</h1>',
            //加载外部文件,需通过服务器访问
            //templateUrl:'./header.html'
        }
    });
    <form name="myForm">
        <div class="form-group">
            <label for="">User name:</label>
            <input type="text" class="form-control" name="userName" ensure-unique="username" ng-model="user.name" required>
            <span class="error" ng-show="myForm.userName.$error.unique">Required!</span>
        </div>
        <div class="form-group">
            <label for="">Last name:</label>
            <input type="text" class="form-control" name="lastName" ng-model="user.last" ng-minlength="3" ng-maxlength="10">
            <span class="error" ng-show="myForm.lastName.$error.minlength">Too short!</span>
            <span class="error" ng-show="myForm.lastName.$error.maxlength">Too long!</span>
        </div>
        <div class="form-group">
            <label for="">User age:</label>
            <input type="text" class="form-control" name="userAge" ng-model="user.age" even required>
            <span class="error" ng-show="myForm.userAge.$error.even">数字必须是偶数</span>
        </div>
    </form>
    angular.module('MyApp', [])
    .controller('ExampleController', ['$scope', function ($scope) {}])
    .directive('even',function(){
        return {
            restrict:"A",
            require:"ngModel",
            link:function(scope,ele,attrs,ngModelController){
                //$parsers的值是一个由函数组成的数组,其中的函数会以流水线的形式被逐一调用。ngModel从DOM中读取的值会被传入$parsers中的函数,并依次被其中的解析器处理。
                ngModelController.$parsers.push(function(viewValue){
                    if(viewValue % 2 === 0){
                        //通过$setValidity()函数设置表单的合法性
                        ngModelController.$setValidity('even',true);
                    }else{
                        ngModelController.$setValidity('even',false);
                    }
                    return viewValue;
                });
            }
        }
    })
    .directive('ensureUnique', ['$http','$timeout','$window',function($http,$timeout,$window) {
        return {
            restrict:"A",
            require: 'ngModel',
            link: function(scope, ele, attrs, ngModelController) {
                scope.$watch(attrs.ngModel, function(n) {
                    if (!n) return;
                    $timeout.cancel($window.timer);
                    $window.timer = $timeout(function(){
                        $http({
                            method: 'get',
                            url: '/api/checkusername/', //根据换成自己的url
                            params:{
                                "username":n
                            }
                        }).success(function(data) {
                            //这个取决于你返回的,其实就是返回一个是否正确的字段,具体的这块可以自己修改根据自己的项目
                            ngModelController.$setValidity('unique', data.isUnique);
                        }).error(function(data) {
                            ngModelController.$setValidity('unique', false);
                        });
                    },500);
                });
            }
        };
    }]);

自定义指令参数

  • restrict:EACM,默认A
  • terminal:true或false,告诉AngularJS停止运行当前元素上比本指令优先级低的指令。但同当前指令优先级相同的指令还是会被执行
  • template:一段HTML文本或一个可以接受两个参数的函数,参数为tElement和tAttrs,并返回一个代表模板的字符串
  • templateUrl
  • replace:true或不写。默认值意味着模板会被当作子元素插入到调用此指令的元素内部
  • scope:
    • false:直接调用相同的作用域对象
    • true:从当前作用域对象继承一个新的作用域对象
    • {}:创建一个同当前作用域相隔离的作用域对象

广播

使用$httpProvider对请求进行拦截实现权限管理

  • http服务的基础中间件,用来向应用的业务流程中注入新的逻辑。拦截器的核心是服务工厂,通过向httpProvider.interceptors数组中添加服务工厂,在$httpProvider中进行注册。
    //创建拦截器,可以在服务中添加一种或多种拦截器
    angular.module('myApp', []).factory('myInterceptor', function($q) {
        var interceptor = {
            //请求拦截器进行调用。它可以对设置对象进行修改
            'request': function(config) {
                // 成功的请求方法
                return config; // 或者 $q.when(config);
            },
            //对响应拦截器进行调用。它可以对响应进行修改
            'response': function(response) {
                // 响应成功
                return response; // 或者 $q.when(config);
            },
            //在上一个请求拦截器抛出错误时调用此拦截器
            'requestError': function(rejection) {
                // 请求发生了错误,如果能从错误中恢复,可以返回一个新的请求或promise
                return rejection; // 或新的promise
                // 或者,可以通过返回一个rejection来阻止下一步
                // return $q.reject(rejection);
            },
            //在上一个响应拦截器抛出错误时调用此拦截器
            'responseError': function(rejection) {
                // 请求发生了错误,如果能从错误中恢复,可以返回一个新的响应或promise
                return rejection; // 或新的promise
                // 或者,可以通过返回一个rejection来阻止下一步
                // return $q.reject(rejection);
            }
        };
        return interceptor;
    });
    //将实现的拦截器加入到$httpProvider.interceptors数组中,一般在config方法中进行
    myApp.config(['$httpProvider',function($httpProvider) {
        $httpProvider.interceptors.push(myInterceptor);
    }]);

使用angular-translate实现国际化

  • i18n(Internationalization):国际化,在不改变源码的情况下,通过某些简单的配置就能适应不同的语言环境。
  • l10n(Localization):本地化,针对某一些语言进行定制化。
  • angular-translate是一款应用简单、上手容易的国际化服务。它提供了很多的特性:
    • 以组件化的方式形成国际化
    • 异步加载国际化数据
    • 使用messageFormat支持多元化
    • 使用接口提高可扩展性
  • translate中指令是通过过滤器实现的,过滤器是通过服务实现的。
  • 如果使用了requireJS这种异步加载服务,那么需要声明angular-translate与angular的依赖关系
  • 本地化
    shim: {
        angular_translate:{
          deps: ['angular'],
          exports: 'angular_translate'
        }
    }
    <div>
        <h1>{{ 'TITLE' | translate }}</h1>  //以过滤器的方式使用
        <span translate="FOO"></span>  //指令的方式使用
    </div>
    var app = angular.module("MyApp",['pascalprecht.translate']);
    app.config(['$translateProvider',function($translateProvider){
        //添加翻译表格
        $translateProvider.translations('en',{
            'TITLE':'Hello',
            'FOO':'This is a paragraph'
        });
        $translateProvider.translations('zh',{
            'TITLE':'你好',
            'FOO':'这是一幅图'
        });
        //设置首选语言
        $translateProvider.preferredLanguage('zh');
    }]);
  • 运行时切换语言
    app.controller('TranslateController', ['$translate','$scope',function($translate, $scope) {
        $scope.changeLanguage = function(langKey) {
            $translate.use(langKey);
        }
    }]);
    <div ng-controller="TranslateController">
        <button ng-click="changeLanguage('de')" translate="TITLE"></button>
        <button ng-click="changeLanguage('en')" translate="FOO"></button>
    </div>

相关文章

网友评论

      本文标题:AngularJS

      本文链接:https://www.haomeiwen.com/subject/kwunxltx.html