成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

mixin配合class實(shí)現(xiàn)多繼承的絕佳妙用

DevTTL / 1066人閱讀

摘要:源碼地址什么是一般翻譯為混入混合,早期一般解釋為把一個(gè)對(duì)象的方法和屬性拷貝到另一個(gè)對(duì)象上也可以簡(jiǎn)單理解為能夠被繼承的類(lèi),最終目的是實(shí)現(xiàn)代碼的復(fù)用。

Github 源碼地址

什么是mixin

mixin一般翻譯為“混入”、“混合”,
早期一般解釋為:把一個(gè)對(duì)象的方法和屬性拷貝到另一個(gè)對(duì)象上;
也可以簡(jiǎn)單理解為能夠被繼承的類(lèi),
最終目的是實(shí)現(xiàn)代碼的復(fù)用。

從一個(gè)需求說(shuō)起

為了使你能夠最快的清楚我在說(shuō)什么,我們從一個(gè)需求說(shuō)起:

一個(gè)項(xiàng)目中有多個(gè)彈層需求;
一些是公共方法,比如點(diǎn)擊關(guān)閉按鈕關(guān)閉彈層;
一些彈層是可以拖動(dòng)的,且有蒙層;
一些彈層是可以縮放的;
其他都是業(yè)務(wù)方法,無(wú)可復(fù)用性。

你可以先在心里想下,如果是你,你會(huì)怎樣完成這個(gè)需求?

腦海中規(guī)劃下

我們?yōu)楣卜椒▽?xiě)個(gè)類(lèi):BaseModal
為可拖動(dòng)的彈層寫(xiě)個(gè)類(lèi):DragModal
為可縮放的彈層寫(xiě)個(gè)類(lèi):ScaleModal
為自定義的業(yè)務(wù)需求寫(xiě)個(gè)類(lèi):CustomModal

畫(huà)個(gè)腦圖的話,會(huì)是下面圖片中的樣子:

extends簡(jiǎn)單實(shí)現(xiàn)下 看代碼
// 公共方法
class BaseModal {
  close(){
    console.log("close");
  }
}

// 可以拖動(dòng)的彈層,我們寫(xiě)一個(gè)多帶帶的類(lèi)
class DragModal extends BaseModal {
  hasLayer = true;
  drag() {
    console.log("drag");
  }
}

// 可以縮放的彈層,我們寫(xiě)一個(gè)多帶帶的類(lèi)
class ScaleModal extends BaseModal {
  scale() {
    console.log("scale");
  }
}

// 業(yè)務(wù)方法
class CustomModal extends DragModal {
  close(){
    console.log("custom-close");
  }
  do() {
    console.log("do");
  }
}

let c = new CustomModal();
c.close(); // custom-close
c.drag(); // drag
c.do(); // do
c.hasLayer; // true
拋出問(wèn)題

如何使CustomModal能夠同時(shí)繼承DragModalScaleModal?

某個(gè)相同方法希望不覆蓋,而是都執(zhí)行

試試早期的mixin方法實(shí)現(xiàn)多繼承 看代碼
// 可以拖動(dòng)的彈層,我們寫(xiě)一個(gè)多帶帶的類(lèi)
class DragModal extends BaseModal {
  hasLayer = true;
  drag() {
    console.log("drag");
  }
}

// 可以縮放的彈層,我們寫(xiě)一個(gè)多帶帶的類(lèi)
class ScaleModal extends BaseModal {
  scale() {
    console.log("scale");
  }
}

// 獲取原型對(duì)象的所有屬性和方法
function getPrototypes(ClassPrototype) {
  return Object.getOwnPropertyNames(ClassPrototype).slice(1);
}

function mix(...mixins){
  return function(target){
    if (!mixins || !Array.isArray(mixins)) return target;
    let cp = target.prototype;
    for (let C of mixins) {
      let mp = C.prototype;
      for (let m of getPrototypes(mp)) {
        cp[m] = mp[m];
      }
    }
  }
}
@mix(DragModal, ScaleModal)
class CustomModal {
  scale(){
    console.log("custom-scale");
  } 
  do() {
    console.log("do");
  }
}
let c = new CustomModal();
c.close(); // 報(bào)錯(cuò),因?yàn)閐obase沒(méi)在A或B的prototype上,而是在A.prototype.__proto__上
c.drag(); // drag
c.scale(); // scale  并非是我們想要的custom-scale
console.log(c.hasLayer); // undefined
存在的問(wèn)題

以上mix方式實(shí)現(xiàn)了多繼承,但存在以下問(wèn)題

會(huì)修改target類(lèi)的原型對(duì)象

target類(lèi)的相同方法名會(huì)被被繼承類(lèi)的相同方法名覆蓋

實(shí)例屬性無(wú)法繼承

BaseModal類(lèi)無(wú)法被繼承

只繼承不修改prototype的實(shí)現(xiàn)方式 看代碼
class BaseModal {
  close() {
    console.log("close");
  }
}

let DragModalMixin = (extendsClass) => class extends extendsClass {
  hasLayer = true;
  drag() {
    console.log("drag");
  }
};

class CustomModal extends DragModalMixin(BaseModal) {
  drag() {
    console.log("custom-drag");
  }
  do() {
    console.log("do");
  }
}

let c = new CustomModal();

c.close(); // close
c.drag(); // custom-drag
console.log(c.hasLayer); // true
存在的問(wèn)題

如何讓CustomModal再繼承ScaleModal呢?
其實(shí)很簡(jiǎn)單,在上面基礎(chǔ)上,我們?cè)賹?xiě)一個(gè)ScaleModalMixinMixin類(lèi)就可以了

完美的多繼承 看代碼
class BaseModal {
  close() {
    console.log("close");
  }
}

let DragModalMixin = (extendsClass) => class extends extendsClass {
  hasLayer = true;
  drag() {
    console.log("drag");
  }
};

let ScaleModalMixin = (extendsClass) => class extends extendsClass {
  scale() {
    console.log("scale");
  }
};

class CustomModal extends ScaleModalMixin(DragModalMixin(BaseModal)) {
  drag() {
    console.log("custom-drag");
  }
  do() {
    console.log("do");
  }
}

let c = new CustomModal();

c.close(); // close
c.drag(); // custom-drag
c.scale(); // scale
console.log(c.hasLayer); // true
存在的問(wèn)題

這種方式不會(huì)修改父類(lèi)的原型對(duì)象,但是如果存在跟父類(lèi)同名的方法,只會(huì)執(zhí)行父類(lèi)的,而不回執(zhí)行被繼承的類(lèi)的方法,那么如何使相同方法分別執(zhí)行呢?

super實(shí)現(xiàn)相同方法不覆蓋 看代碼
class BaseModal {
  close() {
    console.log("close");
  }
}

let DragModalMixin = (extendsClass) => class extends extendsClass {
  hasLayer = true;
  drag() {
    console.log("drag");
  }
};
let ScaleModalMixin = (extendsClass) => class extends extendsClass {
  scale() {
    console.log("scale");
  }
  close() {
    console.log("scale-close");
    if (super.close) super.close();
  }
};

class CustomModal extends ScaleModalMixin(DragModalMixin(BaseModal)) {
  close() {
    console.log("custom-close");
    if (super.close) super.close();
  }
  do() {
    console.log("do");
  }
}

let c = new CustomModal();

c.close(); // custom-close   ->   scale-close   ->   close
總結(jié)

Mixin是一種思想,用來(lái)實(shí)現(xiàn)代碼高度可復(fù)用性,又可以用來(lái)解決多繼承的問(wèn)題,是一種非常靈活的設(shè)計(jì)模式,如果你多多琢磨,相信你也會(huì)發(fā)現(xiàn)一些其他的妙用的,看好你喲!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/95713.html

相關(guān)文章

  • 妙用協(xié)程】 - 單元測(cè)試setUp和tearDown

    摘要:一般的做法是把這些動(dòng)作寫(xiě)在和的兩個(gè)方法里,單元測(cè)試框架會(huì)負(fù)責(zé)在開(kāi)始和結(jié)束的時(shí)候調(diào)用這兩個(gè)方法。從視覺(jué)上無(wú)法直觀的指導(dǎo)原來(lái)和是一對(duì)的。然后再把這個(gè)小的上下文附著到主測(cè)試邏輯上這里利用了單元測(cè)試的的特性,把轉(zhuǎn)化為回調(diào)在的時(shí)候就設(shè)置好。 很多測(cè)試都需要在啟動(dòng)的時(shí)候做一些事情,然后在結(jié)束的時(shí)候再把做的事情給清理了。一般的做法是把這些動(dòng)作寫(xiě)在setUp和tearDown的兩個(gè)方法里,單元測(cè)試框架...

    MartinDai 評(píng)論0 收藏0
  • Javascript裝飾器妙用

    摘要:最近新開(kāi)了一個(gè)項(xiàng)目,采用來(lái)開(kāi)發(fā),在數(shù)據(jù)庫(kù)及路由管理方面用了不少的裝飾器,發(fā)覺(jué)這的確是一個(gè)好東西。在中的使用該裝飾器會(huì)在定義前調(diào)用,如果函數(shù)有返回值,則會(huì)認(rèn)為是一個(gè)新的構(gòu)造函數(shù)來(lái)替代之前的構(gòu)造函數(shù)。函數(shù)參數(shù)裝飾器最后,還有一個(gè)用于函數(shù)參 最近新開(kāi)了一個(gè)Node項(xiàng)目,采用TypeScript來(lái)開(kāi)發(fā),在數(shù)據(jù)庫(kù)及路由管理方面用了不少的裝飾器,發(fā)覺(jué)這的確是一個(gè)好東西。 裝飾器是一個(gè)還處于草案中...

    phodal 評(píng)論0 收藏0
  • Vue with typescript

    摘要:想要使用語(yǔ)法的話,配合,這個(gè)插件,體驗(yàn)更佳,這個(gè)插件在語(yǔ)法中實(shí)現(xiàn)了。這種方式最接近的單文件組件的寫(xiě)法,如果一個(gè)完善項(xiàng)目從改成,用這種方法很快,只要加上和一些必要的變量類(lèi)型就好了,然后用包裹就好。不推薦混入用這種方式寫(xiě),無(wú)法實(shí)現(xiàn)多繼承。 最近嘗試了一下 TypeScript,試著把一個(gè) Vue 項(xiàng)目改成了 TypeScript 的,感覺(jué)還不錯(cuò) 目前 Vue 和 TypeScript 的配...

    JerryWangSAP 評(píng)論0 收藏0
  • CSS border屬性--妙用

    摘要:在下實(shí)現(xiàn)圓角效果由于兼容性特別差,所以要在低版本瀏覽器下實(shí)現(xiàn)圓周角效果特別難利用的效果可實(shí)現(xiàn)如下圖所示的圓效果代碼簡(jiǎn)單如下制作三杠效果其實(shí)就是利用特性變色我們?cè)谧鋈缦聢D標(biāo)時(shí),一般情況下時(shí)會(huì)有三處變色但是利用繼承自這一特性 在ie下實(shí)現(xiàn)圓角效果 (由于border-radius兼容性特別差,所以要在ie低版本瀏覽器下實(shí)現(xiàn)圓周角效果特別難)利用border-style的dotted效果可實(shí)...

    heartFollower 評(píng)論0 收藏0
  • 談?wù)凜SS預(yù)處理器

    摘要:變量插值預(yù)處理器中定義的變量不僅可以用作屬性值,還可以用作選擇器,屬性名等,這就是變量插值。三種預(yù)處理器的嵌套語(yǔ)法是一致的,引用父級(jí)選擇器的標(biāo)記也相同。三種預(yù)處理器的使用方式的差異比較大,下面分別說(shuō)明。 在寫(xiě)CSS的時(shí)候我們會(huì)發(fā)現(xiàn),為了兼容瀏覽器等原因,我們往往需要寫(xiě)很多冗余的代碼,CSS預(yù)處理器就是為了解決CSS的這些問(wèn)題,簡(jiǎn)化CSS代碼的編寫(xiě)。 目前最主流的CSS預(yù)處理器是LESS...

    BlackMass 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<