亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

vue源碼解析-插件入侵機(jī)制

Mike617 / 2245人閱讀

摘要:代碼如下核心這里會(huì)再次合并一下上的全局的一些指令或則組件或則過濾器到組件的構(gòu)造函數(shù)上最后在內(nèi)部組件初始化時(shí)。會(huì)調(diào)用這里還是把構(gòu)造函數(shù)的放在了上供后續(xù)使用總的來說。將原型指向根構(gòu)造函數(shù)的自然而然就會(huì)有的原型上的所有屬性和方法。。

插件:聰明的程序員往往希望能更高(tou)效(lan)的完成指定的工作,插件就是按照一定的封裝方式,暴露接口。讓我們利用這些接口更快捷的實(shí)現(xiàn)功能。升職加薪。每個(gè)框架都提供了插件的擴(kuò)展機(jī)制。這是框架可擴(kuò)展性必不可少的一個(gè)部分。插件機(jī)制越簡(jiǎn)單。對(duì)于框架的生態(tài)的發(fā)展大有好處。jquery提供了$.fn.extend,angular有對(duì)應(yīng)的依賴注入,module機(jī)制。既然vue那么精美,能迅速火起來。插件這部分的可擴(kuò)展性必須頂級(jí)。這里接下來我們看看vue插件的入侵機(jī)制。
說到插件。我們最多使用的一個(gè)方法。無非就是 Vue.use(MyPlugin, { someOption: true });
這么說的話,這個(gè)方法應(yīng)該是所有插件入侵vue的起點(diǎn)。沒錯(cuò)。那么我們來看看這個(gè)方法:

Vue.use = function (plugin) {
    /* istanbul ignore if */
    if (plugin.installed) {
      return//假如插件已經(jīng)初始化過就不再繼續(xù)。避免插件重復(fù)入侵
    }
    // additional parameters
    var args = toArray(arguments, 1);//獲取插件的配置參數(shù)
    args.unshift(this);
    if (typeof plugin.install === "function") {
      plugin.install.apply(plugin, args);//調(diào)用的是插件的install方法;
    } else if (typeof plugin === "function") {
      plugin.apply(null, args);//若插件本省就是一個(gè)函數(shù)。則直接調(diào)用該函數(shù)
    }
    plugin.installed = true;
    return this
  };

Vue.use這個(gè)方法讓我們知道來。插件入侵的起點(diǎn)是調(diào)用插件自身的install函數(shù)。那么不同的插件入侵的機(jī)制有些時(shí)候很不一樣。我們可以知道。這個(gè)不一樣肯定發(fā)生在install函數(shù)中。我們來看看官方的install函數(shù)中的一些方式:

MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或?qū)傩?  Vue.myGlobalMethod = function () {
    // 邏輯...
  }
  // 2. 添加全局資源
  Vue.directive("my-directive", {
    bind (el, binding, vnode, oldVnode) {
      // 邏輯...
    }
    ...
  })
  // 3. 注入組件
  Vue.mixin({
    created: function () {
      // 邏輯...
    }
    ...
  })
  // 4. 添加實(shí)例方法
  Vue.prototype.$myMethod = function (options) {
    // 邏輯...
  }
}

我們按官網(wǎng)推薦的四種例子。來看看每種方法對(duì)應(yīng)的源碼:

1:Vue.myGlobalMethod = function () {
    // 邏輯...
  }

類似jquery中的jquery.myGlobalMethod或則$.myGlobalMethod簡(jiǎn)單來說就是給Vue這個(gè)全局對(duì)象添加一些工具方法??梢怨┤挚旖菡{(diào)用。我們這里就略過了

2: // 2. 添加全局資源
  Vue.directive("my-directive", {
    bind (el, binding, vnode, oldVnode) {
      // 邏輯...
    }
    ...
  })

Vue.directive,Vue.filter,Vue.component等價(jià)。當(dāng)全局使用這些api時(shí)。會(huì)在vue上把這些指令過濾器組件等放在相應(yīng)的屬性數(shù)組里。形如:

Vue.options = {
    components: {
      
    },
    directives: {},
    filters: {},
    _base: Vue
}

因?yàn)樗麙煸谌值膙ue中。在vue初始化。調(diào)用init方法時(shí)。會(huì)執(zhí)行:

 vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),//策略合并核心函數(shù)??梢宰屑?xì)去看看
        options || {},
        vm
      );

vue在創(chuàng)建實(shí)例時(shí)。會(huì)把vue對(duì)象上的options的對(duì)象中的屬性提取出來和傳入的options做合并。這里涉及到合并策略。以后會(huì)專門講一下。這里只要知道。vue每個(gè)配置相都有自己的合并規(guī)則。mergeOptions會(huì)根據(jù)合并的類目去選擇對(duì)應(yīng)的合并規(guī)則。這里的component.directive.filter根據(jù)合并規(guī)則。Vue對(duì)象上的全局的這些屬性會(huì)被放在實(shí)例的__proto__上。
同樣的。相應(yīng)的子組件。可以回過頭去看一下組件那一章。在render創(chuàng)建子組件的時(shí)候。代碼如下:

function createComponent (
  Ctor,
  data,
  context,
  children,
  tag
) {
  if (isUndef(Ctor)) {
    return
  }

  var baseCtor = context.$options._base;

  // plain options object: turn it into a constructor
  if (isObject(Ctor)) {
    Ctor = baseCtor.extend(Ctor);
  }

  // if at this stage it"s not a constructor or an async component factory,
  // reject.
  if (typeof Ctor !== "function") {
    {
      warn(("Invalid Component definition: " + (String(Ctor))), context);
    }
    return
  }

  // async component
  if (isUndef(Ctor.cid)) {
    Ctor = resolveAsyncComponent(Ctor, baseCtor, context);
    if (Ctor === undefined) {
      // return nothing if this is indeed an async component
      // wait for the callback to trigger parent update.
      return
    }
  }

  // resolve constructor options in case global mixins are applied after
  // component constructor creation
  resolveConstructorOptions(Ctor);//核心:這里會(huì)再次合并一下vue上的全局的一些指令或則組件或則過濾器到組件的構(gòu)造函數(shù)上

  data = data || {};

  // transform component v-model data into props & events
  if (isDef(data.model)) {
    transformModel(Ctor.options, data);
  }

  // extract props
  var propsData = extractPropsFromVNodeData(data, Ctor, tag);

  // functional component
  if (isTrue(Ctor.options.functional)) {
    return createFunctionalComponent(Ctor, propsData, data, context, children)
  }

  // extract listeners, since these needs to be treated as
  // child component listeners instead of DOM listeners
  var listeners = data.on;
  // replace with listeners with .native modifier
  data.on = data.nativeOn;

  if (isTrue(Ctor.options.abstract)) {
    // abstract components do not keep anything
    // other than props & listeners
    data = {};
  }

  // merge component management hooks onto the placeholder node
  mergeHooks(data);

  // return a placeholder vnode
  var name = Ctor.options.name || tag;
  var vnode = new VNode(
    ("vue-component-" + (Ctor.cid) + (name ? ("-" + name) : "")),
    data, undefined, undefined, undefined, context,
    { Ctor: Ctor, propsData: propsData, listeners: listeners, tag: tag, children: children }
  );
  return vnode
}

最后在內(nèi)部組件初始化時(shí)。vue會(huì)調(diào)用

function initInternalComponent (vm, options) {
  var opts = vm.$options = Object.create(vm.constructor.options);//這里還是把構(gòu)造函數(shù)的options放在了$options上供后續(xù)使用
  // doing this because it"s faster than dynamic enumeration.
  opts.parent = options.parent;
  opts.propsData = options.propsData;
  opts._parentVnode = options._parentVnode;
  opts._parentListeners = options._parentListeners;
  opts._renderChildren = options._renderChildren;
  opts._componentTag = options._componentTag;
  opts._parentElm = options._parentElm;
  opts._refElm = options._refElm;
  if (options.render) {
    opts.render = options.render;
    opts.staticRenderFns = options.staticRenderFns;
  }
}

總的來說。如果是全局的指令過濾器時(shí)。vue統(tǒng)一把他放在根構(gòu)造方法上。根實(shí)例初始化時(shí)。通過策略合并合并到$options中。而子組件稍微繞了一下。最終也是放在$options的原型上。很連貫啊。這樣只要是全局的組件。指令過濾器。每個(gè)子組件都可以繼承使用。達(dá)到了插件的效果。

3:下面來看看mixin方法:

Vue.mixin({
    created: function () {
      // 邏輯...
    }
    ...
  })


Vue.mixin = function (mixin) {
    this.options = mergeOptions(this.options, mixin);
  };


//這里還是不可避免要看看mergeOptions函數(shù):
function mergeOptions (
  parent,
  child,
  vm
) {
  {
    checkComponents(child);
  }

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

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

分兩種情況吧:

a:全局注冊(cè)時(shí)即vue.mixin時(shí)。直接調(diào)用合并。直接便利mixin中的項(xiàng)目。分別調(diào)用相應(yīng)合并策略。合并到構(gòu)造函數(shù)的options中。影響后面所有的子組件

b:局部注冊(cè)時(shí)。

if (child.mixins) {
    for (var i = 0, l = child.mixins.length; i < l; i++) {
      parent = mergeOptions(parent, child.mixins[i], vm);
    }
  }

則會(huì)去遞歸的調(diào)用合并策略把該合并的項(xiàng)目合并結(jié)束為止;

vue.mixin就相當(dāng)于是一個(gè)傳入的額外的配置項(xiàng)目,會(huì)讓vue重新按照規(guī)則合并一次,成功入侵vue

4:

// 4. 添加實(shí)例方法
  Vue.prototype.$myMethod = function (options) {
    // 邏輯...
  }

這個(gè)方法就很明顯了。在vue的原型上掛載方法。vue的實(shí)例自然而然就能繼承。子組件在創(chuàng)建的時(shí)候。

Sub.prototype = Object.create(Super.prototype);
    Sub.prototype.constructor = Sub;

將原型指向根構(gòu)造函數(shù)Vue的prototype;自然而然就會(huì)有Vue的原型上的所有屬性和方法。。

以上就是vue比較常用的插件侵入方法。哈哈。下次再說。告辭

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

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

相關(guān)文章

  • 讀?VuePress(四)插件機(jī)制的設(shè)計(jì)

    前言 從 9 月份開始,vuepress 源碼進(jìn)行了重新設(shè)計(jì)和拆分。先是開了個(gè) next 分支,后來又合并到 master 分支,為即將發(fā)布的 1.x 版本做準(zhǔn)備。 最主要的變化是:大部分的全局功能都被拆分成了插件的形式,以可插拔的方式來支撐 vuepress 的運(yùn)作,這一點(diǎn)很像 webpack。 具體架構(gòu)如下: showImg(https://user-gold-cdn.xitu.io/2019...

    April 評(píng)論0 收藏0
  • Vuex源碼解析

    摘要:可能會(huì)有理解存在偏差的地方,歡迎提指出,共同學(xué)習(xí),共同進(jìn)步。先來看一下這張的數(shù)據(jù)流程圖,熟悉使用的同學(xué)應(yīng)該已經(jīng)有所了解。它允許用戶在某些情況下避免自動(dòng)安裝。 寫在前面 因?yàn)閷?duì)Vue.js很感興趣,而且平時(shí)工作的技術(shù)棧也是Vue.js,這幾個(gè)月花了些時(shí)間研究學(xué)習(xí)了一下Vue.js源碼,并做了總結(jié)與輸出。 文章的原地址:https://github.com/answershuto/lear...

    chinafgj 評(píng)論0 收藏0
  • 前端窩 - 收藏集 - 掘金

    摘要:毫無疑問,設(shè)計(jì)模式于己于他人于系統(tǒng)都是多贏的設(shè)計(jì)模式使代碼編寫真正工程化設(shè)計(jì)模小書前端掘金這是一本關(guān)于的小書。 JavaScript 常見設(shè)計(jì)模式解析 - 掘金設(shè)計(jì)模式(Design pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。毫無疑問,設(shè)計(jì)模式于己于他人于系統(tǒng)都是多贏的;設(shè)計(jì)...

    李文鵬 評(píng)論0 收藏0
  • 深入解析Vue源碼

    摘要:你可以使用的方法傳入指令和定義對(duì)象來注冊(cè)一個(gè)全局自定義指令。深度數(shù)據(jù)觀察如果你希望在一個(gè)對(duì)象上使用自定義指令,并且當(dāng)對(duì)象內(nèi)部嵌套的屬性發(fā)生變化時(shí)也能夠觸發(fā)指令的函數(shù),那么你就要在指令的定義中傳入。 Vue簡(jiǎn)介 數(shù)據(jù)綁定 /** *假設(shè)有這么兩個(gè)鐘東西 **/ //數(shù)據(jù) var object = { message: Hello World! } //DOM {{ messag...

    weapon 評(píng)論0 收藏0
  • [全網(wǎng)最全的 Vue CLI 3 原創(chuàng)合集] 你要的這里都有

    摘要:慢慢地,關(guān)于的原創(chuàng)學(xué)習(xí)文章已經(jīng)寫了多篇了會(huì)一直放出來,目前篇,因此做一個(gè)合集,獻(xiàn)給那些對(duì)新版本腳手架使用和背后設(shè)計(jì)感興趣的同學(xué),都是一步一步去看源碼,也給官方提了幾次,合進(jìn)去了幾個(gè)原創(chuàng)不易,歡迎大家互相轉(zhuǎn)發(fā),期望大家一起快速過度到版本目錄 慢慢地,關(guān)于 Vue CLI 3 的原創(chuàng)學(xué)習(xí)文章已經(jīng)寫了 20 多篇了(會(huì)一直放出來,目前 23 篇), 因此做一個(gè)合集,獻(xiàn)給那些對(duì)新版本腳手架使用...

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

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

0條評(píng)論

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