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

資訊專欄INFORMATION COLUMN

JS設(shè)計(jì)模式之Mixin(混入)模式

caiyongji / 3327人閱讀

摘要:概念模式就是一些提供能夠被一個(gè)或者一組子類簡(jiǎn)單繼承功能的類意在重用其功能。示例下面通過一個(gè)簡(jiǎn)單的例子來演示這個(gè)模式混入模式的實(shí)現(xiàn)不指定特定方法名的時(shí)候,將后者所有的方法都添加到前者里優(yōu)缺點(diǎn)優(yōu)點(diǎn)有助于減少系統(tǒng)中的重復(fù)功能及增加函數(shù)復(fù)用。

概念

Mixin模式就是一些提供能夠被一個(gè)或者一組子類簡(jiǎn)單繼承功能的類,意在重用其功能。在面向?qū)ο蟮恼Z言中,我們會(huì)通過接口繼承的方式來實(shí)現(xiàn)功能的復(fù)用。但是在javascript中,我們沒辦法通過接口繼承的方式,但是我們可以通過javascript特有的原型鏈屬性,將功能引用復(fù)制到原型鏈上,達(dá)到功能的注入。

示例

下面通過一個(gè)簡(jiǎn)單的例子來演示這個(gè)模式

var Car = function(settings) {
  this.model = settings.model || "no model provided"
  this.color = settings.color || "no color provided"
}

var Mixin = function() {}

Mixin.prototype = {
  driveForward: function() {
    console.log("drive forward")
  },
  driveBackward: function() {
    console.log("drive backward")
  },
  driveSideways: function() {
    console.log("drive sideways")
  }
}

//混入模式的實(shí)現(xiàn)
function Merge(recClass, giveClass) {
  if(arguments.length > 2) {
    for(var i = 2, lenth = arguments.length; i < lenth ; ++ i) {
      var methodName = arguments[i]
      recClass.prototype[methodName] = giveClass.prototype[methodName]
    }
  }else {
    for(var methodName in giveClass.prototype) {
      if(!recClass.prototype[methodName]) {
        recClass.prototype[methodName] = giveClass.prototype[methodName]
      }
    }
  }
}

Merge(Car, Mixin, "driveForward", "driveBackward")

var myCar = new Car({
  model: "BMW",
  color: "blue"
})

myCar.driveForward()    //drive forward
myCar.driveBackward()   //drive backward

//不指定特定方法名的時(shí)候,將后者所有的方法都添加到前者里
Merge(Car, Mixin)

var mySportsCar = new Car({
  model: "Porsche",
  color: "red"
})

mySportsCar.driveForward()  //drive forward
優(yōu)缺點(diǎn)

優(yōu)點(diǎn)
有助于減少系統(tǒng)中的重復(fù)功能及增加函數(shù)復(fù)用。當(dāng)一個(gè)應(yīng)用程序可能需要在各種對(duì)象實(shí)例中共享行為時(shí),我們可以通過在Mixin中維持這種共享功能并專注于僅實(shí)現(xiàn)系統(tǒng)中真正不同的功能,來輕松避免任何重復(fù)。

缺點(diǎn)
有些人認(rèn)為將功能注入對(duì)象原型中會(huì)導(dǎo)致原型污染和函數(shù)起源方面的不確定性。

Vue混入功能研究

vue中關(guān)于混入的代碼目錄/src/core/global-api/mixin.js
可以看到vue源碼中是通過mergeOptions來合并配置到options上

export function initMixin (Vue: GlobalAPI) {
  Vue.mixin = function (mixin: Object) {
    this.options = mergeOptions(this.options, mixin)
    return this
  }
}

下面我們來看合并配置的相關(guān)代碼/src/core/instance/init.js
當(dāng)執(zhí)行new Vue的時(shí)候options._isComponent為false,會(huì)走else的分支

export function initMixin (Vue: Class) {
  Vue.prototype._init = function (options?: Object) {
    const vm: Component = this
    // a uid
    vm._uid = uid++

    let startTag, endTag
    /* istanbul ignore if */
    if (process.env.NODE_ENV !== "production" && config.performance && mark) {
      startTag = `vue-perf-start:${vm._uid}`
      endTag = `vue-perf-end:${vm._uid}`
      mark(startTag)
    }

    // a flag to avoid this being observed
    vm._isVue = true
    // merge options
    if (options && options._isComponent) {
      // optimize internal component instantiation
      // since dynamic options merging is pretty slow, and none of the
      // internal component options needs special treatment.
      initInternalComponent(vm, options)
    } else {
      vm.$options = mergeOptions(  //合并配置
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      )
    }
    /* istanbul ignore else */
    if (process.env.NODE_ENV !== "production") {
      initProxy(vm)
    } else {
      vm._renderProxy = vm
    }
    // expose real self
    vm._self = vm
    initLifecycle(vm)
    initEvents(vm)
    initRender(vm)
    callHook(vm, "beforeCreate")
    initInjections(vm) // resolve injections before data/props
    initState(vm)
    initProvide(vm) // resolve provide after data/props
    callHook(vm, "created")

    /* istanbul ignore if */
    if (process.env.NODE_ENV !== "production" && config.performance && mark) {
      vm._name = formatComponentName(vm, false)
      mark(endTag)
      measure(`vue ${vm._name} init`, startTag, endTag)
    }

    if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }
  }
}

下面來看mergeOptions的實(shí)現(xiàn)src/core/util/options.js
mergeField將this.options(parent)和需要混入的對(duì)象mixin(child)合并在this.options上面

/**
 * Merge two option objects into a new one.
 * Core utility used in both instantiation and inheritance.
 */
export function mergeOptions (
  parent: Object,
  child: Object,
  vm?: Component
): Object {
  if (process.env.NODE_ENV !== "production") {
    checkComponents(child)
  }

  if (typeof child === "function") {
    child = child.options
  }

  normalizeProps(child, vm)
  normalizeInject(child, vm)
  normalizeDirectives(child)
  const extendsFrom = child.extends
  if (extendsFrom) {
    parent = mergeOptions(parent, extendsFrom, vm)
  }
  if (child.mixins) {
    for (let i = 0, l = child.mixins.length; i < l; i++) {
      parent = mergeOptions(parent, child.mixins[i], vm)
    }
  }
  const options = {}
  let key
  for (key in parent) {
    mergeField(key)
  }
  for (key in child) {
    if (!hasOwn(parent, key)) {
      mergeField(key)
    }
  }
  function mergeField (key) {
    const strat = strats[key] || defaultStrat
    options[key] = strat(parent[key], child[key], vm, key)
  }
  return options
}
參考

《JavaScript設(shè)計(jì)模式》

JS設(shè)計(jì)模式系列文章

JS設(shè)計(jì)模式之Obeserver(觀察者)模式、Publish/Subscribe(發(fā)布/訂閱)模式
JS設(shè)計(jì)模式之Factory(工廠)模式
JS設(shè)計(jì)模式之Singleton(單例)模式
JS設(shè)計(jì)模式之Facade(外觀)模式
JS設(shè)計(jì)模式之Module(模塊)模式、Revealing Module(揭示模塊)模式
JS設(shè)計(jì)模式之Mixin(混入)模式

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

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

相關(guān)文章

  • mixin混入邏輯

    摘要:現(xiàn)在有一個(gè)需求,將沒有而有的屬性混入到中。有而且也有的屬性不混入以為準(zhǔn)。通過這種混入機(jī)制滾雪球的方式可以不斷地?cái)U(kuò)充一個(gè)對(duì)象地的功能。暫且將它定義為混入模式?;烊肽J绞菢?gòu)建復(fù)雜對(duì)象的一種常用的模式。 有A對(duì)象和B對(duì)象,A, B對(duì)象有有方法屬性和數(shù)據(jù)屬性?,F(xiàn)在有一個(gè)需求,將A沒有而B有的屬性混入到A中。A有而且B也有的屬性不混入以A為準(zhǔn)。通過這種混入機(jī)制(滾雪球的方式)可以不斷地?cái)U(kuò)充一個(gè)對(duì)...

    hufeng 評(píng)論0 收藏0
  • 高級(jí) Vue 組件模式 (4)

    摘要:使用替換目標(biāo)在第三篇文章中,我們使用來抽離了注入依賴項(xiàng)的公共邏輯。成果通過作用域插槽,我們有效地避免了第三方組件由于混入而可能造成的命名沖突以及隱式依賴等問題。 04 使用 slot 替換 mixin 目標(biāo) 在第三篇文章中,我們使用 mixin 來抽離了注入 toggle 依賴項(xiàng)的公共邏輯。在 react 中,類似的需求是通過 HOC 的方式來解決的,但是仔細(xì)想想的話,react 在早...

    LancerComet 評(píng)論0 收藏0
  • 高級(jí) Vue 組件模式 (3)

    摘要:在中,我們是否也有一些手段或特性來提高組件的復(fù)用程度和靈活性呢答案當(dāng)然是有的,那就是。成果通過實(shí)現(xiàn),我們成功將注入的邏輯抽離了出來,這樣每次需要共享組件的狀態(tài)和方法時(shí),混入該即可。 03 使用 mixin 來增強(qiáng) Vue 組件 目標(biāo) 之前一篇文章中,我們雖然將 toggle 組件劃分為了 toggle-button、toggle-on 和 toggle-off 三個(gè)子組件,且一切運(yùn)行良...

    iKcamp 評(píng)論0 收藏0
  • 從裝飾模式到裝飾器

    摘要:從裝飾模式到裝飾器裝飾模式裝飾模式的作用是在不修改原有的接口的情況下,讓類表現(xiàn)的更好。它是一個(gè)語法糖說完了裝飾模式,我們?cè)倏匆幌略谥凶钚乱氲难b飾器。 從裝飾模式到裝飾器 裝飾模式 裝飾模式的作用是:在不修改原有的接口的情況下,讓類表現(xiàn)的更好。 什么叫更好? 為什么需要裝飾模式 自然是繼承有一些問題繼承會(huì)導(dǎo)致超類和子類之間存在強(qiáng)耦合性,當(dāng)超類改變時(shí),子類也會(huì)隨之改變; 超類的內(nèi)...

    monw3c 評(píng)論0 收藏0
  • 如何正確的(?)利用 Vue.mixin() 偷懶

    摘要:前言最近開發(fā)的頁(yè)面以及功能大都以表格為主,接口獲取來的數(shù)據(jù)大都是需要經(jīng)過處理,比如時(shí)間戳需要轉(zhuǎn)換,或者狀態(tài)碼的轉(zhuǎn)義。首先,還是在文件中定義一個(gè)狀態(tài)碼對(duì)應(yīng)對(duì)象,這里我們將其對(duì)應(yīng)的內(nèi)容設(shè)為段落。 前言 最近開發(fā)的頁(yè)面以及功能大都以表格為主,接口獲取來的 JSON 數(shù)據(jù)大都是需要經(jīng)過處理,比如時(shí)間戳需要轉(zhuǎn)換,或者狀態(tài)碼的轉(zhuǎn)義。對(duì)于這樣的問題,各大主流框架都提供了類似于過濾的方法,在 Vue ...

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

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

0條評(píng)論

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