自定義Angular插件 - 網站用戶引導


最近由於項目進行了較大的改版,為了讓用戶能夠適應這次新的改版,因此在系統中引入了“用戶引導”功能,對於初次進入系統的用戶一些簡單的使用培訓training。對於大多數網站來說,這是一個很常見的功能。所以在開發這個任務之前,博主嘗試將其抽象化,獨立於現有系統的業務邏輯,將其封裝為一個通用的插件,使得代碼更容易擴展和維護。

無圖無真相,先上圖:

training demo

關於這款trainning插件的使用很簡單,它采用了類似Angular路由一樣的配置,只需要簡單的配置其每一步training信息。

  • title:step的標題信息;
  • template/templateUrl: step的內容模板信息。這類可以配置html元素,或者是模板的url地址,同時templateUrl也支持Angular route一樣的function語法;
  • controller: step的控制器配置;在controller中可注入如下參數:當前step – currentStep、所有step的配置 – trainnings、當前step的配置 – currentTrainning、以及下一步的操作回調 – trainningInstance(其中nextStep:為下一步的回調,cancel為取消用戶引導回調);
  • controllerAs: controller的別名;
  • resolve:在controller初始化前的數據配置,同Angular路由中的resolve;
  • locals:本地變量,和resolve相似,可以傳遞到controller中。區別之處在於它不支持function調用,對於常量書寫會比resolve更方便;
  • placement: step容器上三角箭頭的顯示方位,
  • position: step容器的具體顯示位置,這是一個絕對坐標;可以傳遞{left: 100, top: 100}的絕對坐標,也可以是#stepPanelHost配置相對於此元素的placement位置。同時它也支持自定義function和注入Angular的其他組件語法。並且默認可注入:所有step配置 – trainnings,當前步驟 – step,當前step的配置 – currentTrainning,以及step容器節點 – stepPanel;
  • backdrop:是否需要顯示遮罩層,默認顯示,除非顯示聲明為false配置,則不會顯示遮罩層;
  • stepClass:每一個step容器的樣式信息;
  • backdropClass: 每一個遮罩層的樣式信息。

了解了這些配置后,並根據特定需求定制化整個用戶引導的配置信息后,我們就可以使用trainningService的trainning方法來在特定實際啟動用戶引導,傳入參數為每一步step的配置信息。並可以注冊其done或者cancel事件:

trainningService.trainning(trainningCourses.courses)
    .done(function() {
        vm.isDone = true;
    });

下面是一個演示的配置信息:

    .constant('trainningCourses', {
                courses: [{
                    title: 'Step 1:',
                    templateUrl: 'trainning-content.html',
                    controller: 'StepPanelController',
                    controllerAs: 'stepPanel',
                    placement: 'left',
                    position: '#blogControl'
                },{
                    title: 'Step 3:',
                    templateUrl: 'trainning-content.html',
                    controller: 'StepPanelController',
                    controllerAs: 'stepPanel',
                    placement: 'top',
                    position: {
                        top: 200,
                        left: 100
                    }
                },
                    ...
                {
                    stepClass: 'last-step',
                    backdropClass: 'last-backdrop',
                    templateUrl: 'trainning-content-done.html',
                    controller: 'StepPanelController',
                    controllerAs: 'stepPanel',
                    position: ['$window', 'stepPanel', function($window, stepPanel) {
                        // 自定義函數,使其屏幕居中
                        var win = angular.element($window);
                        return {
                            top: (win.height() - stepPanel.height()) / 2,
                            left: (win.width() - stepPanel.width()) / 2
                        }
                    }]
                }]
            })

本文插件源碼和演示效果唯一codepen上,效果如下:

See the Pen ng-trainning by green (@greengerong) on CodePen.

在trainning插件的源碼設計中,包含如下幾個要點:

  • 提供service api。因為關於trainning這個插件,它是一個全局的插件,正好在Angular中所有的service也是單例的,所以將用戶引導邏輯封裝到Angular的service中是一個不錯的設計。但對於trainning的每一步展示內容信息則是DOM操作,在Angular的處理中它不該存在於service中,最佳的方式是應該把他封裝到Directive中。所以這里采用Directive的定義,並在service中compile,然后append到body中。
  • 對於每一個這類獨立的插件應該封裝一個獨立的scope,這樣便於在后續的銷毀,以及不會與現有的scope變量的沖突。
  • $q對延時觸發的結果包裝。對於像該trainning插件或者modal這類操作結果采用promise的封裝,是一個不錯的選擇。它取代了回調參數的復雜性,並以流暢API的方式展現,更利於代碼的可讀性。同時也能與其他Angular service統一返回API。
  • 對於controller、controllerAs、resolve、template、templateUrl這類類似路由的處理代碼,完全可以移到到你的同類插件中去。它們可以增加插件的更多定制化擴展。關於這部分代碼的解釋,博主將會在后續文章中為大家推送。
  • 利用$injector.invoke動態注入和調用Angular service,這樣既能獲取Angular其他service注入的擴展性,也能獲取到函數的動態性。如上例中的屏幕居中的自定義擴展方式。

這類設計要點,同樣可以運用到想modal、alert、overload這類全局插件中。有興趣的讀者,你可以在博主的codepen筆記中閱讀這段代碼http://codepen.io/greengerong/pen/pjwXQW#0


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM