AngularJS(二、如何用AngularJS建立前端代码框架)

首先,我们来看一下工程结构目录:

我们可以看到scripts中分列了一下几个文件夹:controllers、services、directives、filters、vendor,以及两个文件app.js和main.js。

controllers里面主要就是控制器

services里面是服务,为控制器提供数据服务支持,与后台交互的代码就在其中

directives是指令,用于生成自定义标签的html模板

filters是过滤器,用于处理显示数据的形式

vendor文件夹中存放的是引用的第三方js插件

跟scripts同级的是styles和views文件夹,styles存放css样式文件,view存放html文件。

我们先来看一下index.html中的主要代码:

<!DOCTYPE html>
<html> <!-- Do not add ng-app here as we bootstrap AngularJS manually-->
<head>
  <title>My AngularJS App</title>
  <meta charset="utf-8" />

  <link rel="stylesheet" type="text/css"
        href="styles/bootstrap.min.css">
  <link rel="stylesheet" type="text/css" href="styles/ng-grid.css" />
  <link rel="stylesheet" type="text/css" href="styles/main.css">

</head>
<body class="home-page row-fluid">

<nav class="navbar navbar-default">
    ……
</nav>

<div class="col-lg-10 col-md-12 col-sm-12 col-sm-12 col-lg-offset-1">
    <div ng-view></div>
</div>
<div class="row-fluid">

</div>
  <script data-main="scripts/main"
        src="scripts/vendor/require.js"></script>
</body>
</html>

我们可以看到导入的js只有一个require.js,但是这个script中有个这样的属性

data-main="scripts/main"

这个属性就将主js指向了scripts/main.js。

下面来看main.js,其中,分为了两块,第一块是对第三方的引用和依赖配置:

// the app/scripts/main.js file, which defines our RequireJS config
require.config({
    paths:{
        angular:‘vendor/angular.min‘,
        jquery:‘vendor/jquery‘,
        bootstrap:‘vendor/bootstrap.min‘,
        domReady:‘vendor/domReady‘,
        ngGrid:‘vendor/ng-grid.debug‘
    },
    shim:{
        angular:{
            deps:[ ‘jquery‘],
            exports:‘angular‘
        },
        ngGrid:{
            deps:[ ‘jquery‘]
        },
        bootstrap:{
            deps:[ ‘jquery‘]
        }
    }
});

第二块就是主要的引用和route信息了:

require([
    ‘angular‘,
    ‘app‘,
    ‘domReady‘,
    ‘bootstrap‘,
    ‘services/userService‘,
    ‘controllers/rootController‘,
    ‘directives/ngbkFocus‘,
    ‘controllers/user/listController‘,
    ‘controllers/user/editController‘,
    ‘controllers/user/newController‘,
    ‘ngGrid‘
    // Any individual controller, service, directive or filter file
    // that you add will need to be pulled in here.
],
    function (angular, app, domReady) {
        ‘use strict‘;
        app.config([‘$routeProvider‘,
            function ($routeProvider) {
                $routeProvider.when(‘/‘, {
                    templateUrl:‘views/user/list.html‘,//当跳转到该路径时,将此html嵌入到ng-view属性的dom中
                    controller:‘ListCtrl‘//当前templateUrl的controller为ListCtrl
                })
                    .when(‘/edit/:name/:allowance‘, {
                        templateUrl:‘views/user/form.html‘,
                        controller:‘EditCtrl‘
                    })
                    .when(‘/new‘, {
                        templateUrl:‘views/user/form.html‘,
                        controller:‘NewCtrl‘
                    })
                    .when(‘/root‘, {
                        templateUrl:‘views/root.html‘,
                        controller:‘RootCtrl‘
                    });
            }
        ]);
        domReady(function () {
            angular.bootstrap(document, [‘MyApp‘]);//app名为MyApp

            // The following is required if you want AngularJS Scenario tests to work
            $(‘html‘).addClass(‘ng-app: MyApp‘);//给html添加ng-app属性
        });
    }
);

以list的route为示例,我们来讲解controller,先看一张list效果图(此处我们引用了ng-grid插件):

我们来看引入的controllers/user/listController:

define([‘controllers/controllers‘, ‘services/userService‘],
    function (controllers) {
        controllers.controller(‘ListCtrl‘, [‘$scope‘, ‘$http‘, ‘$location‘, ‘UserService‘,//此处数组中的参数依次对应下面回调方法中的参数
            function ($scope, $http, $location, UserService) {
                
                $scope.mySelections = [];
                $scope.filterOptions = {
                    filterText:"",
                    useExternalFilter:true
                };
                $scope.totalServerItems = 0;
                $scope.pagingOptions = {
                    pageSizes:[250, 500, 1000],
                    pageSize:250,
                    currentPage:1
                };
                $scope.setPagingData = function (data, page, pageSize) {
                    var pagedData = data.slice((page - 1) * pageSize, page * pageSize);
                    $scope.myData = pagedData;
                    $scope.totalServerItems = data.length;
                    if (!$scope.$$phase) {
                        $scope.$apply();
                    }
                };
                $scope.getPagedDataAsync = function (pageSize, page, searchText) {
                    setTimeout(function () {
                        var data;
                        if (searchText) {
                            var ft = searchText.toLowerCase();
                            UserService.getServerData(function (largeLoad) {
                                data = largeLoad.filter(function (item) {
                                    return JSON.stringify(item).toLowerCase().indexOf(ft) != -1;
                                });
                                $scope.setPagingData(data, page, pageSize);
                            });
                        } else {
                            UserService.getServerData(function (largeLoad) {
                                $scope.setPagingData(largeLoad, page, pageSize);
                            });
                        }
                    }, 100);
                };

                $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);

                $scope.$watch(‘pagingOptions‘, function (newVal, oldVal) {
                    if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) {
                        $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
                    }
                }, true);
                $scope.$watch(‘filterOptions‘, function (newVal, oldVal) {
                    if (newVal !== oldVal) {
                        $scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
                    }
                }, true);
                
                $scope.clickme = function (v) {
                    $location.path(‘/edit/‘ + v.name + "/" + v.allowance);
                }

                $scope.gridOptions = {
                    data:‘myData‘,
                    enablePaging:true,
                    showFooter:true,
                    totalServerItems:‘totalServerItems‘,
                    pagingOptions:$scope.pagingOptions,
                    filterOptions:$scope.filterOptions,
                    selectedItems:$scope.mySelections,
                    showSelectionCheckbox:true,
                    columnDefs:[
                        { field:"name", pinned:true }
                        ,
                        { field:"allowance", cellTemplate:‘<div class="ngCellText" ng-class="col.colIndex()"><span ng-cell-text>{{COL_FIELD | currency}}</span></div>‘}
                        ,
                        { field:"entity", pinned:true, cellTemplate:‘<div class="ngCellText" ng-class="col.colIndex()"><span ng-cell-text>{{$parent.row.entity | myfilter}}</span></div>‘ }
                        ,
                        { field:"name", width:100, cellTemplate:‘<button class="btn-xs table-btn" ng-click="clickme($parent.row.entity)"><span class="glyphicon glyphicon-search" aria-hidden="true"></span></button>‘}
                    ]/*,
                    multiSelect:false*/

                };
            }]);
    });

其中定义了该controller名为ListCtrl,$scope为局部变量,其中定义的数据与方法可在当前Ctrl作用域内生效,我们来看一下生效的list.html是怎么样的

<div class="gridStyle" ng-grid="gridOptions"></div>

就是这么一句话,定义了grid的div,其余的都交给了controller和ng-grid插件

listController中引用了services/userService,service层用来与后台交互,管理数据:

define([‘services/services‘],
    function (services) {
        services.factory(‘UserService‘, [‘$http‘,
            function ($http) {
                return {
                    getData:function () {
                        return [
                            { name:"Moroni", age:50, birthday:"Oct 28, 1970", salary:"60,000" },
                            { name:"Tiancum", age:43, birthday:"Feb 12, 1985", salary:"70,000" },
                            { name:"Jacob", age:27, birthday:"Aug 23, 1983", salary:"50,000" },
                            { name:"Nephi", age:29, birthday:"May 31, 2010", salary:"40,000" },
                            { name:"Enos", age:34, birthday:"Aug 3, 2008", salary:"30,000" },
                            { name:"Moroni", age:50, birthday:"Oct 28, 1970", salary:"60,000" },
                            { name:"Tiancum", age:43, birthday:"Feb 12, 1985", salary:"70,000" },
                            { name:"Jacob", age:27, birthday:"Aug 23, 1983", salary:"40,000" },
                            { name:"Nephi", age:29, birthday:"May 31, 2010", salary:"50,000" },
                            { name:"Enos", age:34, birthday:"Aug 3, 2008", salary:"30,000" },
                            { name:"Moroni", age:50, birthday:"Oct 28, 1970", salary:"60,000" },
                            { name:"Tiancum", age:43, birthday:"Feb 12, 1985", salary:"70,000" },
                            { name:"Jacob", age:27, birthday:"Aug 23, 1983", salary:"40,000" },
                            { name:"Nephi", age:29, birthday:"May 31, 2010", salary:"50,000" },
                            { name:"Enos", age:34, birthday:"Aug 3, 2008", salary:"30,000" }
                        ];
                    },
                    getOptions:function () {
                        return {
                            data:‘myData‘,
                            enablePinning:true,
                            columnDefs:[
                                { field:"name", width:120, pinned:true },
                                { field:"age", width:120 },
                                { field:"birthday", width:120 },
                                { field:"salary", width:120 }
                            ]
                        }
                    },
                    getServerData:function (success) {
                        $http.get(‘jsonFiles/largeLoad.json‘).success(success);
                    },

                    saveData:function (data, success) {
                        $http.post(‘/users/save‘, data).success(success);
                    }
                };
            }]);
    });

其中引用的$http是用来管理ajax的对象,类似的对象还有$location,用来管理url地址,类似的对象还有很多,详细可以参见官方API文档。

至此,一个前端MVC框架基本构建完成,在之后的一篇中我们来着重介绍下还没讲过的filters和directives。

时间: 2024-10-19 06:22:32

AngularJS(二、如何用AngularJS建立前端代码框架)的相关文章

开始启程, 你的第一行前端代码

Vue.js杀敌须知 人生最大的敌人,就是没有明确的目标 -- 罗曼罗兰 选择自己的人生坐标,是对自己对生命的负责,没有认识目标,会变得慵懒,只能听天由命叹息茫然.学习前端开发亦是同理,我们开始学习之前我们必须要弄清楚 前端开发的职业前景怎么样? Vue.js是什么?为什么选择它? 学完Vue.js我们能够干什么? 如果自身对以上三个问题的答案都不感兴趣,那么劝诫大家不要再自己不喜欢的道路上花费太多的时间. 1.1 前端开发的职业前景怎么样? 最近两年,尤其是过去的2016年,前端开始引爆市场,

有jQuery背景,该如何用AngularJS编程思想?

"我可以熟练使用jQuery进行客户端应用的开发,但是现在我希望开始使用Angular.js.哪位能描述一下这个过程中必要的模式变化吗?希望您的答案能够围绕下面这些具体的问题: 1. 我如何对客户端web应用进行不同方式的架构和设计?它们之间最大的区别是什么?(译者注:指jQuery和Angular.js) 2. 有什么是我不该做或者不该使用的:而又有什么是我应该做或者应该使用的呢? 3. 有没有一些服务端的考量/约束呢? 我在寻找的就是一个关于jQuery和Angular.js之间的详细的比较

用angularjs开发下一代web应用(二):angularjs应用骨架(二)

1.浅谈非入侵式JavaScript <div ng-click="doSomething()">...</div>这些指令和原来的事件处理器有以下不同之处: 在所有浏览器中具有相同的行为.Angular将会帮你屏蔽差异性. 不会在全局命名空间中进行操作.你所指定的表达式只能访问元素控制器作用域范围内的函数和数据. 2.列表.表格以及其他迭代型元素         ng-repeat可能是最有用的Angular指令了,它可以根据集合中的项目一次创建一组元素的多份

[后端人员耍前端系列]AngularJs篇:使用AngularJs打造一个简易权限系统

一.引言 上一篇博文已经向大家介绍了AngularJS核心的一些知识点,在这篇博文将介绍如何把AngularJs应用到实际项目中.本篇博文将使用AngularJS来打造一个简易的权限管理系统.下面不多说,直接进入主题. 二.整体架构设计介绍 首先看下整个项目的架构设计图: 从上图可以看出整个项目的一个整体结构,接下来,我来详细介绍了项目的整体架构: 采用Asp.net Web API来实现REST 服务.这样的实现方式,已达到后端服务的公用.分别部署和更好地扩展.Web层依赖应用服务接口,并且使

用angularjs开发下一代web应用(二):angularjs应用骨架(一)

1.调用angularjs 1>加载angularjs库 可以从google的CDN(内容分发网络)中加载,获取快,并且可以在多个应用之间缓存脚本库(建议使用这种方式,但是中国的特殊国情,不能用这种方式): <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script> 本地主机方式. 2>使用ng-app申明angular的边界

我和我的广告前端代码(二):突发需求,广告法,加标识,打补丁

概述: 在重构广告‘老代码’的初期发生了一个突发的需求,下面我简单介绍一下,可能文中更多的是思路和结构上的东西.具体的业务实现也会简单说一些,但说的不多. 仅用文章纪录一下,保存我于广告项目珍贵的记忆. 突发事件: 上一篇文章——我和我的广告前端代码(一):打碎重来.化零为整,中提到我在将业务线甲的广告代码重构的事情,但是开发的过程中,有了一个小插曲——加标志.由于我国新出台的广告法规定,所有的广告必须注明“广告”.要求一周内,连开发带测试,打败这个半路杀出来的‘程咬金’. 应急方案: 这本是一

AngularJS学习之旅—AngularJS 表达式(二)

1.AngularJS 表达式 AngularJS 表达式写在双大括号内:{{ expression }}. AngularJS 表达式把数据绑定到 HTML,这与 ng-bind 指令有异曲同工之妙. AngularJS 将在表达式书写的位置"输出"数据. AngularJS 表达式 很像 JavaScript 表达式:它们可以包含文字.运算符和变量. 实例 {{ 5 + 5 }} 或 {{ firstName + " " + lastName }} eg: 1

前端代码异常日志收集与监控

在复杂的网络环境和浏览器环境下,自测.QA测试以及 Code Review 都是不够的,如果对页面稳定性和准确性要求较高,就必须有一套完善的代码异常监控体系,本文从前端代码异常监控的方法和问题着手,尽量全面地阐述错误日志收集各个阶段中可能遇到的阻碍和处理方案. ? 收集日志的方法 平时收集日志的手段,可以归类为两个方面,一个是逻辑中的错误判断,为主动判断:一个是利用语言给我们提供的捷径,暴力式获取错误信息,如 try..catch 和 window.onerror. 1. 主动判断 我们在一些运

[Angularjs]asp.net mvc+angularjs+web api单页应用

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 写在前面 最近的工作一直在弄一些h5的单页应用,然后嵌入到app的webview中.之前一直在用angularjs+html+ashx的一套东西.实在是玩腻了.然后就尝试通过asp.net mvc的方式构建单页应用.用到的技术angularjs