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

資訊專欄INFORMATION COLUMN

徹底搞懂elementUI指令與服務(wù)模式原理

freewolf / 1316人閱讀

摘要:不甘做輪子的搬運(yùn)工記錄一個(gè)實(shí)習(xí)菜鳥寫圖片預(yù)覽組件的艱辛道路很多組件中使用了指令模式和服務(wù)模式,比如以下以組件為例指令模式全屏覆蓋服務(wù)模式跟大多數(shù)萌新一樣,啥是服務(wù)先看看的目錄結(jié)構(gòu)打開目錄,找到其下目錄文件中有一大坨組件注冊(cè)信息重點(diǎn)找

不甘做輪子的搬運(yùn)工?。。?/b>

記錄一個(gè)實(shí)習(xí)菜鳥寫圖片預(yù)覽組件的艱辛道路~

elementUI很多組件中使用了指令模式和服務(wù)模式,比如:loadingmessage...
以下以loading組件為例: 指令模式:
服務(wù)模式:
const loading = this.$loading({
  lock: true,
  text: "Loading",
  spinner: "el-icon-loading",
  background: "rgba(0, 0, 0, 0.7)"
});
跟大多數(shù)萌新一樣,啥是服務(wù)?!

先看看elmentUI的目錄結(jié)構(gòu):

打開node_modules目錄,找到其下elementUI目錄:

element-uisrcindex.js文件中有一大坨組件注冊(cè)信息,重點(diǎn)找到我們要找的loading...

// ...
// directive 指令裝載
Vue.use(Loading.directive)
// prototype 服務(wù)裝載
Vue.prototype.$loading = Loading.service
// ...

Vue.use() 這個(gè)指令是 Vue 用來(lái)安裝插件的,如果傳入的參數(shù)是一個(gè)對(duì)象,則該對(duì)象要提供一個(gè) install 方法,如果是一個(gè)函數(shù),則該函數(shù)被視為 install 方法,在 install 方法調(diào)用時(shí),會(huì)將 Vue 作為參數(shù)傳入。

開始叭!

先看看loading/index.js文件中是什么鬼?

//引入指令文件和服務(wù)文件,directive為指令模式文件,index.js為服務(wù)模式文件
import directive from "./src/directive";
import service from "./src/index";

export default {
  //install方法注冊(cè)組件,不在贅述install的用法,star-pic-list圖片預(yù)覽組件文章中已經(jīng)介紹過
  install(Vue) {
    Vue.use(directive);
    //在vue的原型對(duì)象上注冊(cè)一個(gè)$loading的對(duì)象,這個(gè)$loading非常眼熟,看上面服務(wù)模式的使用,用到了this.$loading,源頭找到了
    Vue.prototype.$loading = service;
  },
  //引入的directive文件
  directive,
  //引入的index.js文件
  service
};
v-loading 指令解析

篇幅太長(zhǎng),其中我們只取 fullscreen 修飾詞。

// 引入 .vue 文件
import Vue from "vue"
// 引入loading.vue基礎(chǔ)文件,里面包含的是組件的基礎(chǔ)結(jié)構(gòu),如html結(jié)構(gòu),loading顯示的頁(yè)面結(jié)構(gòu)都在這里面
import Loading from "./loading.vue"
// 后面重點(diǎn)講解extend()構(gòu)造器
// Vue.extend() 是vue構(gòu)造器,它返回的是一個(gè)擴(kuò)展實(shí)例構(gòu)造器,也就是預(yù)設(shè)了部分選項(xiàng)的Vue實(shí)例構(gòu)造器,

// mask字面意思是面具,掩飾,可以猜出來(lái),這個(gè)通過Vue.extend(Loading)返回構(gòu)造器應(yīng)該是用于我們loading加載時(shí)的遮罩層用的
// loading就是預(yù)設(shè)選項(xiàng),就像vue示例中,有components,name,data,methods...好像有點(diǎn)明白了
const Mask = Vue.extend(Loading)

const loadingDirective = {}
// 還記得 Vue.use() 的使用方法么?若傳入的是對(duì)象,該對(duì)象需要一個(gè) install 屬性
loadingDirective.install = Vue => {
  // toggleLoading 方法看名字就是切換loading顯示和隱藏的嘛~
  const toggleLoading = (el, binding) => {
    // 若綁定值為 truthy 則插入 loading 元素
    // binding 值是一個(gè)對(duì)象,有指令名、指令的綁定值、modifiers修飾符對(duì)象等等等等,具體的可以去了解自定義指令相關(guān)內(nèi)容
    if (binding.value) {  //binding.value是綁定的指令值
      if (binding.modifiers.fullscreen) {  還記得我們插入的指令嗎?:v-loading.fullscreen="true" ,  .fullscreen就是修飾符
        insertDom(document.body, el, binding)    //insertDom看名字就知道是插入新的元素
      }
     // visible 是loading.vue   data里面定義的值
    } else {
      el.instance.visible = false
    }
  }

  const insertDom = (parent, el, binding) => {
    // loading 設(shè)為可見
    el.instance.visible = true
    // appendChild 添加的元素若為同一個(gè),則不會(huì)重復(fù)添加
    parent.appendChild(el.mask)
  }
  // 在此注冊(cè) directive 指令
  Vue.directive("loading", {
    bind: function(el, binding, vnode) {
      // 創(chuàng)建一個(gè)子組件,這里和 new Vue(options) 類似
      // 返回一個(gè)組件實(shí)例
      const mask = new Mask({
        el: document.createElement("div"),
        // 有些人看到這里會(huì)迷惑,為什么這個(gè) data 不按照 Vue 官方建議傳函數(shù)進(jìn)去呢?
        // 其實(shí)這里兩者皆可
        // 稍微做一點(diǎn)延展好了,在 Vue 源碼里面,data 是延遲求值的
        // 貼一點(diǎn) Vue 源碼上來(lái)
        // return function mergedInstanceDataFn() {
        //   let instanceData = typeof childVal === "function"
        //     ? childVal.call(vm, vm)
        //     : childVal;
        //   let defaultData = typeof parentVal === "function"
        //     ? parentVal.call(vm, vm)
        //     : parentVal;
        //   if (instanceData) {
        //     return mergeData(instanceData, defaultData)
        //   } else {
        //     return defaultData
        //   }
        // }
        // instanceData 就是我們現(xiàn)在傳入的 data: {}
        // defaultData 就是我們 loading.vue 里面的 data() {}
        // 看了這段代碼應(yīng)該就不難理解為什么可以傳對(duì)象進(jìn)去了
        data: {
          fullscreen: !!binding.modifiers.fullscreen
        }
      })
      // 將創(chuàng)建的子類掛載到 el 上
      // 在 directive 的文檔中建議
      // 應(yīng)該保證除了 el 之外其他參數(shù)(binding、vnode)都是只讀的
      el.instance = mask
      // 掛載 dom
      // bind 只會(huì)調(diào)用一次,在bind 的時(shí)候給 el.mask 賦值,因此el.mask 所指的為同一個(gè) dom 元素
      el.mask = mask.$el
      // 若 binding 的值為 truthy 運(yùn)行 toogleLoading
      binding.value && toggleLoading(el, binding)
    },
    update: function(el, binding) {
      // 若舊不等于新值得時(shí)候(一般都是由 true 切換為 false 的時(shí)候)
      if (binding.oldValue !== binding.value) {
        // 切換顯示或消失
        toggleLoading(el, binding)
      }
    },
    unbind: function(el, binding) {
      // 當(dāng)組件 unbind 的時(shí)候,執(zhí)行組件銷毀
      el.instance && el.instance.$destroy()
    }
  })
}
export default loadingDirective
關(guān)于extend()更多內(nèi)容請(qǐng)參考這里,非常通熟易懂!
loading服務(wù)方式調(diào)用原理

直接看源碼:

import Vue from "vue"
import loadingVue from "./loading.vue"
// 和指令模式一樣,創(chuàng)建實(shí)例構(gòu)造器
const LoadingConstructor = Vue.extend(loadingVue)
// 定義變量,若使用的是全屏 loading 那就要保證全局的 loading 只有一個(gè)
let fullscreenLoading
// 這里可以看到和指令模式不同的地方
// 在調(diào)用了 close 之后就會(huì)移除該元素并銷毀組件
LoadingConstructor.prototype.close = function() {
  setTimeout(() => {
    if (this.$el && this.$el.parentNode) {
      this.$el.parentNode.removeChild(this.$el)
    }
    this.$destroy()
  }, 3000)
}

const Loading = (options = {}) => {
  // 若調(diào)用 loading 的時(shí)候傳入了 fullscreen 并且 fullscreenLoading 不為 falsy
  // fullscreenLoading 只會(huì)在下面賦值,并且指向了 loading 實(shí)例
  if (options.fullscreen && fullscreenLoading) {
    return fullscreenLoading
  }
  // 這里就不用說(shuō)了吧,和指令中是一樣的
  let instance = new LoadingConstructor({
    el: document.createElement("div"),
    data: options
  })
  let parent = document.body
  // 直接添加元素
  parent.appendChild(instance.$el)
  // 將其設(shè)置為可見
  // 另外,寫到這里的時(shí)候我查閱了相關(guān)的資料
  // 自己以前一直理解 nextTick 是在 dom 元素更新完畢之后再執(zhí)行回調(diào)
  // 但是發(fā)現(xiàn)可能并不是這么回事,后續(xù)我會(huì)繼續(xù)研究
  // 如果干貨足夠的話我會(huì)寫一篇關(guān)于 nextTick ui-render microtask macrotask 的文章
  Vue.nextTick(() => {
    instance.visible = true
  })
  // 若傳入了 fullscreen 參數(shù),則將實(shí)例存儲(chǔ)
  if (options.fullscreen) {
    fullscreenLoading = instance
  }
  // 返回實(shí)例,方便之后能夠調(diào)用原型上的 close() 方法
  return instance
}
export default Loading
現(xiàn)學(xué)現(xiàn)用-寫一個(gè)點(diǎn)擊圖片預(yù)覽的組件試試看 目錄結(jié)構(gòu):

directive.js是指令模式文件,index.js是服務(wù)模式文件,star-pic-preview.vue是基礎(chǔ)單文件,包含了基礎(chǔ)的html結(jié)構(gòu)

先看指令模式:

使用:

我直接使用了指令,并沒有傳參,因?yàn)楣δ芎?jiǎn)單,默認(rèn)參數(shù)就是false

 

效果:

點(diǎn)擊出現(xiàn)遮罩層,圖片居中顯示預(yù)覽

服務(wù)模式:

使用:

 methods: {
    // 服務(wù)方式
    openImagePreview2(e) {
        // 如果只傳圖片
        this.$picPreview(e.target.src);
        //如果傳復(fù)雜對(duì)象,可以配置遮罩層的背景顏色等...
        // this.$picPreview({
        //     background: "rgba(0, 0, 0, 0.7)",
        //     imageUrl: e.target.src,
        // });
    },
}

效果如上

源碼請(qǐng)參考github地址: 源碼地址

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

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

相關(guān)文章

  • 線程安全(上)--徹底搞懂volatile關(guān)鍵字

    摘要:此時(shí),就出現(xiàn)了線程不安全問題了。因?yàn)榈某跏贾禃?huì)是因此,重排序是有可能導(dǎo)致線程安全問題的。真的能完全保證一個(gè)變量的線程安全嗎我們通過上面的講解,發(fā)現(xiàn)關(guān)鍵字還是挺有用的,不但能夠保證變量的可見性,還能保證代碼的有序性。 對(duì)于volatile這個(gè)關(guān)鍵字,相信很多朋友都聽說(shuō)過,甚至使用過,這個(gè)關(guān)鍵字雖然字面上理解起來(lái)比較簡(jiǎn)單,但是要用好起來(lái)卻不是一件容易的事。 這篇文章將從多個(gè)方面來(lái)講解vol...

    teren 評(píng)論0 收藏0
  • 徹底搞懂JavaScript執(zhí)行機(jī)制

    摘要:徹底搞懂執(zhí)行機(jī)制首先我們大家都了解的是,是一門單線程語(yǔ)言,所以我們就可以得出是按照語(yǔ)句順序執(zhí)行的首先看這個(gè)顯然大家都知道結(jié)果,依次輸出,然而換一種這個(gè)時(shí)候再看代碼的順序執(zhí)行,輸出,,,。不過即使主線程為空,也是達(dá)不到的,根據(jù)標(biāo)準(zhǔn),最低是。 徹底搞懂JavaScript執(zhí)行機(jī)制 首先我們大家都了解的是,JavaScript 是一門單線程語(yǔ)言,所以我們就可以得出: JavaScript 是...

    hizengzeng 評(píng)論0 收藏0
  • 一篇文章帶你徹底搞懂NIO

    摘要:阻塞當(dāng)進(jìn)行讀寫時(shí),線程是阻塞的狀態(tài)。當(dāng)任何一個(gè)收到數(shù)據(jù)后,中斷程序?qū)酒疬M(jìn)程。接收數(shù)據(jù)當(dāng)收到數(shù)據(jù)后,中斷程序會(huì)給的就緒列表添加引用。當(dāng)接收到數(shù)據(jù),中斷程序一方面修改,另一方面喚醒等待隊(duì)列中的進(jìn)程,進(jìn)程再次進(jìn)入運(yùn)行狀態(tài)如下圖。 本篇文章目的在于基本概念和原理的解釋,不會(huì)貼過多的使用代碼。 什么是NIO Java NIO (New IO)是 Java 的另一個(gè) IO API (來(lái)自 jav...

    ziwenxie 評(píng)論0 收藏0
  • 來(lái)一輪帶注釋的demo,徹底搞懂javascript中的replace函數(shù)

    摘要:對(duì)應(yīng)于上述的,等。匹配到的子字符串在原字符串中的偏移量。插入當(dāng)前匹配的子串右邊的內(nèi)容。 javascript這門語(yǔ)言一直就像一位帶著面紗的美女,總是看不清,摸不透,一直專注服務(wù)器端,也從來(lái)沒有特別重視過,直到最近幾年,javascript越來(lái)越重要,越來(lái)越通用。最近和前端走的比較近,借此機(jī)會(huì),好好鞏固一下相關(guān)知識(shí)點(diǎn)。 1.初識(shí)replace 在js中有兩個(gè)replace函數(shù) 一個(gè)是lo...

    Coding01 評(píng)論0 收藏0
  • 徹底搞懂JavaScript中的繼承

    摘要:這正是我們想要的太棒了毫不意外的,這種繼承的方式被稱為構(gòu)造函數(shù)繼承,在中是一種關(guān)鍵的實(shí)現(xiàn)的繼承方法,相信你已經(jīng)很好的掌握了。 你應(yīng)該知道,JavaScript是一門基于原型鏈的語(yǔ)言,而我們今天的主題 -- 繼承就和原型鏈這一概念息息相關(guān)。甚至可以說(shuō),所謂的原型鏈就是一條繼承鏈。有些困惑了嗎?接著看下去吧。 一、構(gòu)造函數(shù),原型屬性與實(shí)例對(duì)象 要搞清楚如何在JavaScript中實(shí)現(xiàn)繼承,...

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

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

0條評(píng)論

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