1. 程式人生 > >使用angularjs1.x構建前臺開發框架(八)——彈窗【二】

使用angularjs1.x構建前臺開發框架(八)——彈窗【二】

如果有同學基於上一章的程式碼執行過,那麼一定會發現上一章提供的彈窗在實際的web應用開發中根本沒法用,為什麼?問題太多了:

1.無法控制彈窗後父頁面是否可以響應使用者的操作(我們希望父頁面是否可以響應時可控的);

2.彈窗僅僅只是一個html模板(從程式碼角度而言),沒有說明如何在彈窗內自定義行為(比如彈窗需要在幾秒後自動關閉,則需要為彈窗定義一個定時器);

3.沒有說明彈窗和父頁面如何進行資料互動。

接下來的幾篇部落格會詳細說明基於目前的彈窗功能應該如何處理這些問題。

首先,我們來看問題的現象:


當彈出框顯示時,滑鼠在父頁面與彈出框不重合的任意位置點選,都會導致彈出框消失。這其實不能算是問題,我們引入的第三方外掛提供的$modal服務支援我們對彈出框在什麼情況下消失進行配置。實際上$modal服務還支援很多配置,想詳細瞭解的同學可以看看這篇部落格,裡面有對$modal(即筆者部落格裡說的彈窗或彈出框,通常也被稱為模態框)服務API的詳細說明:

就我們上面的問題而言,裡可以參考API裡的這個屬性:

backdrop:控制背景,允許的值:true(預設),false(無背景),static” - 背景是存在的,但點選模態視窗之外時,模態視窗不關閉

在筆者之前的給的程式碼示例中並沒有對backdrop屬性進行配置,所以實際在執行時使用的是預設配置,即true,這表示點選彈出框外部時,彈出框會關閉。

下面我們配置一下backdrop屬性看一下效果,首先是配置為配置為false:

在frameworkCtrl.js中定義彈出框時增加backdrop配置項:

/**
 * Created by 李慶 on 2016/10/6.
 */
define(["language"],function(i18n){
    var frameworkControl=["$rootScope","$scope","$modal",function($rootScope,$scope,$modal){
        $rootScope.menus={
            "url":"framework/views/menu.html"
        };
        $scope.i18n = i18n;

        $scope.change = function(language){
            var expires = new Date(9999,12,31).toUTCString();
            document.cookie = "lan="+language+"; "+expires;

            location.reload();
        };

        $scope.modal = function(){
            $modal.open({
                templateUrl:"framework/views/modal.html",
                backdrop:false
            });
        }
    }];
    return frameworkControl;
})

新增backdrop配置項位置如下:


重新觸發彈出框效果:


可以看到,相比預設的true屬性效果,彈出框顯示時不再會灰化背景,但是當滑鼠在非彈出框範圍點選時,彈出框不會消失。

接下來是配置為static(程式碼和配置項變更截圖略):


和預設的true屬性效果相比,同樣會灰化背景,但是當滑鼠在非彈出框範圍點選時,彈出框不會消失。這三個屬性對應的效果無所謂哪個好哪個不好,而是控制元件本身提供的功能可以讓彈出框匹配不同的業務需求:

true適用於頁面的一些告警或提醒,無需使用者移動滑鼠去點選關閉彈出框,可以提升使用者體驗;

false適用於全域性的頁面提示,彈出框不影響使用者繼續進行其他操作(即可以不管彈出框,繼續點選其他的按鈕或連結,當然這需要頁面進行圖層的適配,讓彈出框的z-index小 於父頁面的z-index);

static適用於最常用的業務邏輯控制,使用者必須完成與彈出框的互動才能繼續操作父頁面。

然後來看一下彈出框和父頁面如何進行資料互動(這也是常用的功能,比如商城系統中我們希望使用者點選商品列表中的某一件商品時能夠在彈出框中顯示商品的詳細資訊,那麼 在實現時就必須在點選彈出框的時候把商品id傳過去)。

這個問題(或者說需求)可以參考API裡的這個屬性:

resolve:定義一個成員並將他傳遞給$modal指定的控制器,相當於routes的一個reslove屬性,如果需要傳遞一個object物件,需要使用angular.copy()

下面筆者用一個最簡單的例子來說明resolve的用法——實現父頁面向彈出框傳遞一個“it is a message”字串這樣一個功能:

在frameworkCtrl.js中新增需要傳遞給彈出框的字串以及彈出框的controller和resolve:

/**
 * Created by 李慶 on 2016/10/6.
 */
define(["language"],function(i18n){
    var frameworkControl=["$rootScope","$scope","$modal",function($rootScope,$scope,$modal){
        $rootScope.menus={
            "url":"framework/views/menu.html"
        };
        $scope.i18n = i18n;
        $scope.item = "it is a message";

        $scope.change = function(language){
            var expires = new Date(9999,12,31).toUTCString();
            document.cookie = "lan="+language+"; "+expires;

            location.reload();
        };

        var modalController = function($scope, $modalInstance, item){
            $scope.item = item;
        }

        $scope.modal = function(){
            $modal.open({
                templateUrl:"framework/views/modal.html",
                backdrop:"static",
                controller:modalController,
                resolve:{
                    "item":function(){
                        return $scope.item;
                    }
                }
            });
        }
    }];
    return frameworkControl;
})
變更程式碼如下:



在彈出框的檢視modal.html中顯示父頁面傳遞的值,以便我們確認值已經在彈出框獲取:

<div style="width: 600px; height: 200px; border-radius: 4px">
    <div>{{item}}</div>
    <button ng-click="close()">關閉</button>
</div>

變更程式碼如下:


重新觸發彈出框效果:


可以看到父頁面傳遞的字串在彈出框正常顯示,即我們可以通過$modal提供的controller和resolve來完成父頁面向彈出框傳值的功能。