同時注冊多個 vue 自定義指令 —— require.context

我們時常會用到自定義指令递胧,如果是局部注冊碑韵,簡單,照這官網(wǎng)上來就可以缎脾。如果是會在不同頁面上用到的相同指令祝闻,通常會注冊為全局的。注冊為全局指令赊锚,照著官網(wǎng)來治筒,一樣是可以完成。
但是舷蒲,如果我們有多個需要全局注冊的指令,一個一個來注冊的話友多,寫上一堆Vue.directive() 么牲平,可以是可以,如果不覺得麻煩的話域滥,只是纵柿,我們凡事都講究,優(yōu)雅启绰,以此來規(guī)范(zb)我們的代碼昂儒。

在這之前,假使你已經(jīng)了解指令的具體語法委可,不理解的同學自行查看官網(wǎng) 自定義指令

如何同時注冊很多很多個全局指令呢渊跋?用到的是 require.context方法,webpack 上的一個 api着倾。

作用:

官網(wǎng)的原話是:
It allows you to pass in a directory to search, a flag indicating whether subdirectories should be searched too, and a regular expression to match files against.
簡單的理解是:匹配出某個目錄(及其子目錄)下你所需要的的某種類型的文件

語法:

require.context(directory, useSubdirectories, regExp, mode)

接收三個參數(shù):

  • directory:需要檢索的目錄
  • useSubdirectories:是否檢索子目錄
  • regExp: 需要作用于什么文件(匹配文件的正則表達式)
  • mode: 加載模式拾酝,默認為同步sync,異步值為 lazy

返回:
context.require 返回一個require 函數(shù):

function webpackContext(req) {
  return __webpack_require__(webpackContextResolve(req));
}

該函數(shù)有三個屬性:resolve 卡者、keys蒿囤、id

  • resolve: {Function} ,返回這個匹配文件相對于整個工程的相對路徑
  • keys: {Function} 崇决,返回匹配成功模塊的名字組成的數(shù)組
  • id: {String} 材诽,返回的是一個字符串,執(zhí)行環(huán)境的id

使用:
因為是 webpack 上自帶的api恒傻,在cli 構建的項目中脸侥,我們可以直接使用,不用再另外引入其他的包碌冶。

用例:

注冊全局指令

我的項目結(jié)構如下


image.png

1. 指令的定義
拷貝了官網(wǎng)上的幾個案例湿痢,為了方便管理,一個文件里放一個指令。要把他們注冊成三個指令:v-color-swatch譬重、v-focus拒逮、v-pin。
focus.js:

export default {
  inserted: function (el) {
    el.focus()
  }
}

pin.js:

export default {
  bind: function (el, binding, vnode) {
    el.style.position = 'fixed'
    var s = binding.arg === 'left' ? 'left' : 'top'
    el.style[s] = binding.value + 'px'
  },
  update: function (el, binding, vnode, oldVnode) {}
}

color-swatch.js:

export default function (el, binding) {
  el.style.backgroundColor = binding.value.color
  el.innerHTML = binding.value.text
}

這里說下 color-swatch.js 臀规,這里直接導出一個函數(shù)滩援,沒有寫函數(shù)鉤子,其實這是生命 bindupdate鉤子函數(shù)的簡寫塔嬉,如官網(wǎng)原話:

在很多時候玩徊,你可能想在 bind 和 update 時觸發(fā)相同行為,而不關心其它的鉤子谨究。比如這樣寫:

Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})

2. 指令的注冊
注冊全局指令就是在項目初始化的時候我們就開始注冊恩袱。項目初始化 -> main.js
所以這些指令的注冊我們應該是在main.js寫的,但是為了不讓 main.js 的代碼看起來太多太亂胶哲,我們在 directives 文件夾下 添加一個 index.js 文件畔塔。這個文件處理的就是這幾個指令的注冊。

2.1 第一種方法:
index.js:

import Vue from 'vue'
import colorSwatch from './modules/color-swatch.js'
import focus from './modules/focus.js'
import pin from './modules/pin.js'

Vue.directive('color-swatch', colorSwatch)
Vue.directive('focus', focus)
Vue.directive('pin', pin)

main.js:

import './directives/index'

當然你也可以不用 index.js 文件鸯屿,直接把上面 index.js 的內(nèi)容放到 main.js 也是一樣的澈吨。

2.2 第二種方法:
index.js:

import colorSwatch from './modules/color-swatch.js'
import focus from './modules/focus.js'
import pin from './modules/pin.js'

export {
colorSwatch,
focus,
pin
}

main.js :

// 導入
import * as directives from './directives/index'
// 注冊
Object.keys(directives).forEach(k => Vue.directive(k, directives[k]))

跟第一種差不多,index.js 作為中間文件模塊化指令寄摆,導入默認指令再分模塊導出谅辣。這樣在 main.js 就也可以用 import * 導出所有的模塊。

2.3 第三種方法:
上面兩種方法是我們注冊全局指令一般的寫法婶恼,簡單易懂桑阶。
但是如果我們有很多個指令,每個都要這樣引進來嗎熙尉?

知道了 require.context 語法后联逻,怎么把它用在注冊全局指令這件事上呢?
匹配出 'directives/modules‘ 下的文件检痰,然后在 index.js 做這些文件需要做的操作包归,如下:

import Vue from 'vue'

const files = require.context(
    // 指令目錄
    './modules',
    // 不查找子目錄
    false,
    // js文件
    /.+\.js$/
)

// 對配匹出來的的文件進行操作
files .keys().forEach(fileName => {

    // 獲取指令函數(shù)
    const directiveConfig = files(fileName)

        // 獲取指令名稱
    const directiveName = fileName
        // 移除開始的 './'
        .replace(/^\.\//, '')
        // 移除文件擴展
        .replace(/\.\w+$/, '')

    // 注冊指令, 文件名作為指令名
    Vue.directive(directiveName, directiveConfig.default || directiveConfig)
})

這里打印出 files 的三屬性返回的是什么

console.log('files: ', files)
console.log('-----')
console.log('files.resolve: ', files.resolve(files.keys()[0]))
console.log('files.keys: ', files.keys())
console.log('files.id: ', files.id)
image.png

解析1:
fileName.replace(/^.//, '').replace(/.\w+$/, '') 獲取到指令名稱。
console.log(files.keys()) 得到的是 ["./color-swatch.js", "./focus.js", "./pin.js"]铅歼。因為這里是要用文件名來設置指令名公壤,所以用正則把"./color-swatch.js" 替換成 “color-swatch”
解析2:
files(fileName) 獲取到指令函數(shù);
webpackContext 作為一個函數(shù),也接受一個req參數(shù),這個和resolve方法的req參數(shù)是一樣的,即匹配的文件名的相對路徑,而files函數(shù)返回的是一個模塊,這個模塊才是真正我們需要的椎椰。

3. 指令的使用
上面注冊時都是用文件名來做指令名厦幅,所以用的時候的格式為 v-文件名 ,如下:

<input v-focus>
<p v-pin:[direction]="200">I am pinned onto the page at 200px to the left.</p>
<div v-color-swatch="{ color: '#fcc', text: 'hello!' }"></div>


總結(jié)

其實 require.context 的作用就是幫我匹配出某個路徑下我們指定類型的文件慨飘。
因為它可以方便匹配出指定文件确憨,那是不是可以把需要做同一種操作的文件放在同一個文件夾下译荞,然后用require.context 提取出這些文件去做需要做的操作。
通過上面的案例休弃,除了在注冊全局指令上能用到這個方法吞歼,還有其他地方可以用嗎?例如 全局注冊多個自定義指令
塔猾,例如 router篙骡、store 這種需要一個一個來導出的文件,就可以用 require.context 匹配出來啦丈甸。

最后要說糯俗,這些優(yōu)化的方法都是看場景使用,并沒有絕對的時候睦擂。就上面的例子得湘,如果要全局注冊的指令只有2個,倒不如用第一種方法來的簡單顿仇。所以要看具體情況來選擇忽刽。


參考:
自定義指令
前端工程化之動態(tài)導入文件
requre.content(GUIDES- Dependency Management)
requre.content(API - Module Methods )

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市夺欲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌今膊,老刑警劉巖些阅,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異斑唬,居然都是意外死亡市埋,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門恕刘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缤谎,“玉大人,你說我怎么就攤上這事褐着】涝瑁” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵含蓉,是天一觀的道長频敛。 經(jīng)常有香客問我,道長馅扣,這世上最難降的妖魔是什么斟赚? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮差油,結(jié)果婚禮上拗军,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好发侵,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布交掏。 她就那樣靜靜地躺著,像睡著了一般器紧。 火紅的嫁衣襯著肌膚如雪耀销。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天铲汪,我揣著相機與錄音熊尉,去河邊找鬼。 笑死掌腰,一個胖子當著我的面吹牛狰住,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播齿梁,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼催植,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了勺择?” 一聲冷哼從身側(cè)響起创南,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎省核,沒想到半個月后稿辙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡气忠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年邻储,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旧噪。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡吨娜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出淘钟,到底是詐尸還是另有隱情宦赠,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布日月,位于F島的核電站袱瓮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏爱咬。R本人自食惡果不足惜尺借,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望精拟。 院中可真熱鬧燎斩,春花似錦虱歪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至怪瓶,卻和暖如春萧落,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背洗贰。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工找岖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人敛滋。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓许布,卻偏偏與公主長得像,于是被迫代替她去往敵國和親绎晃。 傳聞我的和親對象是個殘疾皇子蜜唾,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容