国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

怎樣在項(xiàng)目中使用JS裝飾器函數(shù)

來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-27 19:40:04
文檔

怎樣在項(xiàng)目中使用JS裝飾器函數(shù)

怎樣在項(xiàng)目中使用JS裝飾器函數(shù):這次給大家?guī)碓鯓釉陧?xiàng)目中使用JS裝飾器函數(shù),怎在項(xiàng)目中使用JS裝飾器函數(shù)的注意事項(xiàng)有哪些,下面就是實(shí)戰(zhàn)案例,一起來看一下。在 ES6 中增加了對類對象的相關(guān)定義和操作(比如 class 和 extends ),這就使得我們在多個不同類之間共享或者擴(kuò)展一些方法或者
推薦度:
導(dǎo)讀怎樣在項(xiàng)目中使用JS裝飾器函數(shù):這次給大家?guī)碓鯓釉陧?xiàng)目中使用JS裝飾器函數(shù),怎在項(xiàng)目中使用JS裝飾器函數(shù)的注意事項(xiàng)有哪些,下面就是實(shí)戰(zhàn)案例,一起來看一下。在 ES6 中增加了對類對象的相關(guān)定義和操作(比如 class 和 extends ),這就使得我們在多個不同類之間共享或者擴(kuò)展一些方法或者

這次給大家?guī)碓鯓釉陧?xiàng)目中使用JS裝飾器函數(shù),怎在項(xiàng)目中使用JS裝飾器函數(shù)的注意事項(xiàng)有哪些,下面就是實(shí)戰(zhàn)案例,一起來看一下。

在 ES6 中增加了對類對象的相關(guān)定義和操作(比如 class 和 extends ),這就使得我們在多個不同類之間共享或者擴(kuò)展一些方法或者行為的時候,變得并不是那么優(yōu)雅。這個時候,我們就需要一種更優(yōu)雅的方法來幫助我們完成這些事情。

什么是裝飾器

Python 的裝飾器

在面向?qū)ο螅∣OP)的設(shè)計(jì)模式中,decorator被稱為裝飾模式。OOP的裝飾模式需要通過繼承和組合來實(shí)現(xiàn),而Python除了能支持 OOP 的 decorator 外,直接從語法層次支持 decorator。

如果你熟悉 python 的話,對它一定不會陌生。那么我們先來看一下 python 里的裝飾器是什么樣子的吧:

def decorator(f):
 print "my decorator"
 return f
@decorator
def myfunc():
 print "my function"
myfunc()
# my decorator
# my function

這里的 @decorator 就是我們說的裝飾器。在上面的代碼中,我們利用裝飾器給我們的目標(biāo)方法執(zhí)行前打印出了一行文本,并且并沒有對原方法做任何的修改。代碼基本等同于:

def decorator(f):
 def wrapper():
 print "my decorator"
 return f()
 return wrapper
def myfunc():
 print "my function"
myfunc = decorator(myfuc)

通過代碼我們也不難看出,裝飾器 decorator 接收一個參數(shù),也就是我們被裝飾的目標(biāo)方法,處理完擴(kuò)展的內(nèi)容以后再返回一個方法,供以后調(diào)用,同時也失去了對原方法對象的訪問。當(dāng)我們對某個應(yīng)用了裝飾以后,其實(shí)就改變了被裝飾方法的入口引用,使其重新指向了裝飾器返回的方法的入口點(diǎn),從而來實(shí)現(xiàn)我們對原函數(shù)的擴(kuò)展、修改等操作。

ES7 的裝飾器

ES7 中的 decorator 同樣借鑒了這個語法糖,不過依賴于 ES5 的 Object.defineProperty 方法 。

Object.defineProperty

Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現(xiàn)有屬性, 并返回這個對象。

該方法允許精確添加或修改對象的屬性。通過賦值來添加的普通屬性會創(chuàng)建在屬性枚舉期間顯示的屬性(for...in 或 Object.keys 方法), 這些值可以被改變,也可以被刪除。這種方法允許這些額外的細(xì)節(jié)從默認(rèn)值改變。默認(rèn)情況下,使用 Object.defineProperty() 添加的屬性值是不可變的。

語法

Object.defineProperty(obj, prop, descriptor)
  1. obj:要在其上定義屬性的對象。

  2. prop:要定義或修改的屬性的名稱。

  3. descriptor:將被定義或修改的屬性描述符。

  4. 返回值:被傳遞給函數(shù)的對象。

在ES6中,由于 Symbol類型 的特殊性,用 Symbol類型 的值來做對象的key與常規(guī)的定義或修改不同,而Object.defineProperty 是定義 key為 Symbol 的屬性的方法之一。

屬性描述符

對象里目前存在的屬性描述符有兩種主要形式:數(shù)據(jù)描述符和存取描述符。

數(shù)據(jù)描述符是一個具有值的屬性,該值可能是可寫的,也可能不是可寫的。

  • 存取描述符是由 getter-setter 函數(shù)對描述的屬性。

  • 描述符必須是這兩種形式之一;不能同時是兩者。

  • 數(shù)據(jù)描述符和存取描述符均具有以下可選鍵值:

    configurable

    當(dāng)且僅當(dāng)該屬性的 configurable 為 true 時,該屬性描述符才能夠被改變,同時該屬性也能從對應(yīng)的對象上被刪除。默認(rèn)為 false。

    enumerable

    enumerable定義了對象的屬性是否可以在 for...in 循環(huán)和 Object.keys() 中被枚舉。

    當(dāng)且僅當(dāng)該屬性的 enumerable 為 true 時,該屬性才能夠出現(xiàn)在對象的枚舉屬性中。默認(rèn)為 false。
    數(shù)據(jù)描述符同時具有以下可選鍵值:

    value

    該屬性對應(yīng)的值。可以是任何有效的 JavaScript 值(數(shù)值,對象,函數(shù)等)。默認(rèn)為 undefined。

    writable

    當(dāng)且僅當(dāng)該屬性的 writable 為 true 時,value 才能被賦值運(yùn)算符改變。默認(rèn)為 false。

    存取描述符同時具有以下可選鍵值:

    get

    一個給屬性提供 getter 的方法,如果沒有 getter 則為 undefined。該方法返回值被用作屬性值。默認(rèn)為 undefined。

    set

    一個給屬性提供 setter 的方法,如果沒有 setter 則為 undefined。該方法將接受唯一參數(shù),并將該參數(shù)的新值分配給該屬性。默認(rèn)為 undefined。

    如果一個描述符不具有value,writable,get 和 set 任意一個關(guān)鍵字,那么它將被認(rèn)為是一個數(shù)據(jù)描述符。如果一個描述符同時有(value或writable)和(get或set)關(guān)鍵字,將會產(chǎn)生一個異常。
    用法

    類的裝飾

    @testable
    class MyTestableClass {
     // ...
    }
    function testable(target) {
     target.isTestable = true;
    }
    MyTestableClass.isTestable // true

    上面代碼中,@testable 就是一個裝飾器。它修改了 MyTestableClass這 個類的行為,為它加上了靜態(tài)屬性isTestable。testable 函數(shù)的參數(shù) target 是 MyTestableClass 類本身。

    基本上,裝飾器的行為就是下面這樣。

    @decorator
    class A {}
    // 等同于
    class A {}
    A = decorator(A) || A;

    也就是說,裝飾器是一個對類進(jìn)行處理的函數(shù)。裝飾器函數(shù)的第一個參數(shù),就是所要裝飾的目標(biāo)類。

    如果覺得一個參數(shù)不夠用,可以在裝飾器外面再封裝一層函數(shù)。

    function testable(isTestable) {
     return function(target) {
     target.isTestable = isTestable;
     }
    }
    @testable(true)
    class MyTestableClass {}
    MyTestableClass.isTestable // true
    @testable(false)
    class MyClass {}
    MyClass.isTestable // false

    上面代碼中,裝飾器 testable 可以接受參數(shù),這就等于可以修改裝飾器的行為。

    注意,裝飾器對類的行為的改變,是代碼編譯時發(fā)生的,而不是在運(yùn)行時。這意味著,裝飾器能在編譯階段運(yùn)行代碼。也就是說,裝飾器本質(zhì)就是編譯時執(zhí)行的函數(shù)。

    前面的例子是為類添加一個靜態(tài)屬性,如果想添加實(shí)例屬性,可以通過目標(biāo)類的 prototype 對象操作。

    下面是另外一個例子。

    // mixins.js
    export function mixins(...list) {
     return function (target) {
     Object.assign(target.prototype, ...list)
     }
    }
    // main.js
    import { mixins } from './mixins'
    const Foo = {
     foo() { console.log('foo') }
    };
    @mixins(Foo)
    class MyClass {}
    let obj = new MyClass();
    obj.foo() // 'foo'

    上面代碼通過裝飾器 mixins,把Foo對象的方法添加到了 MyClass 的實(shí)例上面。

    方法的裝飾

    裝飾器不僅可以裝飾類,還可以裝飾類的屬性。

    class Person {
     @readonly
     name() { return `${this.first} ${this.last}` }
    }

    上面代碼中,裝飾器 readonly 用來裝飾“類”的name方法。

    裝飾器函數(shù) readonly 一共可以接受三個參數(shù)。

    function readonly(target, name, descriptor){
     // descriptor對象原來的值如下
     // {
     // value: specifiedFunction,
     // enumerable: false,
     // configurable: true,
     // writable: true
     // };
     descriptor.writable = false;
     return descriptor;
    }
    readonly(Person.prototype, 'name', descriptor);
    // 類似于
    Object.defineProperty(Person.prototype, 'name', descriptor);
  • 裝飾器第一個參數(shù)是 類的原型對象,上例是 Person.prototype,裝飾器的本意是要“裝飾”類的實(shí)例,但是這個時候?qū)嵗€沒生成,所以只能去裝飾原型(這不同于類的裝飾,那種情況時target參數(shù)指的是類本身);

  • 第二個參數(shù)是 所要裝飾的屬性名

  • 第三個參數(shù)是 該屬性的描述對象

  • 另外,上面代碼說明,裝飾器(readonly)會修改屬性的 描述對象(descriptor),然后被修改的描述對象再用來定義屬性。

    函數(shù)方法的裝飾

    裝飾器只能用于類和類的方法,不能用于函數(shù),因?yàn)榇嬖诤瘮?shù)提升。

    另一方面,如果一定要裝飾函數(shù),可以采用高階函數(shù)的形式直接執(zhí)行。

    function doSomething(name) {
     console.log('Hello, ' + name);
    }
    function loggingDecorator(wrapped) {
     return function() {
     console.log('Starting');
     const result = wrapped.apply(this, arguments);
     console.log('Finished');
     return result;
     }
    }
    const wrapped = loggingDecorator(doSomething);

    core-decorators.js

    core-decorators.js是一個第三方模塊,提供了幾個常見的裝飾器,通過它可以更好地理解裝飾器。

    @autobind

    autobind 裝飾器使得方法中的this對象,綁定原始對象。

    @readonly

    readonly 裝飾器使得屬性或方法不可寫。

    @override

    override 裝飾器檢查子類的方法,是否正確覆蓋了父類的同名方法,如果不正確會報錯。

    import { override } from 'core-decorators';
    class Parent {
     speak(first, second) {}
    }
    class Child extends Parent {
     @override
     speak() {}
     // SyntaxError: Child#speak() does not properly override Parent#speak(first, second)
    }
    // or
    class Child extends Parent {
     @override
     speaks() {}
     // SyntaxError: No descriptor matching Child#speaks() was found on the prototype chain.
     //
     // Did you mean "speak"?
    }

    @deprecate (別名@deprecated)

    deprecate 或 deprecated 裝飾器在控制臺顯示一條警告,表示該方法將廢除。

    import { deprecate } from 'core-decorators';
    class Person {
     @deprecate
     facepalm() {}
     @deprecate('We stopped facepalming')
     facepalmHard() {}
     @deprecate('We stopped facepalming', { url: 'http://knowyourmeme.com/memes/facepalm' })
     facepalmHarder() {}
    }
    let person = new Person();
    person.facepalm();
    // DEPRECATION Person#facepalm: This function will be removed in future versions.
    person.facepalmHard();
    // DEPRECATION Person#facepalmHard: We stopped facepalming
    person.facepalmHarder();
    // DEPRECATION Person#facepalmHarder: We stopped facepalming
    //
    // See http://knowyourmeme.com/memes/facepalm for more details.
    //

    @suppressWarnings

    suppressWarnings 裝飾器抑制 deprecated 裝飾器導(dǎo)致的 console.warn() 調(diào)用。但是,異步代碼發(fā)出的調(diào)用除外。

    使用場景

    裝飾器有注釋的作用

    @testable
    class Person {
     @readonly
     @nonenumerable
     name() { return `${this.first} ${this.last}` }
    }

    有了裝飾器,就可以改寫上面的代碼。裝飾

    @connect(mapStateToProps, mapDispatchToProps)
    export default class MyReactComponent extends React.Component {}

    相對來說,后一種寫法看上去更容易理解。

    新功能提醒或權(quán)限

    菜單點(diǎn)擊時,進(jìn)行事件攔截,若該菜單有新功能更新,則彈窗顯示。

    /**
     * @description 在點(diǎn)擊時,如果有新功能提醒,則彈窗顯示
     * @param code 新功能的code
     * @returns {function(*, *, *)}
     */
     const checkRecommandFunc = (code) => (target, property, descriptor) => {
     let desF = descriptor.value; 
     descriptor.value = function (...args) {
     let recommandFuncModalData = SYSTEM.recommandFuncCodeMap[code];
     if (recommandFuncModalData && recommandFuncModalData.id) {
     setTimeout(() => {
     this.props.dispatch({type: 'global/setRecommandFuncModalData', recommandFuncModalData});
     }, 1000);
     }
     desF.apply(this, args);
     };
     return descriptor;
     };

    loading

    在 React 項(xiàng)目中,我們可能需要在向后臺請求數(shù)據(jù)時,頁面出現(xiàn) loading 動畫。這個時候,你就可以使用裝飾器,優(yōu)雅地實(shí)現(xiàn)功能。

    @autobind
    @loadingWrap(true)
    async handleSelect(params) {
     await this.props.dispatch({
     type: 'product_list/setQuerypParams',
     querypParams: params
     });
    }

    loadingWrap 函數(shù)如下:、

    export function loadingWrap(needHide) {
     const defaultLoading = (
     <p className="toast-loading">
     <Loading className="loading-icon"/>
     <p>加載中...</p>
     </p>
     );
     return function (target, property, descriptor) {
     const raw = descriptor.value;
     
     descriptor.value = function (...args) {
     Toast.info(text || defaultLoading, 0, null, true);
     const res = raw.apply(this, args);
     
     if (needHide) {
     if (get('finally')(res)) {
     res.finally(() => {
     Toast.hide();
     });
     } else {
     Toast.hide();
     }
     }
     };
     return descriptor;
     };
    }

    相信看了本文案例你已經(jīng)掌握了方法,更多精彩請關(guān)注Gxl網(wǎng)其它相關(guān)文章!

    推薦閱讀:

    express + mock如何操作前后臺并行開發(fā)

    字符串+數(shù)組去重實(shí)戰(zhàn)案例解析

    聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    怎樣在項(xiàng)目中使用JS裝飾器函數(shù)

    怎樣在項(xiàng)目中使用JS裝飾器函數(shù):這次給大家?guī)碓鯓釉陧?xiàng)目中使用JS裝飾器函數(shù),怎在項(xiàng)目中使用JS裝飾器函數(shù)的注意事項(xiàng)有哪些,下面就是實(shí)戰(zhàn)案例,一起來看一下。在 ES6 中增加了對類對象的相關(guān)定義和操作(比如 class 和 extends ),這就使得我們在多個不同類之間共享或者擴(kuò)展一些方法或者
    推薦度:
    標(biāo)簽: 如何使用 js 項(xiàng)目
    • 熱門焦點(diǎn)

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 日韩电影免费在线观看视频 | 久久91精品国产一区二区 | 日韩欧美国产高清 | 91精品成人免费国产 | 欧美日本一区二区三区 | 国产日韩欧美综合 | 999久久久免费精品国产牛牛 | 日韩二三区 | 美女一级a毛片免费观看 | 亚洲色图欧美在线 | 日韩阿v| 成人爽a毛片在线视频 | a级毛片免费高清视频 | 国产在线视频网 | 可以看的毛片 | 亚洲精品99久久久久中文字幕 | 在线观看亚洲欧美 | a一级毛片免费播放 | 国产视频二区 | 欧美爱爱网址 | 九九精品免视看国产成人 | 成人久久久精品乱码一区二区三区 | 国产亚洲一区二区三区在线观看 | 韩国精品一区 | 国产欧美在线观看视频 | 色伊人久久| 国内精品伊人久久久久 | 欧美综合自拍亚洲综合 | 久久久久国产成人精品亚洲午夜 | 亚洲国产一区二区三区在线观看 | 国产成人成人一区二区 | 国产一区二区在线观看视频 | 国产精品高清一区二区三区 | 亚洲欧美国产精品专区久久 | 日韩精品欧美高清区 | 另类亚洲色图 | 免费国产小视频在线观看 | 欧洲综合网 | 国产精品久久久久毛片 | 九九热国产 | 欧美日韩国产一区二区三区不卡 |