ABP+AdminLTE+Bootstrap Table權(quán)限管理系統(tǒng)第七節(jié)--登錄邏輯及abp封裝的Javascript函數(shù)庫

ABP+AdminLTE+Bootstrap Table權(quán)限管理系統(tǒng)一期
Github:https://github.com/Jimmey-Jiang/ABP-ASP.NET-Boilerplate-Project-CMS
前往博客園總目錄:ABP+AdminLTE+Bootstrap Table權(quán)限管理系統(tǒng)一期

經(jīng)過前幾節(jié),我們已經(jīng)解決數(shù)據(jù)庫,模型,DTO,控制器和注入等問題.那么再來看一下登錄邏輯.這里算是前面幾節(jié)的一個初次試水.
首先我們數(shù)據(jù)庫已經(jīng)有的相應(yīng)的數(shù)據(jù).



模型和DTO已經(jīng)建好,所以我們直接在服務(wù)層添加Login方法就可以了.



在展現(xiàn)層添加Account控制器,注入IUserService接口,調(diào)用Login方法.

然后添加視圖頁面.


運(yùn)行一下,看一下結(jié)果.




除了頁面比較漂亮(哈哈),這些本來都沒有什么好說的,直接上圖,
這里值得注意的是,我們在創(chuàng)建下面的方法,在調(diào)用接口的的時候會報一個錯誤:web的App_Data/Logs/Logs.txt日志文件中查看到打印到錯誤信息。
public async Task<ListResultDto<UserInfoDto>> GetUsers()
        {
            var users = await _userRepository.GetAllListAsync();

            return new ListResultDto<UserInfoDto>(
                users.MapTo<List<UserInfoDto>>()
                );
        }

錯誤提示: Mapper not initialized. Call Initialize with appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance.
意思是:映射器未初始化。 通過適當(dāng)?shù)呐渲谜{(diào)用初始化。 如果您嘗試通過容器或其他方式使用映射器實(shí)例,請確保您沒有任何調(diào)用靜態(tài)Mapper.Map方法,如果您使用ProjectTo或UseAsDataSource擴(kuò)展方法,請確保您傳入相應(yīng)的IConfigurationProvider實(shí)例。
原因:Mapper not initialized 映射未初始化
解決:在ApplicationModule類中增加依賴typeof(AbpAutoMapperModule)即可。

using System.Reflection;
using Abp.Modules;
using Abp.AutoMapper;

namespace JCmsErp
{
    [DependsOn(typeof(JCmsErpCoreModule), typeof(AbpAutoMapperModule))]
    public class JCmsErpApplicationModule : AbpModule
    {
        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
        }
    }
}

另外上面這個提示窗是不是很漂亮,登錄頁面的設(shè)計(jì)樣式都是自己寫的,自己這個彈窗,只是abp自己封裝.我們來看一下具體的代碼.

abp.message.confirm(
                    '請輸入密碼.', //確認(rèn)提示
                    '確定?',//確認(rèn)提示(可選參數(shù))
                    function (isConfirmed) {
                        if (isConfirmed) {
                            //...delete user 點(diǎn)擊確認(rèn)后執(zhí)行
                        }
                    }
                );

其實(shí)abp封裝很多js函數(shù)庫,這讓我不得不感嘆土牛(土耳其牛人)真是牛啊!看下圖左邊部分js文件



包括像abp.jquery.js,ABP服務(wù)端支持標(biāo)準(zhǔn)的ajax的請求/輸出。建議大家使用abp.jquery.js中提供的ajax請求方法,這個方法基于jquery的ajax方法,可以自動處理服務(wù)端的異常信息,當(dāng)然,如果你對js很熟練的話,也可以根據(jù)自己的需要寫ajax。你也可以使用jquery的ajax方法調(diào)用,但是需要設(shè)置一下默認(rèn)請求參數(shù),dataType 設(shè)置為 'json', type 設(shè)置為 'POST' and contentType 設(shè)置為 'application/json,在發(fā)送請求時需要將js對象轉(zhuǎn)換成json字符串,和$.ajax一樣,你也可以傳遞參數(shù)覆蓋abp.ajax的默認(rèn)參數(shù)abp.ajax返回一個promise類型.Login上標(biāo)記了 HttpPost 特性 abp.ajax默認(rèn)以 POST 方式請求. 返回值被簡化成了一個匿名對象。
消息
用于向用戶顯示對話框,展示消息或者得到用戶的確認(rèn),ABP默認(rèn)采用的sweetalert庫實(shí)現(xiàn)的對話框信息,使用時你需要引用sweetalert的樣式和js,在我的登錄頁面里面已經(jīng)引用了,并且引用abp.sweet-alert.js就可以使用下列API了:

abp.message.info('some info message', 'some optional title');
abp.message.success('some success message', 'some optional title');
abp.message.warn('some warning message', 'some optional title');
abp.message.error('some error message', 'some optional title');

abp.message.confirm(
    'User admin will be deleted.', //確認(rèn)提示
    'Are you sure?',//確認(rèn)提示(可選參數(shù))
    function (isConfirmed) {
        if (isConfirmed) {
            //...delete user 點(diǎn)擊確認(rèn)后執(zhí)行
        }
    }
);

用戶界面的繁忙提示
設(shè)置一個半透明層,阻止點(diǎn)擊頁面元素,可以覆蓋局部或者整個頁面,例子如下:

abp.ui.block(); //覆蓋整個頁面
abp.ui.block($('#MyDivElement')); //覆蓋指定元素,可以把jquery對象作為參數(shù)
abp.ui.block('#MyDivElement'); //或者直接使用選擇器參數(shù)
abp.ui.unblock(); //整個頁面解除覆蓋
abp.ui.unblock('#MyDivElement'); //指定元素解除覆蓋

UI Block API使用blockUI這個js庫來實(shí)現(xiàn)效果的,如果使用這個api需要在頁面引用blockUI的js庫和abp.blockUI.js文件。
UI Busy API 指示頁面繁忙的API,如ajax請求中:

abp.ui.block = function (elm) {
        if (!elm) {
            $.blockUI();
        } else {
            $(elm).block();
        }
    };

    abp.ui.unblock = function (elm) {
        if (!elm) {
            $.unblockUI();
        } else {
            $(elm).unblock();
        }
    };

abp.ui.setBusy('#MyLoginForm');
abp.ui.clearBusy('#MyLoginForm');

Js日志接口
這個主要是對瀏覽器console.log('...') 進(jìn)行的包裝,可以支持所有瀏覽器,你可以通過設(shè)置abp.log.level來控制日志輸出,和服務(wù)端一樣,如設(shè)置了abp.log.levels為INFO時就不會輸出debug日志了,你也可以根據(jù)你的需要定制重新這些API。

abp.notify.success = function (message, title, options) {
        abp.log.warn('abp.notify.success is not implemented!');
    };

    abp.notify.info = function (message, title, options) {
        abp.log.warn('abp.notify.info is not implemented!');
    };

    abp.notify.warn = function (message, title, options) {
        abp.log.warn('abp.notify.warn is not implemented!');
    };

    abp.notify.error = function (message, title, options) {
        abp.log.warn('abp.notify.error is not implemented!');
    };

格式化字符串(abp.utils.formatString)
和C#的string.Format一樣的用法

/* Formats a string just like string.format in C#.
    *  Example:
    *  abp.utils.formatString('Hello {0}','Tuana') = 'Hello Tuana'
    ************************************************************/
    abp.utils.formatString = function () {
        if (arguments.length < 1) {
            return null;
        }

        var str = arguments[0];

        for (var i = 1; i < arguments.length; i++) {
            var placeHolder = '{' + (i - 1) + '}';
            str = abp.utils.replaceAll(str, placeHolder, arguments[i]);
        }

        return str;
    };

最后,當(dāng)然我們登錄頁面也可以改一下.這樣就更簡潔了.

var url = "/Account/Login";
            //構(gòu)建要傳輸?shù)膮?shù)對象
            var newPerson = {
                userName:$("#userName").val(),
                password:$("#password").val() }
            };
            //調(diào)用abp的ajax方法
            abp.ajax({
                url:url,
                data: JSON.stringify(newPerson) //轉(zhuǎn)換成json字符串
            }).done(function (data) {
                abp.message.warn('用戶名或密碼錯誤!', '登錄失敗');
            });

至此,我們登錄邏輯,和JavaScript封裝模塊就全部完成了,其實(shí)abp提示窗還蠻好看的,大家也可以借鑒一下在自己的項(xiàng)目里面.
下面說下JavaScript的封裝。

AJAX操作問題

現(xiàn)代的應(yīng)用經(jīng)常會使用AJAX,尤其是單頁應(yīng)用,幾乎是和服務(wù)器通信的唯一手段,執(zhí)行AJAX通常會有以下步驟:

  • 基本上:為了執(zhí)行一個AJAX調(diào)用,首先你要在客戶端提供一個可供請求的URL,選取提交數(shù)據(jù)和一個方法(GET,POST,PUT,DELETE)。

  • 等待調(diào)用完成后,處理返回結(jié)果。當(dāng)執(zhí)行AJAX調(diào)用服務(wù)器端的時候,可能會有錯誤(一般是網(wǎng)絡(luò)錯誤)。當(dāng)然也有可能是服務(wù)器端產(chǎn)生了一些錯誤,對于這些錯誤會,服務(wù)器會返回一個失敗的響應(yīng)并且附上錯誤消息給客戶端。

  • 客戶端代碼應(yīng)該處理這些錯誤,并且可以選擇通知用戶(可以顯示一個錯誤對話框)。如果沒有錯誤且服務(wù)器端返回了數(shù)據(jù),客戶端必須處理它。還有你應(yīng)該限制頁面的某個區(qū)域(或者整個頁面),并顯示一個忙碌的指示直到AJAX操作完成。

  • 服務(wù)器端在得到請求后執(zhí)行服務(wù)器端代碼,捕獲異常并返回一個有效的響應(yīng)給客戶端。在錯誤情況下,可以選擇發(fā)送錯誤消息給客戶端。如果是驗(yàn)證錯誤,服務(wù)器端可以添加驗(yàn)證錯誤的驗(yàn)證信息。在成功情況下,可以發(fā)送返回值給客戶端。

ABP的方式

由于使用 abp.ajax 函數(shù)對AJAX調(diào)用進(jìn)行了封裝, 所以ABP能自動化這些步驟。下面是一個AJAX調(diào)用示例:

var newPerson = {
    name: 'Dougles Adams',
    age: 42
};

abp.ajax({
    url: '/People/SavePerson',
    data: JSON.stringify(newPerson)
}).done(function(data) {
    abp.notify.success('created new person with id = ' + data.personId);
});

abp.ajax得到 options 作為對象。你可以傳遞任何有效的jQuery的 $.ajax 函數(shù)中的參數(shù)。有一些默認(rèn)參數(shù):dataType 是 json,type是 POST,還有 contentType是 application/json(在發(fā)送數(shù)據(jù)到服務(wù)器端之前,我們需要調(diào)用 JSON.stringify 將腳本對象轉(zhuǎn)換為JSON字符串)。通過對apb.ajax傳遞options可以覆蓋默認(rèn)值。

abp.ajax返回promise。因此,你可以寫這些處理函數(shù):done,fail,then等等。在這個例子中,我們對 PeopleController's SavePerson action 發(fā)送了一個簡單的AJAX請求。在 done 處理函數(shù)中,我們對新創(chuàng)建的person取得了它的主鍵id并且顯示了創(chuàng)建成功的通知。讓我們看看 MVC Controller

public class PeopleController : AbpController
{
    [HttpPost]
    public JsonResult SavePerson(SavePersonModel person)
    {
        //TODO: 保存新創(chuàng)建的person到數(shù)據(jù)庫并且返回person的id
        return Json(new {PersonId = 42});
    }
}

正如你猜測的 SavePersonModel 包含了Name和Age屬性。SavePerson 被標(biāo)記為 HttpPost 特性,因?yàn)閍bp.ajax默認(rèn)方法是POST。通過返回了匿名對象簡化了方法實(shí)現(xiàn)。

這個看上去很簡單直白,但是ABP在背后做了很多重要的處理。讓我們深入了解一下:

AJAX 返回消息

即使我們直接的返回了一個帶有PersonId = 2 的對象,ABP也會使用 MvcAjaxResponse 對象來包裝它。事實(shí)上AJAX響應(yīng)返回的內(nèi)容應(yīng)該像下面一樣:

{
  "success": true,
  "result": {
    "personId": 42
  },
  "error": null,
  "targetUrl": null,
  "unAuthorizedRequest": false,
  "__abp": true
}

在這里所有的屬性都是駝峰命名的(因?yàn)檫@在JavaScript中是慣例),即使在服務(wù)端代碼中是PascalCased的。下面解釋一下所有的字段:

  • success:boolean類型的值(true或者false),用來表示操作的成功狀態(tài)。如果是ture,abp.ajax會解析該promise并且調(diào)用 done 函數(shù)。如果是false(在方法被調(diào)用的時候,如果有個異常被拋出),它會調(diào)用 fail 函數(shù)并且使用 abp.message.error 函數(shù)顯示 error 消息。

  • result:控制器的action的實(shí)際返回值。如果success是ture并且服務(wù)器發(fā)送了返回值那么它才是有效的。

  • error:如果success是false,這個字段是一個包含 message和details 字段的對象。

  • targetUrl:如果需要的話,這提供了一種可能性:服務(wù)器端發(fā)送一個URL到客戶端,使客戶端可以重定向到其它的URL。

  • unAuthorizedRequest:這提供了一種可能性:服務(wù)器端發(fā)送通知給客戶端該操作未被授權(quán),或者是未認(rèn)證用戶。如果該值是true,那么abp.ajax會 reloads 當(dāng)前的頁面。

  • __abp:通過ABP包裝響應(yīng)返回的特殊簽名。你自己不需要用到它,但是abp.ajax會處理它。

這種格式的對象會被 abp.ajax 函數(shù)識別且處理。abp.ajax會得到控制器的實(shí)際返回值(一個帶有personid屬性的對象),如果沒有錯誤的話,那么你會在done函數(shù)中處理返回值。

處理錯誤

正如上面所述,ABP在服務(wù)器端處理異常,并且返回一個帶有錯誤消息的對象。如下所示:

{
  "targetUrl": null,
  "result": null,
  "success": false,
  "error": {
    "message": "An internal error occured during your request!",
    "details": "..."
  },
  "unAuthorizedRequest": false,
  "__abp": true
}

正如你看到的,success是false 并且 result是null。abp.ajax處理這個對象,并且使用abp.message.error函數(shù)來顯示錯誤消息給用戶。如果你的服務(wù)器端代碼拋出了 UserFriendlyException 類型的異常。它會直接的顯示異常信息給用戶。否則,它會隱藏實(shí)際的錯誤(將錯誤寫入日志),并且顯示一個標(biāo)準(zhǔn)的“服務(wù)器內(nèi)部錯誤...”信息給用戶。所有的這些都是ABP自動處理的。

你可能想為某個特別的AJAX調(diào)用禁止顯示消息,那么添加 ** abpHandleError: false** 到 abp.ajax的options。

HTTP狀態(tài)碼

在異常發(fā)生的時候,ABP會返回給定的HTTP狀態(tài)碼:

  • 401:未經(jīng)身份驗(yàn)證的請求(沒有登錄,但是服務(wù)器端需要身份驗(yàn)證);

  • 403:未授權(quán)的請求;

  • 500:所有其它類型的異常。

6.6.2.5 WrapResult和DontWrapResult特性

使用 WrapResult和DontWrapResult 特性,可以對控制器的某個action或者所有的action來控制包裝。

ASP.NET MVC 控制器

如果返回的類型是 JsonResult(或者Task<JsonResult>),那么ABP會默認(rèn)包裝ASP.NET MVC action的返回結(jié)果。你可以使用 WrapResult 特性來改變它。如下所示:

public class PeopleController : AbpController
{
    [HttpPost]
    [WrapResult(WrapOnSuccess = false, WrapOnError = false)]
    public JsonResult SavePerson(SavePersonModel person)
    {
        //TODO: 保存新創(chuàng)建的person到數(shù)據(jù)庫并且返回person的id
        return Json(new {PersonId = 42});
    }
}

作為一個快速開發(fā)方式,我們只能使用 [DontWrapResult] 特性在這個相同的示例上。

你可以在啟動配置里面改變這個默認(rèn)的行為(使用 Configuration.Modules.AbpMvc()...)。

ASP.NET Web API 控制器

如果action被成功執(zhí)行,ABP 不會默認(rèn)包裝 Web API Action的返回結(jié)果。如果需要的話,你可以添加WrapResult特性到action或者控制器上。但是它會 包裝異常。

你可以在啟動配置里面改變這個默認(rèn)的行為(使用 Configuration.Modules.AbpWebApi()...)。

動態(tài)Web API層

默認(rèn) ABP會 包裝 動態(tài)Web API層的所有方法。你可以在你應(yīng)用服務(wù)的接口上使用 WrapResult和DontWrapResult 特性來改變這個行為。

你可以在啟動配置里面改變這個默認(rèn)的行為(使用 Configuration.Modules.AbpWebApi()...)。

ASP.NET Core 控制器

ABP會自動包裝JsonResult,ObjectRes以及那些沒有實(shí)現(xiàn)IActionResult對象。詳情請查閱ASP.NET Core文檔。

你可以在啟動配置里面改變這個默認(rèn)的行為(使用 using Configuration.Modules.AbpAspNetCore()...)。

動態(tài)Web API層

雖然ABP提供了一種調(diào)用Ajax的簡單機(jī)制,但是在真實(shí)世界的應(yīng)用中,為每個Ajax調(diào)用編寫javascript函數(shù)是很經(jīng)典的。例如:

//創(chuàng)建一個抽象了Ajax調(diào)用的function
var savePerson = function(person) {
    return abp.ajax({
        url: '/People/SavePerson',
        data: JSON.stringify(person)
    });
};

//創(chuàng)建一個新的 person
var newPerson = {
    name: 'Dougles Adams',
    age: 42
};

//保存該person
savePerson(newPerson).done(function(data) {
    abp.notify.success('created new person with id = ' + data.personId);
});

這是一個最佳實(shí)踐,但是對每個AJAX調(diào)用函數(shù)都這樣做,那是耗時且乏味的。對于應(yīng)用服務(wù)和控制器,ABP能夠自動的生成這些函數(shù)。

詳情請閱讀動態(tài)Web API層文檔ASP.NET Core文檔

Javascript Notification API

當(dāng)一些事情發(fā)生的時候,我們喜歡顯示一些別致的能夠自動消失的通知,例如,當(dāng)某個記錄被保存或者某個問題發(fā)生的時候。ABP定義了標(biāo)準(zhǔn)的API實(shí)現(xiàn)了該功能。

abp.notify.success('a message text', 'optional title');
abp.notify.info('a message text', 'optional title');
abp.notify.warn('a message text', 'optional title');
abp.notify.error('a message text', 'optional title');

作為通知庫的 自定義選項(xiàng),它也能夠取得第3個參數(shù)(對象)。

通知API默認(rèn)是使用toastr庫實(shí)現(xiàn)的。要使toastr生效,你應(yīng)該引用toastr的css和javascript文件,然后再在頁面中包含abp.toastr.js作為適配器。一個toastr成功通知如下所示:

image.png

你也可以用你最喜歡的通知庫實(shí)現(xiàn)通知。只需要在自定義javascript文件中重寫所有的函數(shù),然后把它添加到頁面中而不是abp.toastr.js中(你可以檢查該文件看它是否實(shí)現(xiàn),這個相當(dāng)簡單)。

abp.message簡介

消息API被用來向用戶顯示一個消息或者從用戶那里得到一個確認(rèn)。

消息API默認(rèn)實(shí)現(xiàn)方式是使用了sweetalert庫。使用時你需要引用sweetalert的樣式和js,然后把 abp.sweet-alert.js 作為適配器包含到你的頁面中。

顯示消息

如下所示:

abp.message.info('some info message', 'some optional title');
abp.message.success('some success message', 'some optional title');
abp.message.warn('some warning message', 'some optional title');
abp.message.error('some error message', 'some optional title');

成功的消息框顯示如下:

image.png

Confirmation對話框

如下所示:

abp.message.confirm(
    'User admin will be deleted.', //確認(rèn)提示
    'Are you sure?',//確認(rèn)提示(可選參數(shù))
    function (isConfirmed) {
        if (isConfirmed) {
            //...delete user 點(diǎn)擊確認(rèn)后執(zhí)行
        }
    }
);

第二個參數(shù)(標(biāo)題)是可選的(所以,回調(diào)函數(shù)可以作為第二個參數(shù))。

確認(rèn)消息框顯示如下:

image.png

ABP在內(nèi)部使用了消息API,例如:如果某個AJAX調(diào)用失敗,那么它會調(diào)用abp.message.error。

Javascript UI Block & Busy API

ABP提供了有用的API,使整個頁面或者頁面的某個部分被遮罩層覆蓋實(shí)現(xiàn)阻塞或者繁忙指示(使用加載圖標(biāo)表示繁忙)。

UI Block API

這個API使用一個透明的遮罩層(透明度可調(diào)節(jié))來遮住整個頁面或者該頁面的某個元素。因此用戶不能夠點(diǎn)擊。當(dāng)你保存表單或者加載某個區(qū)域時(某個層或者整個頁面),這是相當(dāng)有用的。

如下所示:

abp.ui.block(); //遮住整個頁面
abp.ui.block($('#MyDivElement')); //遮罩某個元素,在這里可以使用jQuery選擇器選擇元素..
abp.ui.block('#MyDivElement'); //..或者直接指定元素
abp.ui.unblock(); //解除遮罩
abp.ui.unblock('#MyDivElement'); //對指定元素解除遮罩

UI Block API 默認(rèn)是使用jQuery插件block UI來實(shí)現(xiàn)的。為了能正常運(yùn)行,你需要引用腳本文件,然后包含 abp.blockUI.js 文件作為適配器到你的頁面中。

UI Busy API

該API被用來指示某些頁面或者元素正在忙碌(加載)。例如:當(dāng)你提交表單數(shù)據(jù)到服務(wù)器的時候,你可能想要遮罩這個表單并顯示一個忙碌的指示器。

如下所示:

abp.ui.setBusy('#MyLoginForm');
abp.ui.clearBusy('#MyLoginForm');
image.png

參數(shù)應(yīng)該是一個jQuery選擇器(如:#MyLoginForm)或者jQuery對象(如:$('#MyLoginForm'))。為了使整個頁面都是在繁忙狀態(tài),你應(yīng)該傳遞null或者body作為選擇器。

setBusy函數(shù)能夠傳入一個promise(作為第二個參數(shù))并且自動的清除busy,當(dāng)該promise完成的時候。如下所示:

abp.ui.setBusy(
    $('#MyLoginForm'), 
    abp.ajax({ ... })   
);

由于abp.ajax返回的是promise,所以我們能直接使用它作為參數(shù)。如果你想了解更多關(guān)于promise的資料,請查閱jQuery的Deferred。setBusy對Q提供支持(以及angulars的$http服務(wù))。

UI Busy API 使用spin.js實(shí)現(xiàn)的。為使其正常運(yùn)行,你應(yīng)該引用該腳本文件,然后在你的頁面中包含 abp.spin.js 作為適配器。

ABP表現(xiàn)層 - 事件總線EventBUS

簡介

Pub/Sub 事件模型被廣泛的應(yīng)用在客戶端。ABP包含了一個 簡單的全局事件總線 用來注冊事件并且觸發(fā)事件。

注冊事件

你可以使用 abp.event.on注冊 一個 全局事件 。示例如下:

abp.event.on('itemAddedToBasket', function (item) {
    console.log(item.name + ' is added to basket!');
});

第一個參數(shù)是 該事件的唯一名稱。另一個參數(shù)是 回調(diào)函數(shù),當(dāng)指定的事件被觸發(fā)后將調(diào)用該參數(shù)。

你可以使用 abp.event.off 方法來 卸載 已注冊的事件。
注意:為了能夠卸載指定的事件,應(yīng)該提供相同的事件函數(shù)。
正如上面的示例所展示的,你應(yīng)該將回調(diào)函數(shù)設(shè)置為一個變量,然后在 on和off 中使用它。

觸發(fā)事件

abp.event.trigger 被用來觸發(fā)全局事件。觸發(fā)一個已注冊的事件的代碼如下:

abp.event.trigger('itemAddedToBasket', {
    id: 42,
    name: 'Acme Light MousePad'
});

第一個參數(shù)是 該事件的唯一名稱。第二個是(可選的)事件參數(shù)。你可以添加任何數(shù)量的參數(shù),并且在回調(diào)方法中獲得它們。

ABP表現(xiàn)層 - Javascript 日志 API

簡介

當(dāng)你想要在客戶端寫一些簡單的日志的時候,你可以使用 console.log('...') API。但是,它不是所有的瀏覽器都支持該API,并且該函數(shù)也可能破壞你的腳本。所以,在使用的時候你首先應(yīng)該檢查console是否有效。還有,你可能想在其它地方寫日志。甚至你可能對寫日志的等級也有要求。ABP定義了安全的日志函數(shù):

abp.log.debug('...');
abp.log.info('...');
abp.log.warn('...');
abp.log.error('...');
abp.log.fatal('...');

你可以通過設(shè)置 abp.log.levelabp.log.levels 中的某個日志等級進(jìn)行更改(例如:abp.log.levels.INFO 不會記錄調(diào)試日志)。這些函數(shù)默認(rèn)將日志記錄到了瀏覽器的控制臺里了。但如果你需要的話,你也可以重寫或者擴(kuò)展這個行為。

ABP表現(xiàn)層 - 其他工具函數(shù)OtherUtilities

ABP提供了一些通用的工具函數(shù)。

abp.utils.createNamespace

用于創(chuàng)建更深的命名空間。假設(shè)我們有一個基命名空間 abp,然后想要創(chuàng)建或者獲得 abp.utils.strings.formatting 命名空間。不需要像下面這樣寫:

//創(chuàng)建或獲得namespace
abp.utils = abp.utils || {};
abp.utils.strings = abp.utils.strings || {};
abp.utils.strings.formatting = abp.utils.strings.formatting || {};

//給該namespace添加一個function
abp.utils.strings.formatting.format = function() { ... };

我們可以這樣寫:

var formatting = abp.utils.createNamespace(abp, 'utils.strings.formatting');

//給該namespace添加一個function
formatting.format = function() { ... };

這樣即安全又簡單的創(chuàng)建了更深層次的命名空間。注意,第一個參數(shù)是必須存在的根命名空間。

abp.utils.formatString

近似于C#中的string.Format()方法。示例如下:

var str = abp.utils.formatString('Hello {0}!', 'World'); //str = 'Hello World!'
var str = abp.utils.formatString('{0} number is {1}.', 'Secret', 42); //str = 'Secret number is 42'

返回簡書總目錄:ABP+AdminLTE+Bootstrap Table權(quán)限管理系統(tǒng)一期
前往博客園總目錄:ABP+AdminLTE+Bootstrap Table權(quán)限管理系統(tǒng)一期

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容