zoukankan      html  css  js  c++  java
  • Angular

    Angular

     

     

    前言

    简介

    Angular简称

    四个特性

    优点

    初尝试

    常用介绍

    指令

    说明

    ng-app

    ng-bind

    ng-repeat

    ng-class

    ng-show/ng-hide/ng-if:true/false

    ng-href/ng-src

    ng-switch

    ng-checked/ng-disabled/ng-readonly/ng-selected

    常用事件指令

    自定义指令

    控制器

    表达式

    闪烁问题

    表达式可承载的内容

    双向数据绑定

    $scope

     

     

    前言

    单一页面程序【SPA】体会:现在请你打开网易云的官网https://music.163.com,播放一首你最喜欢的歌曲,然后点击一下”我的音乐“,不知道这个过程你是否会想到这个问题:唉?我都点击一个资源了,页面并没有跳转也没有任何刷新的迹象,页面的头部没有改变,更重要的是你最喜欢的歌依旧没有任何停顿的在播放。不用我说你可能觉得这很简单,这不就是用ajax去做的吗?这有什么难的!没错,这个过程确实是用ajax去做的,那你该问这个Angular有个毛关系?关系不关系我们接着看!如果你足够细心,会发现当你点击“我的音乐”时,浏览器是没有刷新的,但是浏览器的地址栏却发生了一些细微的变化,在地址栏中出现了像是锚点的东西,不过我们的锚点不是常常指向一个dom元素的id吗?细看这个锚点后面的东西有些像一个路径,下面我们来扯一扯window对象的一个锚点切换事件你大概就略有所悟了。

    <script>
        (function (window) {
            // 每当锚点改变触发以下事件
            window.addEventListener('hashchange', function (e) {
                console.log(e);
                console.log(window.location);
                var hash = window.location.hash;
                
                // 网易锚点后的链接
                switch (hash) {
                    case '#/my/':
                        // ajax do somethings
                        break;
                    case '#/friend':
                        // ajax do somethings
                        break;
                    case '#/download':
                        // ajax do somethings
                        break;
                }
            })
        })(window)
    </script>

    说白了,还是使用ajax去请求后台,只不过是换了一种方式,使用锚点的方式触发了。

     

     

    简介

    来自百度百科的介绍:https://baike.baidu.com/item/SPA/17536313

    中文官网:https://www.angular.cn/

    API:https://docs.angularjs.org/api

    一个测试不同技术的模板:https://github.com/tastejs/todomvc-app-template

     

    Angular简称

    ng

     

    四个特性

     MVC

     模块化

     自动化双向数据绑定

     指令系统

     

    优点

     Angular最大程度的减少了页面上的DOM操作;

     JavaScript中专注业务逻辑的代码;

     通过简单的指令结合页面结构与逻辑数据;

     通过自定义指令实现组件化编程;

     代码结构更合理;

     维护成本更低;

     Angular解放了传统JavaScript中频繁的DOM操作;

     

    初尝试

    官网地址:https://docs.angularjs.org/tutorial/step_00

    插件:AngularJS Batarang自己去goole商店下载,可用来查看Angular一些数据渲染

     

    首先:所有需要ng管理的代码必须被包裹在一个有ng-app指令的元素中,ng-app是ng的入口,表示当前元素的所有指令都会被angular管理(对每一个指令进行分析和操作)。

    <body>
    <!--所有需要ng管理的代码必须被包裹在一个有ng-app指令的元素中,ng-app是ng的入口,
    表示当前元素的所有指令都会被angular管理(对每一个指令进行分析和操作)-->
    <div ng-app ng-init="_name='毛毛'"> <!--ng-init表示初始化一个默认值-->
        <!--在ng中定义一个模型-->
        <input type="text" ng-model="name">
        <!--在ng中使用定义的模型-->
        <p>你好,{{name}}</p>
    </div>
    <script src="../node_modules/angular/angular.js"></script>
    </body>

    代码解析:

     当网页加载完毕,AngularJS自动开始执行;

     HTML页面中ng-xxx的属性称之为指令(Directive);

     ng-app指令告诉AngularJS,<div>元素是AngularJS程序管理的边界;

     ng-model:是双向数据绑定的指令,效果就是将当前元素的value属性和模型中的name建立绑定关系。

     {{name}}表达式就是把应用程序变量name绑定到某个段落的innerHTML

    <!--如果ng-app中有模块名,则表示我这个div将由myApp这个模块管理,否则由angular管理-->
    <!--ng-controller中指明我这个模块将由AppController控制-->
    <div ng-app="myApp" ng-controller="AppController">
        <!--在ng中定义一个模型-->
        <input type="text" ng-model="user.name">
        <!--在ng中使用定义的模型-->
        <p>你好,{{user.name}}</p>
        <button ng-click="show()">点击</button>
    </div>
    <script src="../node_modules/angular/angular.js"></script>
    <script>
        (function () {
            var myApp = angular.module("myApp",[]);// 第二个参数数组表示可能引用的模块
            // 存在不能混淆压缩的问题
            myApp.controller("AppController",function($scope) { // $scope这个参数名称固定!代表上图中存储区块对象
                $scope.user = {};
                $scope.user.name = '毛毛';
                $scope.show = function() {
                    console.log($scope.user.name);
                }
            });
        })()
    </script>

    注册控制器存在的问题:在上面说了$scope是一个固定写死的参数,一旦更改名称,angular将不能识别注入!这就存在一个问题就是js压缩问题,我们都知道生产环境中可以使用未压缩的js文件,但是上线常常使用标识符混淆的压缩方式压缩代码,一旦使用标识符混淆,$scope就会被改变,angular又不能注入了。angular为了解决这个问题,声明了一种标准的写法:

    // 标准写法:
    myApp.controller("AppController",['$scope',function(a) { // 字符串'$scope'固定写法
                a.user = {};
                a.user.name = '毛毛';
                a.show = function() {
                    console.log(a.user.name);
                }
            }]);

    使用数组的方式,要求数组的最后一个元素是一个function,之前的元素对应该function中的参数,由于数组中存储的function参数是字符串类型而不是一个变量,就不会存在混淆压缩被替换的问题。

     

     

    常用介绍

    指令

    说明

     ng-xxx的属性本身并不是标准中定义的属性,很多情况下语法检验(W3C)是无法通过的

     HTML5允许扩展的(自制的)属性,以data-开头,在AngularJS中可以使用data-ng-xx来让网页对HTML5有效,这和直接在元素中使用ng-xx效果相同

     

    ng-app

    标记范围尽可能小,为了性能

    最好只出现一个ng-app,如果出现多个ng-app就需要手动引导,或模块带入方式实现

     

     

    ng-bind

    在下面讲到表达式的时候,在表达式中存在一个闪烁问题,解决这个问题我们还可以使用ng-bind中绑定数据,而不是直接在标签文本内部使用。

    你可以在其中绑定一些基本的数据,但是并不建议你去绑定html,因为这将带来不安全的操作,可能存在一些脚本攻击【假如你绑定的是某个用户评论的内容,该内容是一段js脚本用来获取你本地cookie信息模拟你登陆,窃取一些东西】。所以默认的你在ng-bind中所有的文本标签<,>将会被替换为<>,防止你绑定的数据是一个脚本。如果你非要去绑定一个标签内容,并想呈现标签的效果,你就要使用ng-bind-html,使用该标签你要求你使用angular提供的一种校验库sanitize,用以校验你绑定的内容是否安全。【即使这样,还是不推荐你去绑定html】

    <body ng-app ng-init="h='shif'">
        <p>{{h}}</p>
        <p ng-bind="h"></p><!--不会出现闪烁问题-->
        <script src="../../node_modules/angular/angular.js"></script>
    </body>
    <body ng-app="myApp" ng-init="exam='<h1>shif</h1>'">
        <p ng-bind-html="exam"></p>
        <script src="../../node_modules/angular/angular.js"></script>
        <script src="../../node_modules/angular-sanitize/angular-sanitize.js"></script>
        <script>
            (function () {
                var myApp = angular.module("myApp",["ngSanitize"])
            })();
        </script>
    </body>

    ng-repeat

    用来遍历一个数组重复创建当前元素。

    <body ng-app="myApp">
    <ul ng-controller="ULController">
        <li ng-repeat="item in data">
            <span>id:{{$id}}</span>
            <span>index:{{$index}}</span>
            <span>first:{{$first}}</span>
            <span>last:{{$last}}</span>
            <span>middle:{{$middle}}</span>
            <span>even:{{$even}}</span>
            <span>odd:{{$odd}}</span>
            <span>{{item.name}}</span>
        </li>
    </ul>
    <script src="../../node_modules/angular/angular.js"></script>
    <script>
        (function () {
            angular.module('myApp', []).controller('ULController', ['$scope', function ($scope) {
                $scope.data = [{name: '毛毛'}, {name: '吉吉'}, {name: '咪咪'}, {name: '可可'}];
            }])
        })();
    </script>

    如果遍历的元素存在重复的,则需要track by 一个不重复的量:

    <li ng-repeat="item in data track by $index">

    ng-class

    ng-class中可以写入一个对象,如下例中对象的key值表示现有的css样式属性名,对象的value为true或者false,表示是否起作用。ng-class还可以绑定model。

    <style>
            .red {
                color: red;
            }
    
            .green {
                color: yellow;
            }
        </style>
    </head>
    <body ng-app="myApp" ng-init="nnm='red'">
    <div ng-controller="ULController">
        <ul>
            <li ng-repeat="item in data"><!--隔行换色-->
                <span class="{{$even?'red':'green'}}">{{item.name}}</span>
            </li>
        </ul>
        <ul>
            <li ng-repeat="item in data"><!--隔行换色-->
                <span ng-class="{red:$even,green:$odd}">{{item.name}}</span>
            </li>
        </ul>
        <span ng-class="nnm">{{ 10+20 }}</span> <!--还可以绑定一个模型-->
    </div>
    
    <script src="../../node_modules/angular/angular.js"></script>
    <script>
        (function () {
            angular.module('myApp', []).controller('ULController', ['$scope', function ($scope) {
                $scope.data = [{name: '毛毛'}, {name: '吉吉'}, {name: '咪咪'}, {name: '可可'}];
            }])
        })();
    </script>

    ng-show/ng-hide/ng-if:true/false

    ng-show:决定是否显示

    ng-hide:决定是否隐藏

    ng-if:决定是否显示[不显示就删除]

    <body ng-app="myApp" ng-init="nnm='red'">
    <div ng-controller="ULController">
        <div class="hong" ng-show="show"></div>
        <div class="hong" ng-hide="show"></div>
        <div class="hong" ng-if="if"></div>
    </div>
    
    <script src="../../node_modules/angular/angular.js"></script>
    <script>
        (function () {
            angular.module('myApp', []).controller('ULController', ['$scope', function ($scope) {
                $scope.show = true;
                $scope.hide = false;
                $scope.if = false;
            }])
        })();
    </script>

    ng-href/ng-src

    ng-href/ng-src指令用于解决当链接类型的数据绑定时造成的加载BUG

    <body ng-app ng-init="url = '../images/123.png'">
    <img src="{{url}}" alt=""> // 在angular没起作用之前就开始发送了请求,所有控制台会报一个错
    <img ng-src="{{url}}" alt="">
    
    <script src="../../node_modules/angular/angular.js"></script>
    </body>

    ng-switch

    <div ng-app="myApp" ng-controller="AppController">
        <div ng-repeat="item in exam">
            <div ng-switch="item.name">
                <p ng-switch-when="Liu">刘</p>
                <p ng-switch-when="Li">李</p>
                <p ng-switch-when="Wang">王</p>
                <p ng-switch-default>赵</p>
            </div>
        </div>
    </div>
    <script src="../../node_modules/angular/angular.js"></script>
    <script>
        (function () {
            angular.module('myApp',[]).controller('AppController',['$scope',function ($scope) {
                $scope.exam = [{name:'Li'},{name:'Liu'},{name:'Zhao'},{name:'Wang'}]
            }]);
        })();
    </script>

    ng-checked/ng-disabled/ng-readonly/ng-selected

    ng-checked:单选/复选是否选中

    ng-disable:是否禁用

    ng-readonly:是否只读

    ng-selected:是否选中

    <!-- 双向绑定的,任意一个选中则全部选中 -->
    <input type="checkbox" ng-model="checked"><br/>
    <input type="checkbox" ng-model="checked">
    <input type="checkbox" ng-model="checked">
    <input type="checkbox" ng-model="checked">
    <!-- ng-model双向绑定的,ng-checked时模型到视图的绑定(单项),第一个选中全选中,其他选中只选中自己 -->
    <input type="checkbox" ng-model="checked"><br/>
    <input type="checkbox" ng-checked="checked">
    <input type="checkbox" ng-checked="checked">
    <input type="checkbox" ng-checked="checked">

    常用事件指令

    ng-blur:失去焦点

    ng-change:发生改变

    ng-copy:拷贝完成

    ng-click:单击

    ng-dbclick:双击

    ng-focus:得到焦点

    ng-blur:失去焦点

    ng-submit:表单提交

     

    自定义指令

    <head>
        <meta charset="UTF-8">
        <title>自定义指令</title>
        <link rel="stylesheet" href="../../node_modules/bootstrap/dist/css/bootstrap.css">
    </head>
    <body ng-app="myApp" ng-init="nnm='red'">
    <div ng-controller="ULController">
        <breadcrumb data="{{data}}"></breadcrumb>
    </div>
    
    <script src="../../node_modules/angular/angular.js"></script>
    <script>
        (function () {
            var myApp = angular.module('myApp', []);
            myApp.controller('ULController', ['$scope', function ($scope) {
                $scope.data = ['blogs','home','doc','index'];
            }]);
            /*自定义指令*/
            myApp.directive('breadcrumb',[function () {
                return {
                    scope:{
                        // data:'@' // 不能直接引用到该元素的data属性,因为直接拿到的是一个字符串,不是对象
                    },
                    // template:'<h1>xasx</h1>',
                    templateUrl:'./template.html',// 模板的地址
                    replace:true, // 是否是以替代的方式替换之前元素
                    link:function (scope,element,attributes) {
                        scope.data = JSON.parse(attributes.data);
                        // console.log(scope.data);
                    }
                }
            }])
        })();
    </script>

    上代码引用的template.html:

    <nav aria-label="breadcrumb">
        <ol class="breadcrumb">
            <li class="breadcrumb-item" ng-repeat="item in data track by $index">
                <a href="#" ng-if="$last == false ? true:false">{{item}}</a>
                <span ng-if="$last">{{item}}</span>
            </li>
        </ol>
    </nav>

    控制器

    控制器的三大作用:

    暴露数据

    暴露行为

    监视数据变化

    <body ng-app="Login"><!--这是angular管理的一个模块-->
    <table border="1" ng-controller="LoginController"><!--该模块的这一部分dom由LoginController控制-->
        <tr>
            <td>用户名:</td>
            <td><input type="text" ng-model="user.name"></td><!--双向绑定$scope中的数据模型-->
        </tr>
        <tr>
            <td>密码:</td>
            <td><input type="password" ng-model="user.password"></td><!--双向绑定$scope中的数据模型-->
        </tr>
        <tr>
            <td></td>
            <td><input type="button" value="登陆" ng-click="login()"></td><!--绑定$scope中的方法-->
        </tr>
        <tr>
            <td colspan="2">{{message}}</td>
        </tr>
    </table>
    <script src="../node_modules/angular/angular.js"></script>
    <script>
        var loginApp = angular.module("Login",[]);
        loginApp.controller("LoginController",['$scope',function ($scope) {
            // 数据
            $scope.user = {
                name:'',
                password:'',
            };
    
            $scope.message = '';
    
            // 行为数据
            $scope.login = function() {
                // ajax do somethings
                console.log($scope.user);
            };
    
            // 监视数据的行为,第一个参数为要监视的模型,第二个参数为一个function
            $scope.$watch('user.name',function (now,old) { // now表示模型的当前值,old表示模型的上一次值
                console.log(now,old);
                if(now) {
                    if (now.length < 7) {
                        $scope.message = '输入的用户名不合法!';
                    } else {
                        $scope.message = '';
                    }
                }else {
                    $scope.message = '请输入用户名!';
                }
            })
        }])
    </script>

    表达式

    表达式是单向数据绑定的。

     

    闪烁问题

    <body>
    <div ng-app ng-init="_name='毛毛'">
        <input type="text" ng-model="_name">
        <p class="ng-cloak">你好,{{_name}}</p>
    </div>
    <script src="../node_modules/angular/angular.js"></script>
    </body>

    依旧是最开始的例子,在goole里测试由于goole的缓存可能看不到,这个例子在火狐里面你就会发现,每次刷新时页面先出现“你好,{{_name}}”,然后又迅速的变成了“你好,毛毛”,查其原因,当然是由浏览器解析dom的顺序导致的,由于我们是在后面导出angular的,所以浏览器按照顺序解析会先出现“你好,{{_name}}”,然后当解析到angularJS时才将表达式里的内容替换掉的。当你把angularJS文件的引用放到最开始,就不会出现这个问题(如果你刷新的速度足够快,还是会出现闪烁问题)。

    Angular为了解决这个问题提供了一个属性标签ng-cloak,将存在表达式的标签上添加该属性,并且还要把angularJS文件的引用放在前面才行。

    当然还有另外一种解决方案使用css方式去控制,我们依旧使用angularJS提供的指令标签ng-cloak,然后写一段css代码:

    <head>
        <meta charset="UTF-8">
        <title>Angular</title>
        <style>
            [ng-cloak] {
                display: none;
            }
        </style>
    </head>
    <body>
    <div ng-app ng-init="_name='毛毛'">
        <input type="text" ng-model="_name">
        <p ng-cloak>你好,{{_name}}</p>
    </div>
    <script src="../node_modules/angular/angular.js"></script>
    </body>

    使用属性选择器先将该元素隐藏,等加载angularJS时,由angularJS渲染表达式,最后将标签显现出来。

    表达式可承载的内容

     //数字
    
    {{ 100 + 100 }}
    
     //字符串
    
    {{ 'hello' + 'world' }}
    
     //对象
    
    {{ user.name }}
    
     数组
    
    {{ data[0] }}
    
     //三元表达式
    
    {{ flag == true ? data[1] : data[2] }}

    双向数据绑定

    两个方向的数据自动同步:

    -模型($scope)发生变化自动同步到视图上

    -视图上的数据发生变化过后自动同步到模型上

     

     

    $scope

    $scope(上下文模型)

     视图和控制器之间的桥梁

     用于在视图和控制器之间传递数据

     利用$scope暴露数据模型

     

    前进时,请别遗忘了身后的脚印。
  • 相关阅读:
    Linux 的硬链接与软链接
    Django补遗(一)
    Django之Form组件
    Django进阶(三)
    Django进阶(二)
    Web请求提交页面--防重提交
    Lucene的搭建(3)
    Lucene的搭建(2)
    Redis-cluster集群搭建
    Redis安装
  • 原文地址:https://www.cnblogs.com/liudaihuablogs/p/13468542.html
Copyright © 2011-2022 走看看