天天看點

angularjs + seajs建構Web Form前端(一)

簡介

  Bootstrap是Twitter推出的一個用于前端開發的開源工具包,它由Twitter的設計師Mark Otto和Jacob Thornton合作開,是一個CSS/HTML架構。

  AngularJS是Google 開源出來的一套 js 工具,為了克服HTML在建構應用上的不足而設計的,試圖成為WEB應用中的一種端對端的解決方案,通過為開發者呈現一個更高層次的抽象來簡化應用的開發,後面簡稱"ng"。

  Seajs是一款優秀的子產品開發插件,可以實作按需加載。

  Bootstrap有自己的一套js庫,但是為了防止與AngularJS産生相容性的問題,我們不選擇使用,隻是使用它的css而已,是以這裡我還要引入另外一個基于Bootstrap與AngularJS的UI元件--UI-Bootstrap,雖然該庫提供的控件并不多,但是基本夠用,而且可以參考它的代碼來自己實作複雜的控件(後面的文章再講)。

背景

  目前Web前端開發中,我們已經可以很熟練的使用jQuery在對資料互動的時候來操作關聯Dom的一些内容、樣式等狀态上的變化,然而很多的這些變化是代碼重複的,雖然它并不複雜,但是有些确實需要大量的代碼來進行操作;雖然jQuery為我們提供了大量的操作方式來減少複雜性,但是每次我們都要從頁面中找尋一些相關的元素改變狀态是重複且難以避免的,那麼怎麼樣才能從這種重複的操作中解脫呢?

  MVVM便可以讓我們從這種重複的操作中解脫出來,簡單的說MVVM就是我們将需要操作的元素與ViewModel進行綁定,當我們對ViewModel進行操作導緻其狀态發生變化的時候,與之相關的元素會自動發生變化。

  由于我也使用jQuery開發了較長的時間,雖然前幾年就已經有前端MVVM架構出現,卻沒有能讓我覺得比原始方式更簡單的,但是技術總是在發展的并趨向成熟,現在就可以将以上提到的3種架構進行結合,大大簡化Web前端的開發(雖然需要一段時間的學習和适應),接下來就讓我們一起來使用這3中架構進行開發吧(這裡我不會對各個庫有詳細的介紹,有些地方仍然需要自己去學習)。

實作

  首先我們從登入功能開始着手,登入界面比較簡單,html代碼如下:

1 <body class="container" ng-app="login">
2     <form name="frmLogin" class="col-sm-offset-4 col-sm-4" role="form" ng-controller="HomeLoginController">
3         <input name="txtName" ng-model="name" type="text" class="form-control input-lg" placeholder="請輸入使用者名" required autofocus />
4         <input name="txtPwd" ng-model="pwd" type="password" class="form-control input-lg" placeholder="密碼" required />
5         <button class="btn-lg btn-primary btn-block" ng-click="submit()">登入</button>
6         <alert ng-repeat="a in alerts" type="a.type" close="closeAlert($index)">{{a.msg}}</alert>
7     </form>
8 </body>      

  這裡不使用ngSubmit、ngShow、ngHide是因為有一些注意點需要講解,登入的流程是當點選登入按鈕的時候,如果使用者名、密碼未填寫的情況下,會在登入按鈕下面增加2個Alert提醒框,js代碼如下:

angular.module('login', ['ui.bootstrap']);
function HomeLoginController($scope) {
    $scope.alerts = [];

    $scope.submit = function () {
        if ($scope.frmLogin.txtName.$invalid)
            $scope.alerts.push({ type: 'danger', msg: '使用者名不能為空!' });
        if ($scope.frmLogin.txtPwd.$invalid)
            $scope.alerts.push({ type: 'danger', msg: '密碼不能為空!' });

        if ($scope.alerts.length)
            return;

        $scope.alerts = [{ type: 'success', msg: '登入成功' }];
    };

    $scope.closeAlert = function (index) {
        $scope.alerts.splice(index, 1);
    };
};
      

  當使用者名密碼未填寫或者表單正确的情況下,點選送出按鈕的時候會出現以下2種情況,如圖:

  

angularjs + seajs建構Web Form前端(一)
angularjs + seajs建構Web Form前端(一)

  當我們點選X的時候(多次點選的時候會出現多個提示,别在意這個小問題,^_^),會調用closeAlert方法,并根據$index删除alerts數組内對應的元素,這時候綁定的視圖就會自動重新整理,不需要手動去操作這些元素,這裡要注意的主要有3個地方:1、ng-app="login"是不能缺少的,除非你要手動啟動ng;2、開頭的angular.module('login', ['ui.bootstrap']);的意思是注冊login子產品且該子產品需要對ui-bootstrap的引用(否則無法顯示alert的效果);3、HomeLoginController方法的參數$scope是不能重命名成其他名字,否則ng會報錯。

  如果我們想要讓彈出來的Alert自己消失怎麼辦呢?一開始的時候,大家可能會跟我一樣,會嘗試使用setTimeout函數去直接從$scope.alerts數組内将對應的元素移除掉,然後等待着視圖将Alert移除掉,但是最後會發現一點作用都沒有,因為視圖資料是在ng内部進行控制的,需要使用它提供的機制去處理,視圖才會跟着資料發生變化,這裡需要使用$timeout去完成以上的操作,代碼改動如下:

//其他代碼略

$scope.submit = function () {
    if ($scope.frmLogin.txtName.$invalid)
        addAlert({ type: 'danger', msg: '使用者名不能為空!' });
    if ($scope.frmLogin.txtPwd.$invalid)
        addAlert({ type: 'danger', msg: '密碼不能為空!' });

    if ($scope.alerts.length)
        return;

    addAlert({ type: 'success', msg: '登入成功' });
};

function addAlert(alert) {
    $scope.alerts.push(alert);
    $timeout(function () {
        angular.forEach($scope.alerts, function (a, i) {
            if (alert != a)
                return;
            $scope.alerts.splice(i, 1);
        });
    }, 500);
};
      

  寫到這裡已經把大緻該出現的效果都做出來了,現在的問題是這個腳本是直接寫在頁面上的,那麼怎麼樣通過seajs來加載呢?這裡就需要用到angular的手動加載模式了,首先需要對html進行修改要先将ng-app給移除掉,不然ng會自動加載,由于已經将腳本轉移到js檔案内了,無法找到HomeLoginController方法ng會抛出錯誤,使用seajs後的代碼如下:

//頁面
    seajs.use('home-login');

    //腳本檔案
    this.define(function (require, exports, module) {
        angular.module('home.login', ['ui.bootstrap']).controller('HomeLoginController', function ($scope, $timeout) {
            //原本HomeLoginController方法内的代碼,這裡就不重複貼出了
        });

        angular.bootstrap($('[name=frmLogin]'), ['home.login']);
    });
      

  從代碼中可以看到首先要注冊子產品home.login這個名字是可以任意的,但是必須跟bootstrap内引用的子產品對應,然後我們建立頁面上需要的Controller(名字一樣得對應),并使用ng的bootstrap來手動啟動。

  那麼第一篇結合bootstrap + angularjs + seajs就到這裡了,如果有任何錯誤請各位指出,謝謝,^_^!