AngularJS(二、如何用AngularJS建立前端程式碼框架)

farsun發表於2021-09-09

     我們可以看到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"        class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="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 configrequire.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。




來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4289/viewspace-2815833/,如需轉載,請註明出處,否則將追究法律責任。

相關文章