AngularJS1.X版本基础

AngularJS 知识点:

DataBinding Providers Validators Directives 

Controllers Modules Expressions Factories

Services Filters Dependency Injection Scope 

AngularJS优缺点比较

优点

MVVM 数据和视图绑定,省去频繁操作jquery更新dom,自带了丰富的Angular指令,整体功能比较完善,包含模板,数据双向绑定,路由,模块化,服务,过滤器,依赖注入等所有功能

自定义Directive组件,组件化,模块化

引入后台开发的一些概念,MVC,服务,依赖注入 ,容易构建SPA单页面应用

文档丰富,生态圈相对较好,问题容易解决

缺点

相比jquery,代码侵入性过大,依赖太多而且剥离升级困难,另外与jquery组件冲突严重,需要$apply()

directive一些指令生命周期定义复杂,容易如门但学习曲线陡峭

本身有些自带指令ng-route不好用,要依赖第三方,ui router仍旧问题太多,复杂路由很难用

版本迭代变化太大,2.0完全颠覆以前东西,甚至都不能说是同一个框架,1.x设计有问题(同第一条)

MVVM

Module

<script src="../../../resources/plugin/angular/angular.min.js"></script>
var planApp = angular.module("planApp", ["pascalprecht.translate", "kendo.directives", "ds.directives", "ds.controls", "plan.controls", ‘ui.router‘, "oc.lazyLoad"]);
planApp.controller("frameController", function ($http, $scope, $timeout, $state, $translate, $filter, $rootScope) {
    //省略........
});

AngularJS允许我们使用angular.module()方法来声明模块,这个方法能够接受两个参数,第一个是模块的名称,第二个是依赖列表,也就是可以被注入到模块中的对象列表。

angular.module(‘myApp‘, []);

这个方法相当于AngularJS模块的setter方法,是用来定义模块的。

调用这个方法时如果只传递一个参数,就可以用它来引用模块。例如,可以通过以下代码来引用myApp模块:

angular.module(‘myApp‘)

这个方法相当于AngularJS模块的getter方法,用来获取对模块的引用。

注意第二个参数中ds.controls即总体组给的一些控件的依赖模块,plan.controls即预案自定义控件的依赖模块,pascalprecht.translate是多语言模块。

var planApp = angular.module("planApp");
planApp.controller("strContentCtrl", function($rootScope,$http,$scope,$timeout,$state,$stateParams,$transitions,$filter){
    //省略......
});    

 Module的使用

(Recommended Setup)推荐设置

大规模的应用,建议将自己的应用按照如下建议,拆分为多个module:

service module,用于声明service。

directive module,用于声明directive。

filter module,用于声明filter。

应用级别的module,依赖上述的module,并且包含初始化的代码。

自带指令

ng-app

ng-init <div ng-init=“quantity=1;price=5”> 不常用

ng-repeat

ng-model,ng-bind

ng-click

ng-show

ng-change

ng-focus

ng-src

ng-class

ng-include

ng-mouseover, ng-mouseout, ng-mouseleave,ng-mouseenter

Databinding及表达式

AngularJS 表达式

AngularJS 表达式写在双大括号内:{{ expression }}。

AngularJS 表达式把数据绑定到 HTML,这与 ng-bind 指令有异曲同工之妙。

AngularJS 将在表达式书写的位置"输出"数据。

AngularJS 表达式 很像 JavaScript 表达式:它们可以包含文字、运算符和变量。

实例 {{ 5 + 5 }} 或 {{ firstName + " " + lastName }}

推荐使用ng-bind, {{ expression }}在页面加载完成之前,页面会出现表达式的乱码

<div ng-app=""><p>姓名: {{ firstName + " " + lastName }} </p>
<p>总价: <span ng-bind="quantity * cost“ ></span></p></div>

Controller

<body ng-app="studyApp" ng-controller="frameController">
studyApp.controller("frameController", function ($http, $scope, $timeout, $state, $translate, $filter, $rootScope) {
    //省略......
});

一个页面或者一块独立功能区域都可以对应一个controller,即MVC中的C,页面model和相应页面的逻辑处理js,写在这里;

PS:$scope即当前controller的独立作用域,相关页面变量和方法可以放在里面,类似于jquery自执行函数的闭包,起到封闭作用域的作用

Factory

factory方式创建的服务,作用就是返回一个有属性有方法的对象。相当于:var f = myFactory();

//创建模型
var app = angular.module(‘myApp‘, []);
//通过工厂模式创建自定义服务
app.factory(‘myFactory‘, function ()) {
    var service = {};
    //定义一个Objedct对象
    service.name = "王子";
    var age; //定义一个私有化的变量
    //对私有属性写getter、setter方法
    service.setAge = function (newAge) {
        age = newAge;
    }
    service.getAge = function (newAge) {
        return age;
    }
    return service; //返回这个Object对象
});

Service即提供一个服务,可以认为是JAVA里面的一个Utils类,而且是static的,因为只会有一个实例。类似JS的自执行函数并且返回自身对象

 Provider

provider()是创建service最底层的方式,这也是唯一一个可以使用.config()方法配置创建service的方法;(angularjs translate即采用provider方式)

与 factory 和 service 稍有不同的是, provider 必须提供一个 $get 方法, $get 方法和 factory 要求是一致的, 即: 先定义一个对象, 给这个对象添加属性和方法, 然后返回这个对象;

provider()不同于service()和factory(),在注入其他的服务的时候不能在function()中依赖注入;

这是唯一能注入到config的service,这样定义的service在你开始注入之前就已经实例化,开发共享的模块的时候常常使用它,能够在使用之前进行配置,比如你可能需要配置你的服务端的url;

 Provider定义方法:

app.provider(‘MyProvider‘, function () {
    this.$get = function () {
        var result = {};
        result.greeting = ‘hello from provider‘;
        teturn result;
    }
});

使用方法:

Factory,Service,Provider区别总结

Factory返回的是一个对象,即设计模式的工厂模式,每次由工厂new一个对象;

Service返回的是this本身,只需要对this的对象及方法进行设置即可,只会实例化一次,相当于一个static的Utils类;

Provider返回的是一个$.get方法,主要作用还是可以config里提前配置,在service和factory之前执行;

 Filter

可以用在html标签表达式里面,比如自定义一个字符串过长省略号的过滤器

planControls.filter(‘cut‘, function() {
    return function(value, wordwise, max, tail) {
        if (!value) return ‘‘;

        max = parseInt(max, 10);
        if (!max) return value;
        if (value.length <= max) return value;
        //原方案未考虑到中英文字符串长度不同
        //value = value.substr(0, max);
        //wordWise:对于英文等有空格的短语,将残缺的单词去掉
        var realValue = ‘‘;
        var realLength = 0,
            len = value.length,
            charCode = -1;
        for (var i = 0; i < len; i++) {
            charCode = value.charCodeAt(i);
            if (charCode >= 0 && charCode <= 128)
                realLength += 1;
            else
                realLength += 2;
            if (realLength > max)
                break;
            else
                realValue += value.charAt(i);
        }
        if (wordwise) {
            var lastspace = realValue.lastIndexOf(‘ ‘);
            if (lastspace != -1) {
                realValue = realValue.substr(0, lastspace);
            }
        }
        return realValue + (tail || ‘ …‘);
    };
});

使用:

 <span title="{{plan.name}}" ng-bind="(plan.name| cut:true:20:‘...‘)">

Angular controller通信

此处只涉及同一个dom,单页面,采用事件通信方式

如果一个页面有多个dom,仍旧采用js iframe的方式

Controller通信采用事件方式,事件有两种,emit和broadcast:

broadcast方式与emit方式的区别:

broadcast方式一种广播模式,就是父级发送一个消息时间,子级controller里面监听这个消息事件的函数就会执行;

emit与$broadcast方式相反,是子级controller发布一个消息事件,父级controller监听的函数执行; 注意同一个controller里面都是可以捕获到消息事件的; 但平级之间不能,平级之间可以通过parent中继,先emit再broadcast,不过看有文档说broadcast耗资源过多,路由过于复杂时不宜过多使用

Directive自定义指令, 控件

Directive实现html标签的指令解析

一个例子:

<basicinfopoint show-score="true" ng-model="dataStore.basicPoint"></basicinfopoint>
planControls.directive(‘basicinfopoint‘, function() {
    return {
        restrict: ‘E‘,
        templateUrl: WLJS.getWebRoot() +
            "/views/study/directive/basicinfopoint.html",        replace: true,
        scope: {
            ngModel: "=",
            showScore: "="
        },
        controller: function($scope, $element, $filter) {
            $scope.init = function(point) {
                if (point > 10 || point < 0) {
                    return;
                }
                var cans = $(‘#basicInfoCanvas‘);
                var ctx = cans[0].getContext(‘2d‘);
                ctx.clearRect(0, 0, 300, 150);

                var bigx = 150;
                var bigy = 75;
                var bigr = 60;

                // 外圆轮廓
                ctx.beginPath();
                ctx.arc(bigx, bigy, bigr + 15, 0, 2 * Math.PI, false);
                ctx.strokeStyle = ‘#DCDCDC‘;
                ctx.lineWidth = 1;
                ctx.stroke();
                ctx.closePath();

                // 内圆底色
                ctx.beginPath();
                ctx.arc(bigx, bigy, bigr, 0, 2 * Math.PI, false);
                ctx.strokeStyle = ‘#DCDCDC‘;
                ctx.lineWidth = 10;
                ctx.stroke();
                ctx.closePath();

                // 内圆占比蓝色
                ctx.beginPath();
                ctx.arc(bigx, bigy, bigr, 1.5 * Math.PI, (1.5 + point / 10 * 2) *
                    Math.PI, false);
                ctx.strokeStyle = ‘#01A1FD‘;
                ctx.lineWidth = 10;
                ctx.stroke();
                ctx.closePath();
                // 占比头部小圆外圈
                var smallx = bigx +
                    Math.sin(Math.PI / 180 * (point / 10 * 360)) * bigr;
                var smally = bigy -
                    Math.cos(Math.PI / 180 * (point / 10 * 360)) * bigr;
                ctx.beginPath();
                ctx.arc(smallx, smally, 10, 0, 2 * Math.PI, false);
                ctx.fillStyle = ‘#FFFFFF‘;
                ctx.fill();
                ctx.closePath();
                // 占比头部小圆内圈
                ctx.beginPath();
                ctx.arc(smallx, smally, 10, 0, 2 * Math.PI, false);
                ctx.strokeStyle = ‘#01A1FD‘;
                ctx.lineWidth = 6;
                ctx.stroke();
                ctx.closePath();
                //文字
                ctx.font = ‘bold 20px "Microsoft YaHei"‘;
                ctx.fillStyle = "#01A1FD";
                ctx.fillText(point, bigx - 40, bigy - 5);

                ctx.font = ‘bold 16px "Microsoft YaHei"‘;
                ctx.fillStyle = "#01A1FD";
                // 弥补中文单个字符长度不够,本地化前面加空格\u0020无效的问题
                var pointString = $filter(‘translate‘)(‘Points‘);
                pointString = pointString.length > 3 ? pointString : ‘   ‘ + pointString;
                ctx.fillText(pointString, bigx - 10, bigy - 5);

                ctx.font = ‘16px "Microsoft YaHei"‘;
                ctx.fillStyle = "#9A9A9A";
                ctx.fillText($filter(‘translate‘)(‘Point‘), bigx - 20, bigy + 15);
            }
            $scope.$watch(‘ngModel‘, function() {
                $scope.init($scope.ngModel);
            });

            $scope.showAuditScoreWindow = function() {
                $scope.$emit("showAuditScoreWindow");
            }
        }
    };
});

restrict:

E: 表示该directive仅能以element方式使用,即:<my-dialog></my-dialog>

A: 表示该directive仅能以attribute方式使用,即:<div my-dialog></div>

EA: 表示该directive既能以element方式使用,也能以attribute方式使用

注意,命名规则,不要使用大写,html标签不支持大写,另外,“-”会被忽略

template或者templateUrl:  div or url

replace:  true or false

scope:

默认false直接使用父scope.

true:继承父scope.

{ }:创建一个新的“隔离”scope,通过绑定与父scope通信.

Scope绑定的策略,有3种:

@:单向绑定,外部scope能够影响内部scope,但反过来不成立,

只能当字符串传递,绑定外层scope的值

for-name="{{ Name }}"

scope:{

name:‘@forName‘

}

也可以这样写name:‘@‘, 这样写的话,就默认DOM中的属性名为name,即for-name="{{ Name }}"可简写为name="{{ Name }}";,另外两个符号=和&也有这样的简写规则,方便起见接下来都使用这种写法。

=:双向绑定,外部scope和内部scope的model能够相互改变,字符串和对象都可以

&:传递一个来自父scope的函数(即对父级作用域进行绑定,并将其中的属性(可以是任何属性)包装成一个函数),稍后调用;

<hello method="sayName(name)"></hello>

scope: {

method:‘&‘//得到了父scope的sayName()方法

},

Directive的生命周期:

compile,controller ,link:

compile and link function are used in different phases of the angular cycle

controllers are shared between directives

执行顺序:

controller->compile ->link

compile是对指令的模板进行替换,dom操作

link是再模型和视图中建立关联,注册监听事件

对于多个实例,compile只会执行一次,执行template替换,而link是每个实例执行一次

compile返回的是一个函数,即link函数,如果使用compile,link会被忽略

controllers用于多个指令的交互,和require结合使用

路由管理 ng-router

Angularjs自带路由ng-route,官方路由

<div ng-view>区块1</div>

<div ng-view>区块2</div>

$routeProvider

.when(‘/‘, {

template: ‘hello world‘

}); //不能指定ng-view

视图没有名字进行唯一标志,所以它们被同等的处理,不支持多视图路由

不支持嵌套路由

路由管理 UI-Router

https://ui-router.github.io/

多路由:

页面html引入,ui-view后面即路由id

路由定义,每一个路由{ }里面面都可以定义url,template,cache,controller等配置

子路由相应的js和css引入方式:

html加载时一次性引入,写在一个文件里面,或者用webpack之类的打包工具

oclazyload之类的第三方组件,动态加载

planApp.config([
    "$stateProvider",
    function ($stateProvider, $scope) {
        $stateProvider.state(
            stepurl[0], {
                url: stepurl[0],
                templateUrl: actionType != "view" ? ‘../../../views/study/planinformationedit.html‘ : ‘../../../views/study/publishedplaninformation.html‘,                cache: ‘false‘,
                params: {
                    id: plan_id,
                    actionType: actionType,
                    scene: scene
                },
                resolve: {
                    load: [
                        ‘$ocLazyLoad‘,
                        function ($ocLazyLoad) {
                            return $ocLazyLoad.load([actionType != "view" ? ‘../../../resources/js/study/planinformationedit.js‘ : ‘../../../resources/js/study/publishedplaninformation.js‘, ]);                        }
                    ]
                }
            }).state(
            stepurl[1], {
                url: stepurl[1],
                templateUrl: ‘../../../views/study/publishedplanstructuredcontent.html‘,                cache: ‘false‘,
                params: {
                    id: plan_id,
                    actionType: actionType,
                    scene: scene
                },
                resolve: {
                    load: [
                        ‘$ocLazyLoad‘,
                        function ($ocLazyLoad) {
                            return $ocLazyLoad.load([‘../../../resources/js/study/publishedplanstructuredcontent.js‘, ]);                        }
                    ]
                }
            }).state(stepurl[2], {
            url: stepurl[2],
            templateUrl: ‘../../../views/study/publishedplanworkflow.html‘ + "?id=" + plan_id + "&actionType=" + actionType,            cache: ‘false‘,
            params: {
                id: plan_id,
                actionType: actionType,
                scene: scene
            },
            resolve: {
                load: [‘$ocLazyLoad‘, function ($ocLazyLoad) {
                    return $ocLazyLoad.load([‘../../../resources/js/study/publishedplanworkflow.js‘, ‘../../../resources/js/study/flownodefig.js‘]);                }]
            }
        })

    }
]);

 嵌套路由

主页面及路由定义

一级子页面PageTab.html

二级子页面page1.html和page2.html

路由跳转方式

Ui-serf html超链接

<a ui-sref="parent">点我显示父view内容</a>

<a ui-sref="parent.child">点我显示父view与子view内容</a>

Js跳转

$state.go (‘parent.child’, parms, {reload:true}):

// $state.go 只刷新子路由有bug

// $state.go("a.b",{},{reload:"a.b"})api文档说是只刷新b路由,

// 但当前已经是a.b路由的时候, 此时有需要重复进入自路由,即从a.b到a.b,但a.b==a.b, reload子路由不会执行

// 增加一级三级路由,$state.go("a.b.c",{},{reload:"a.b"}),

// 此时当前路由a.b.c!=a.b,可以绕过此bug

// reload是强制刷新,true或者false, 后面加url实现刷新子路由改变了reload的含义,reload本身失效,Github提过issue,无果

Angular与Jquery一些思考

在用angularjs时,必须先知道的,angularJs 本身设计与Jquery不一样,甚至是冲突的,Jquery是尽量方便的让开发着操作DOM,呈现页面给用户;而angualrjs更注重数据的页面展示及mvvm, 强调一个原则,即所有界面都是自定义控件directive构成,对dom的操作都要封装在directive里面进行,controller要避免操作dom;jquery的控件和angularjs一起会遇到很多问题,jquery的控件不会触发mvvm绑定,有时候;

jquery也极其容易封装自定义控件,控件的封装并不是angular的特色;jquery因其拥有对dom操作的简单方便特性, 同时开发者没有强调控件的封装,很多初学者在页面js里面随意操作dom,造成js代码很乱,不规范;这并不是jquery的缺陷,而是使用者的问题。

对DOM的操作是基础,开发人员还是要熟悉; angularJS的一些指令集的实现,比如ng-repeat, 里面也是对dom的操作,不过其用了jquery的一个简化后轻量级版本,叫jqlite,和jquery大同小易, 方法名也差不多;angularjs不推荐用jquery来操作元素,个人认为,看个人喜好,jquery的应用更广泛,个人开发者没有必要再换个小众版本的jqlite;

Angularjs版本迭代太快,angular1.0和angular2.0是整体架构设计的变更,完全不向下兼容,甚至  严格来说并不是一套框架; 而且,angualrjs对代码侵入性太大,学习曲线陡峭,所以相对的对 angularjs的使用要慎重,框架还是太重了,存在和jquery控件兼容性及取舍问题。

PS:个人更倾向于Vue作者尤雨溪,渐进式前端解决方案;即:有些框架算是工具,他们的存在是为了帮助我们应对系统复杂度,增加开发效率;所以,在框架的复杂度和带来的开发效率中要做一个权衡,如果框架使用过于复杂,代码侵入新过大,要慎重选择;angularjs1.x有些设计过于复杂,不易学习使用,2.x进行了大部分重构和优化,借鉴了 Vue、React等的一些设计;大家有空可以看下其他优秀前端框架;angular1.x与2.x以后的版本基本不能算一个东西;

试想不用angularjs,我们的勤务,预案这些系统是不是保证代码质量下,开发效率更快,性能更好?

原文地址:https://www.cnblogs.com/Alwaysbecoding/p/11840895.html

时间: 2024-10-21 11:46:04

AngularJS1.X版本基础的相关文章

linux发行版本基础目录命名及功能

linux发行版本基础目录命名及功能 目录配置标准 FHS 因为目前linux distribution的种类繁多,而且负责开放的团队及公司也很多. 为了让用户可以了解到已安装软件通常的存放位置,所以为了规范linux的目录结构就推出了FHS(filesystem hierarchy standard)文件系统层次化标准,同时保证了在遵循FHS的同时,各个linux发行版的开发者可以根据自己的意图开发出想要的独特风格. FHS定义出根文件下存放的目录及内容 /bin:所有用户可用的基本命令程序文

Angularjs1.2版本与1.3版本中控制器的问题

写写今天用ng遇到的一个问题吧.因为刚学习就学视频里面写例子,视频里用的是ng1.2.10版本,我用的是1.5.0. 刚开始的时候我按照ng视频的里面的写,但是控制器就是不能绑定好,后来和同学讨论加搜索终于解决了,接下来看解释:从ng1.3开始就不支持全局的controller,这话怎么理解,ng1.3以前的版本我们设定好控制器后就可以直接在我们要引入的文件中直接引用而不报错.1.3以后 的版本后再直接引用就会报错,错误描述:Error [ng:areq]http://errors.angula

AngularJS1.6版本中ui-router路由中/#!/的解决方法 - zhuan

本地编译出的文件可以正常运行,但是服务器编译后到了测试那里路由上就莫名的出现了/#!/,这导致了很多问题. 后来查了下是服务器编译器把AngularJS升级到了1.6版本,而我本地的依旧是1.5. 但是1.6究竟做了哪些改变呢? 可以参考这个:https://github.com/angular/angular.js/commit/aa077e81129c740041438688dff2e8d20c3d7b52 可以看到里面多了很多/#!/的改动.. 如果想让路由依旧表现的与之前版本的一致可以这

angularjs1.x版本,父子组件之间的双向绑定

今天遇到了一个angularjs的坑, ng-repeat和ng-if会改变他所包含的html中绑定变量的作用域. angularjs自定义指令,可以定义四种变量,通过 =,@,&双向绑定,单项绑定,回调函数绑定 如果在ng-repeat 或者ng-if的包含的内容中,调用其它自定义组件,并传输双向绑定的变量时,需要查看当前作用域时什么,需要$parent返回到$scope作用域才能拿到需要绑定的变量 原文地址:https://www.cnblogs.com/HappyYawen/p/88681

Vue 2.6版本基础知识概要(一)

挂载组件 //将 App组件挂载到div#app节点里 new Vue({ render: h => h(App), }).$mount('#app') VueComponent.$mount 封装组件 <template> <div id="app"> Hello Vue </div> </template> <script> export default { name: 'app', } </script>

Java核心技术 卷Ⅰ 基础知识(1)

第三章 Java的基本程序设计结构 Java对大小写敏感 命名规范为骆驼命名法,不能使用保留字 main方法必须声明为public 如果main方法正常退出,java应用程序的退出代码为0,表示成功运行了程序.如果希望终止程序时返回其他代码,那就需要调用System.exit方法. Java通用语法是 object.method(parameter),这等价于函数调用 System.out.print输出不换行 三种注释方式 //. /*  */(不能嵌套).第三种可以用来自动生成文档 Java

Android各个版本代号及其特性

本帖最后由 cosplayking 于 2014-10-20 21:46 编辑 Android1.1 2008 年9月发布的Android第一版 Android1.5 Cupcake (纸杯蛋糕) 2009年4月30日,官方1.5版本(Cupcake 纸杯蛋糕)的Android发布. 主要的更新如下: 1.拍摄/播放影片,并支持上传到Youtube 2.支持立体声蓝牙耳机,同时改善自动配对性能 3.最新的采用WebKit技术的浏览器,支持复制/贴上和页面中搜索 4.GPS性能大大提高 5.提供屏

Hadoop版本说明

由于Hadoop版本混乱多变,Hadoop的版本选择问题一直令很多初级用户苦恼.本文总结了Apache Hadoop和Cloudera Hadoop的版本衍化过程,并给出了选择Hadoop版本的一些建议. 1. Apache Hadoop 1.1  Apache版本衍化 截至目前(2012年12月23日),Apache Hadoop版本分为两代,我们将第一代Hadoop称为Hadoop 1.0,第二代Hadoop称为Hadoop 2.0.第一代Hadoop包含三个大版本,分别是0.20.x,0.

如何在openWRT系统上实现双版本

最近由于项目需要,需要在AR9331芯片单板(原来是4MBFlash,后来扩充到16MB Flash)上,实现openwrt双版本机制. 双版本的好处,主要是:在升级版本过程中,如果遇到断电等情况,不至于导致设备无法启动.因为至少有一个版本是完好的,虽然可能旧了一点. 基于此需求,需要实现的功能,包括: 1.改造uboot,能识别此款16MB Flash 2.改造uboot,能找到Flash中的所有可引导的内核版本,以及对应的rootfs:并选择合适的(较新的)内核进行引导 3.在rootfs中