AngularJS初级入门实践

Angular

配置

模块

Angular项目流程: 模块化(分工合作) + 自动构建工具(优化性能与代码)

主模块与分模块方式开发;
最后利用Gulp合并,压缩,重命名JS;

格式:

//-----------------模块化开发-------------
ng-app="lagouApp"//主模块的名称 主模块是整个程序的作用域
//定义一个主模块
var app = angular.module("lagouApp", ["app2", "app3", "app4", "app5"]);
//定义分模块
  var app4 = angular.module("app4", [])
  //定义分模块的控制器
  app.controller("footerCtrl", function($scope) {
      //点击事件
      $scope.link = function() {
          console.log(666);
      };
      $scope.img =['../../img/weui/icon_tabbar.png','../../img/weui/icon_tabbar.png','../../img/weui/icon_tabbar.png']
  });

//-----------------自动构建工具-----
<!-- 合并后的分模块 -->
    <script src="dist/js/main.js"></script>
    <!-- 分模块 -->
    <!-- <script src="controller/headerCtrl.js"></script>
    <script src="controller/swiperCtrl.js"></script>
    <script src="controller/listCtrl.js"></script>
    <script src="controller/footerCrel.js"></script> -->

注意:

angular规定依附在$scope上的数据才能传递给视图

只要$scope定义了,{{}}对应显示对应的值

比如:$scope=>{{}} $scope.name=>{{name}}
angular表达式很像js表达式:它们可以包含文字、运算符和变量

指令

内置指令

>ng-XX="" //内置指令
    ng-app //定义主模块的作用域
    ng-controller //定义分模块的控制器
    ng-init //初始化应用程序数据(定义数据放在HTML标签内)
    ng-click = "function()" //点击事件执行对应的函数
    ng-bind = "name"// ==> 等同于{{name}} 代替表达式的写法 
    //常用
    ng-model="value"//双向绑定(双方数值都能互相改变彼此);此指令只能配合input select textarea标签使用
    ng-repeat = " arr in arrays" //"单项数组 in 整个数组"   
    
    ng-show = "bool" //"布尔值" 真则显示,反之则隐藏 适合频繁绑定事件的环境
    ng-if = "bool" //增加/删除DOM节点    不适合频繁绑定事件的环境;
    ng-class = "{'am-active':page===n}" //ng-class接受的对象,键名是类名,键值是布尔值,如果右边的布尔值为真,那左边的类就出现,反之就隐藏
    
    //其他
    ng-src="{{路径}}"
    ng-href="{{路径}}"
    ng-switch="变量"配合ng-switch-when=""

拓展:

指令 作用
ng-app 定义应用程序的根元素。
ng-bind 绑定 HTML 元素到应用程序数据
ng-bind-html 绑定 HTML 元素的 innerHTML 到应用程序数据,并移除 HTML 字符串中危险字符
ng-bind-template 规定要使用模板替换的文本内容
ng-blur 规定blur事件的行为
ng-change 规定在内容改变时要执行的表达式
ng-checked 规定元素是否被选中
ng-class 指定 HTML 元素使用的 CSS类
ng-class-even 类似 ng-class,但只在偶数行起作用
ng-class-odd 类似 ng-class,但只在奇数行起作用
ng-click 定义元素被点击时的行为
ng-cloak 在应用正要加载时防止其闪烁
ng-controller 定义应用的控制器对象
ng-copy 规定拷贝事件的行为
ng-csp 修改内容的安全策略
ng-cut 规定剪切事件的行为
ng-dblclick 规定双击事件的行为
ng-disabled 规定一个元素是否被禁用
ng-focus 规定聚焦事件的行为
ng-form 指定 HTML表单继承控制器表单
ng-hide 隐藏或显示 HTML元素
ng-href 为 the<a>元素指定链接
ng-if 如果条件为 false移除 HTML元素
ng-include 在应用中包含 HTML文件
ng-init 定义应用的初始化值
ng-jq 定义应用必须使用到的库,如:jQuery
ng-keydown 规定按下按键事件的行为
ng-keypress 规定按下按键事件的行为
ng-keyup 规定松开按键事件的行为
ng-list 将文本转换为列表 (数组)
ng-model 绑定 HTML 控制器的值到应用数据
ng-mousedown 规定按下鼠标按键时的行为
ng-model-options 规定如何更新模型
ng-mouseenter 规定鼠标指针穿过元素时的行为
ng-mouseleave 规定鼠标指针离开元素时的行为
ng-mousemove 规定鼠标指针在指定的元素中移动时的行为
ng-mouseover 规定鼠标指针位于元素上方时的行为
ng-mouseup 规定当在元素上松开鼠标按钮时的行为
ng-non-bindable 规定元素或子元素不能绑定数据
ng-open 指定元素的open属性
ng-options <select>列表中指定 <options>
ng-paste 规定粘贴事件的行为
ng-pluralize 根据本地化规则显示信息
ng-readonly 指定元素的readonly属性
ng-repeat 定义集合中每项数据的模板
ng-selected 指定元素的selected属性
ng-show 显示或隐藏HTML元素
ng-src 指定元素的src属性
ng-srcset 指定元素的srcset属性
ng-style 指定元素的 style属性 ng-style="{{n.left}}
ng-submit 规定 onsubmit事件发生时执行的表达式
ng-switch 规定显示或隐藏子元素的条件
ng-transclude 规定填充的目标位置
ng-value 规定 input元素的值

Angular内置指令DEMO
详情可参考文档

坑:脏值检测

在双向数据绑定中:
原生/JQ + angular 可能会导致 脏值检查机制失效,从而导致双向绑定失效;
解决:手动刷新或者全部用Angular方法;

服务

定义:

服务是一个函数或'单例对象',就相当于我们可以在angular程序中封装好一些方法然后在需要用的时候 '注入' 到需要用到的地方<span style="color: red">(控制器,自定义服务,自定义指令和自定义过滤器中)</span>,这样可以增强我们程序的扩展性和复用性

内置服务

$scope

用来绑定数据模型,是控制器独有的服务.控制器中的数据需要依赖$scope服务才能传递到View视图层

$rootScope

是ng-app的作用域范围,它可以用在两个控制器之间传递数据,你可以把它看做ng的全局作用域

$sce

处理html为安全字符的一个服务 跟 ng-bind-html 配合

//view
<div ng-bind-html="html"></div>
//model
$scope.html = "<p>Hello Wscat</p>";
$scope.html = $sce.trustAsHtml($scope.html)


$http

Get请求

$http({
    method:"get",
    url:"Oaoafly.php"
    params:{}
})
.then(function(data){
    //成功的回调
},function(err){
    //失败的回调
})

Post请求

    $http({
            method: 'post',
            url: 'http://localhost:8081/search',
            data: {
                "page": $scope.page,
                "pageNum": $scope.pageNum
            },
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
            },
            transformRequest: function(obj) {
                var str = [];
                for (var p in obj) {
                    str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]))
                }
                return str.join('&')
            }
        }).then(function(data) {
           console.log(data)//打印服务端返回的数据
        }, function(err) {
            console.log(err)//打印错误信息
        });

注意点:POST请求参数处理

$filter服务


$window && $document

  1. $window服务对应了JS的全局window
  2. $document服务对应了JS的document,用的时候注意要这样用$document[0]

    注意:

    如果需要用到原生JS代码,最好在前面加上$window有利于解决双向绑定数值失效的问题;

$location

获取url的哈希值

    var app = angular.module('app', []);
    app.controller('div', function($scope,$location) {
    $scope.name = 'heightzhang';

    var abc = $location.search({
        "foo": "yipee",
        "abc":"1231"
    
    });  //1.=>设置哈希值为 : #!?foo=yipee&abc=1231;

    var def = $location.search()
    console.log(def);//2.=>获取哈希值的结果为 : {abc:"1231",foo:"yipee"}

});

注意: angular使用 $location服务比使用 window.location对象更好。

angular会一直监控应用,处理事件变化,window.location 对象在angular应用中有一定的局限性.

$timeout && $interval

  1. $timeout服务对应了JS的window.setTimeout函数
  2. $interval服务对应了JS的window.setInterval函数
$scope.interval = 0;
$scope.timeout = 0;
$timeout(function(){
    $scope.timeout = 1;
},1000)
$interval(function(){
    $scope.interval++
},1000)

过滤器

语法

过滤器可以通过一个管道字符(|)和一个过滤器添加到表达式中

{{num|过滤器的名字:参数}}

内置过滤器

filter methods
currency currency:"货币符号"
uppercase uppercase大写
lowercase lowercase小写
filter 接受一个对象,一般配合ng-repeat
orderBy 接受两个参数,第一个是要排序的键值,第二个是个布尔值
limitTo 可以用于分页,第一个参数就是截取的长度,第二个是截取的位置,可以用于截取字符串和数组
json 就是把对象转为字符串显示,一般用于调试页面数据
date 接受时间戳格式,处理成常用的时间格式
number 精确到就是小数点后几位

Angular内置过滤器

$fiter服务

这个服务可以注入到过滤器或者控制器里面

在AngularJS的controller, service或者driective中使用filter

$filter("过滤器名字")("处理的数据","过滤器的参数")

前端筛选组合

orderBy和filter和limitTo 排序 搜索 分页

orderBy:A:B
接收两个参数
a是要排序的对象,b是个布尔值

true为降序 ,false为升序;

#Bug 数字排序; 存入数据库类型要是int;
实现升序或降序

filter:A|filter:B 或者接收一个对象 实现一级搜索或者二级搜索

limitTo:A:B a数量,b索引值 截取字符串或者数组,实现分页效果;

注意:过滤器支持链式调用

路由

第一种:原生路由

引入../js/angular-route.js

var app = angular.module('routeApp',['ngRoute','routes','controller','directives']);
    //路由
      //建立路由模块
    var routes = angular.module("routes",[]);
      //1.配置路由Url
    routes.config(function($routeProvider){
        $routeProvider.when("/home",{
            templateUrl:"template/home.html"
        }).when("/detail",{
            templateUrl:"template/detail.html"
        })
        //3.路由传参
        .when("/detail/:id/:skill",{
            controller:"ulCtrl"  //建立子控制器
            templateUrl:"template/detail.html"
        })

        //2.默认重定向的路由路径(默认值设定)
        .otherwise({
                redirectTo: '/home'
        })
        // 注意:传参要设置两个路由,一个模版,一个传参路由;
    })

    //建立控制器模块;
    var controller = angular.module('controller',[]);
     //配置控制器
    controller.controller('ulCtrl',function($scope,$routeParams){
        $scope.name = 'heightzhang'
        //3.路由传参  ,打印传递的url参数
        console.log($routeParams)
    });
    
    controller.controller('aCtril',function($scope){
        $scope.name = "zhangggao";
        $scope.url = "#!/home?id=5"
    });

    //4.建立组件化模版
    var directives = angular.module("directives", []);
        directives.directive("xheader", function() {
            return {
                template: "<header>今日头条</header>"
            }
        });

第二种:UI路由

引入../js/angular-ui-router.js

//建立主模块
    var app = angular.module('uirouterApp',['ui.router']);
    //配置路由
    app.config(function($stateProvider,$urlRouterProvider){
        //设置默认路由;
        $urlRouterProvider.when('', '/index');
     //Angular
        //一层
        $stateProvider.state("index",{
            url:"/index",
            templateUrl:"1.2template/angular.html"
        })
        //"."表示从属关系
        //二层
        .state("index.a",{
            url:"/a",
            templateUrl:"1.2template/angular2.html"
        })
        //三层
        .state("index.a.aa",{
            url:"/aa",
            templateUrl:"1.2template/angular3.html"
        })
     //Jquery
        .state("home",{
            url:"/home",
            templateUrl:"1.2template/jquery.html"
        })
        .state("home.a",{
            url:"/a",
            templateUrl:"1.2template/jquery2.html"
        })
        .state("home.a.aa",{
            url:"/aa",
            templateUrl:"1.2template/jquery3.html"
        })
     //传参数
        .state("detail",{
            url:"/detail/:id",
             //设置子控制器;
            controller:"detailCtrl",
            
            templateUrl:"1.2template/detail.html"
        })
    });

    //接收url参数
    app.controller("detailCtrl",function($state){
            console.log($state.params)
    });

    //注意 :路由随便写也能进入网页,是不会报错的,只是你需要打印的东西无法打印出来;

我们开发中一般使用UI路由,UI路由可以嵌套;原生路由不支持嵌套

自定义过滤器

适合:修饰的复用;

//#自定义无参数过滤器:
    //比如:过滤HTML结构  
    //格式:
    <div ng-bind-html="html|htmled"></div>
    app.filter("htmled", function($sce) {
        return function(input) {
            //input => 需要过滤的数据处理成新的数据
            return $sce.trustAsHtml(input)
        }
    })

//#自定义有参数过滤器:
    //适用在需要设置第二个数据才可以过滤的情形下;
    //比如:高亮搜索内容(搜索内容为需要高亮的部分)
    <div ng-bind-html="html|highlight:search"></div>
    app.filter("highlight", function() {
        return function(input, search) {
            console.log(search)
            console.log(input)
            var arr = input.split(search);
            var output = arr.join("<span style='color:red'>" + search + "</span>")
            return output;
        }
    })

自定义服务

适合:方法的复用

//主模块
var app = angular.module('app', ['div','service']);
//分模块
var div = angular.module('div', []);
//分模块控制器
div.controller('divCtrl', function($scope,tool,abc,exchange) {
    $scope.name = "heightzhang";
   console.log(tool); //共享自定义服务;
   console.log(abc);  //自定义服务引用其他服务
   console.log(exchange.name) //自定义服务通信, 传递数据;
});

//服务模块;  1.主模块引入服务'依赖', 所有的分模块 通过注入该新服务,可以共享新服务;

var service = angular.module('service', []);

service.service('tool', function() {
    return {
        add: function(a, b) {
            return a + b
        }
    }
});

//2.第二个自定义服务中使用之前自定义服务或者内置服务的时候;用传参方法;
service.service('abc', function($http) {   
    return {
       tool:$http
    }
});
//3.service作为通信 传递数据;
service.service('exchange',function(){
    return {
        name:'heightzhang'
    }
})

其他自定义服务;

  1. value就是一个简单的可注入的值
  2. service是一个可注入的构造器
  3. factory是一个可注入的方法
  4. decorator可以修改或封装其他的供应商,当然除了constant
  5. provider是一个可配置的factory

自定义组件/指令

适合:组件适合HTML结构的复用

关于自定义的四种状态

自定义组件

//自定义了一个<xheader></xheader>组件
app.directive("xheader", function() {
    return {
        restrict: "E",   //元素
        template: `
            <div>
                <header ng-transclude></header>
                <p>Hello {{name}}</p>
            </div>
        `
    }
})

自定义指令

//自定义了一个<div ng-header></div>的指令
app.directive("ngHeader", function() {
    return {
        restrict: "A",   //属性
        template: `
            <div>
                <header ng-transclude></header>
                <p>Hello {{name}}</p>
            </div>
        `
    }
})

自定义类指令

//自定义了一个<div class = "ng-header"></div>类的指令
app.directive("ngHeader", function() {
    return {
        restrict: "C",   //类
        template: `
            <div>
                <header ng-transclude></header>
                <p>Hello {{name}}</p>
            </div>
        `
    }
})

ECMA:

value
element 元素,标签
attribute 属性
class
m 注释

Tips:

  1. restrict:ECMA或者不写,则默认允许呈现四种状态;
  2. template(模版)的规范,建议先定义一个外围容器包围;
  3. 控制器可以理解为唯一的ID, <span style="color: red">控制器不能去复用</span>;

replace

true:组件的自定义的标签名会消失,模版的div结构出现;

true的好处:对一些不兼容自定义表情的浏览器有好处;

false:组件的自定义标签名出现,模版的div结构也出现,
false的好处:可以方便我们进行分组管理这些组件;

replace默认值为false

controller :组件内部自身的控制器作用域;提供给template模版使用;

transclude :true 组件支持嵌入

replace \ controller transclude 简单代码如下:

<xheader><p>新闻</p></xheader>

app.directive("xheader", function() {
    return {
        restrict: "ECMA",
        //组件自定义标签名出现
        replace: false,
        //组件支持嵌入<p>新闻</p>嵌入到模版<header ng-transclude></header>里面
        transclude: true,
        //组件的子控制器,给template模版使用
        controller: function($scope, $http) {
            $scope.name = "laoyao"
        },
        template: `
            <div>
                <header ng-transclude></header>
                <p>Hello {{name}}</p>   //子控制器的作用域是该模版区域;
            </div>
        `
    }
})

link子控制器:

scope,ele,attr
注意:Controller与scope的区别:两者区别不大,我们开发一般会选用link;

app.directive("xheader", function($http) {
        return {
            //View
            template: `<div>
                <ul>
                    <li ng-repeat="arr in arrs track by $index">{{arr}}</li>
                </ul>
                <button ng-click="loadMore()">{{isShow}}</button> //触发事件
            </div>`,
            //Contrl
                 //link 是组件的控制器 scope是存放该组件的数据模型model;
            link: function(scope, ele, attr) {
                //Model
                //--------1.scope----------
                scope.arrs = [];
                scope.loadMore = function() {
                    //请求后端数据返回给模版
                    $http({
                        method: "GET",
                        url: "http://localhost:81/1702/angular/test.php"
                    }).then(function(data) {
                        console.log(data)
                        scope.arrs = scope.arrs.concat(data.data.arrs)
                });

                //------2.ele ----jQlite----------
                console.log(ele)
                ele.on("click",function(){
                        alert("hello")
                });

                // ----3.attr ----------
                console.log(attr)  //获取xheader上的attr属性,有利于通过JQlite改变原先的attr值;   
            }
        }
})

汇:控制器之间通信数据的方法

1.Angular事件广播

2.$rootScope

3.Cookies和本地存储

4.基于服务器Service通信数据

5.Angular基于$window的数据通信

6.路由传参(跨页面跨路由的情况)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,681评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,710评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,623评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,202评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,232评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,368评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,795评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,461评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,647评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,476评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,525评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,226评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,785评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,857评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,090评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,647评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,215评论 2 341

推荐阅读更多精彩内容