日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

5分鐘帶你了解【前端裝飾器】,“高大上”的“基礎知識”

來源: 責編: 時間:2024-05-08 09:20:36 163觀看
導讀前言大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘,基礎是進階的前提是我的初心。基本介紹裝飾器是一種以 @ 符號開頭的特殊語法,放在目標代碼的前面用于包裝或擴展代碼功能。JavaScript 的裝飾器語法目

前言

大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘,基礎是進階的前提是我的初心。Nd328資訊網——每日最新資訊28at.com

基本介紹

裝飾器是一種以 @ 符號開頭的特殊語法,放在目標代碼的前面用于包裝或擴展代碼功能。JavaScript 的裝飾器語法目前仍處于提案階段,現階段使用的話需要通過 bable 等方式進行編譯之后,才能在瀏覽器正常運行。裝飾器分為兩種:類裝飾器,類成員裝飾器,分別用于裝飾我們的類以及類的成員。Nd328資訊網——每日最新資訊28at.com

基本使用(類裝飾器)

class MyClass {  constructor() {}}

比如現在有一個類或者函數 MyClass,它的身上沒有任何的東西,但是我想要給他加一個 log 方法,那我們應該怎么做呢?很多人回想說,直接在它身上加一個 log 方法即可~Nd328資訊網——每日最新資訊28at.com

class MyClass {  constructor() {}    log() {}}

但是這么做的話,一個 class 是能做,那如果要給 1000 個 class 加上 log方法呢?那豈不是每一個都得寫~很麻煩,這個時候可以使用 裝飾器 去拓展每一個 classNd328資訊網——每日最新資訊28at.com

  • 可以拓展原型方法
  • 可以拓展靜態屬性

裝飾器接收的參數是裝飾的目標類,這里的 cls 就是 MyClassNd328資訊網——每日最新資訊28at.com

function addConcole(target) {  // 拓展原型方法  target.prototype.log = function(msg) {    console.log(`[${new Date()} ${msg}`);  };  // 拓展靜態屬性  target.myName = '一個類'  return target;}@addConcoleclass MyClass {  constructor() {}}const myObj = new MyClass();myObj.log('林三心');// [Sat Jul 08 2023 17:31:55 GMT+0800 (中國標準時間) 林三心console.log(MyClass.myName)// 一個類

應用場景

Node路由請求Url(類成員裝飾器)

我們在使用一些 Node 的框架時,在寫接口的時候,我們可能會經常看到這樣的代碼Nd328資訊網——每日最新資訊28at.com

  • 當我們請求路徑是 GET doc 時會匹配到findDocById
  • 當我們請求路徑是 POST doc 時會匹配到createDoc
class Doc {  @Get('doc')  async findDocById(id) {}    @Post('doc')  async createDoc(data) {}}

其實這個 @Get 和 @Post ,是框架提供給我們的 類成員裝飾器,是的,類成員也能使用裝飾器,類成員裝飾器接收三個參數:Nd328資訊網——每日最新資訊28at.com

  • target 是目標類的原型對象
  • key 表示目標類成員的鍵名
  • descriptor 是一個屬性描述符對象,它包含目標類成員的屬性特性(例如 value、writable 等)
function Get(path) {  return function(target, key, descriptor) {    console.log({      target,      key,      descriptor    })  }}

圖片圖片Nd328資訊網——每日最新資訊28at.com

他的基本實現原理大概是這樣的Nd328資訊網——每日最新資訊28at.com

function Get(routePath) {  return function(target, key, descriptor) {    const originalMethod = descriptor.value; // 保存原始方法    descriptor.value = function() {      // 在原始方法執行前加入邏輯      console.log('處理 Get 請求,路由路徑: ' + routePath);      // 執行原始方法      const result = originalMethod.apply(this, arguments);      // 在原始方法執行后加入邏輯      console.log('Get 請求處理完成');      return result;    };    return descriptor;  };}

接口權限控制(類成員裝飾器疊加)

上面我們介紹了一下 Nodejs Url 的路由匹配基本原理,但是這是不夠的,因為很多接口還需要權限控制,比如:Nd328資訊網——每日最新資訊28at.com

  • GET doc 接口只能 管理員 才能訪問
  • POST doc 接口只能 超級管理員 才能訪問

這也可以用裝飾器來實現,并且裝飾器是可以疊加的~Nd328資訊網——每日最新資訊28at.com

class Doc {  @Get('doc')  @Role('admin')  async findDocById(id) {}    @Post('doc')  @Role('superAdmin')  async createDoc(data) {}}

裝飾器疊加的執行順序是 從下往上 的~我們可以看一下下面的例子,發現輸出順序是Nd328資訊網——每日最新資訊28at.com

  • 2
  • 1
function A () {  console.log(1)}function B () {  console.log(2)}class Doc {  @A  @B  async test() {}}

至于權限控制的裝飾器實現,需要根據不同業務去實現,我這里就粗略實現一下Nd328資訊網——每日最新資訊28at.com

function Role(permissions) {  return function(target, key, descriptor) {    const originalMethod = descriptor.value; // 保存原始方法    descriptor.value = function() {      // 在原始方法執行前進行權限驗證      const user = getCurrentUser(); // 獲取當前用戶信息      // 檢查用戶是否擁有所需權限      const hasPermission = checkUserPermissions(user, permissions);      if (!hasPermission) {        // 如果用戶沒有權限,則拋出錯誤或執行其他處理        throw new Error('無權限訪問該接口');      }      // 執行原始方法      const result = originalMethod.apply(this, arguments);      return result;    };    return descriptor;  };}

記錄日志的裝飾器

我們想要在執行某個函數的時候,記錄一下Nd328資訊網——每日最新資訊28at.com

  • 函數調用時間
  • 函數調用參數

這個時候我們也可以使用裝飾器來完成,非常方便!!!Nd328資訊網——每日最新資訊28at.com

// 日志裝飾器函數function logDecorator(target, key, descriptor) {  const originalMethod = descriptor.value; // 保存原始方法  descriptor.value = function(...args) {    console.log(`調用函數:${key}`);    console.log(`參數:${JSON.stringify(args)}`);    // 執行原始方法    const result = originalMethod.apply(this, args);    console.log(`返回值:${result}`);    return result;  };  return descriptor;}// 示例類class Example {  @logDecorator  greet(name) {    return `Hello, ${name}!`;  }}// 測試const example = new Example();example.greet('林三心');

緩存的裝飾器

如果我們執行一個方法,獲取返回值需要經過一系列的計算,非常耗時間,那么我們可以判斷入參,第一次時計算完緩存起來,第二次的時候如果還是這個入參,就直接從緩存中去拿,這個操作也可以使用裝飾器去完成Nd328資訊網——每日最新資訊28at.com

// 緩存裝飾器函數function cacheDecorator(target, key, descriptor) {  const cache = {}; // 緩存對象  const originalMethod = descriptor.value; // 保存原始方法  descriptor.value = function(...args) {    const cacheKey = JSON.stringify(args); // 生成緩存鍵    if (cacheKey in cache) {      console.log('從緩存中獲取結果');      return cache[cacheKey]; // 直接返回緩存結果    }    // 執行原始方法    const result = originalMethod.apply(this, args);    console.log('將結果緩存起來');    cache[cacheKey] = result; // 緩存結果    return result;  };  return descriptor;}// 示例類class Example {  @cacheDecorator  getValue(key) {    console.log('執行函數邏輯');    return key + Math.random(); // 模擬復雜的計算邏輯  }}// 測試const example = new Example();console.log(example.getValue('foo'));console.log(example.getValue('foo')); // 從緩存中獲取結果

防抖節流的裝飾器

對于防抖節流,我們平時可能會這么去做Nd328資訊網——每日最新資訊28at.com

class C {  onClick = debounce(fn, 100)}

但是這么做的話會使這個函數不好拓展,所以使用裝飾器真的很方便Nd328資訊網——每日最新資訊28at.com

// 防抖裝飾器function debounce(time) {  return function (target, key, descriptor) {    const oldFunction = descriptor.value;    let timer = null;    descriptor.value = function () {      clearTimeout(timer);      timer = setTimeout(() => {        oldFunction.apply(this, arguments)      }, time);    };    return descriptor;  }}// 節流裝飾器function throttle(time) {  return function (target, key, descriptor) {    const oldFunction = descriptor.value;    let isLock = false;    descriptor.value = function() {      if(isLock) { return; }      isLock = true;      oldFunction.apply(this, arguments);      setTimeout(() => {        isLock = false;       }, time);    }    return descriptor;  }}class C {  @debounce(1000)  onClick() {}    @throttle(1000)  onScroll() {}}


Nd328資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-87263-0.html5分鐘帶你了解【前端裝飾器】,“高大上”的“基礎知識”

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 關于 CSS 選擇器權重,99% 的人都理解錯了!

下一篇: 為什么要看 Python 源碼?它的結構長什么樣子?

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 庄河市| 舟山市| 吉林市| 冷水江市| 镇平县| 玉山县| 正宁县| 屏边| 莱州市| 凌海市| 柯坪县| 通城县| 五台县| 铁岭县| 呼图壁县| 同德县| 泸溪县| 察隅县| 临安市| 巫溪县| 伊宁市| 鄂尔多斯市| 安塞县| 车致| 海门市| 五莲县| 长垣县| 洛扎县| 大连市| 奉新县| 循化| 冕宁县| 亚东县| 奉化市| 太谷县| 蓬溪县| 中山市| 城市| 贵阳市| 马山县| 扎赉特旗|