require.context

舞動乾坤發表於2019-03-03

帶表示式的 require 語句

如果你的 require引數含有表示式(expressions),會建立一個上下文(context),因為在編譯時(compile time)並不清楚具體是哪一個模組被匯入

require("./template/" + name + ".ejs");
複製程式碼

webpack 解析 require() 的呼叫,提取出來如下這些資訊:

Directory: ./template
Regular expression: /^.*\.ejs$/
複製程式碼

則會返回template目錄下的所有字尾為.ejs模組的引用,包含子目錄。

require.context

可以使用 require.context() 方法來建立自己的(模組)上下文,這個方法有 3 個引數:

  • 要搜尋的資料夾目錄
  • 是否還應該搜尋它的子目錄,
  • 以及一個匹配檔案的正規表示式。

  require.context(directory, useSubdirectories = false, regExp = /^\.\//)
 

  require.context("./test", false, /\.test\.js$/);
  //(建立了)一個包含了 test 資料夾(不包含子目錄)下面的、所有檔名以 `.test.js` 結尾的、能被 require 請求到的檔案的上下文。
 

  require.context("../", true, /\.stories\.js$/);
  //(建立了)一個包含了父級資料夾(包含子目錄)下面,所有檔名以 `.stories.js` 結尾的檔案的上下文。
  
複製程式碼

require.context模組匯出(返回)一個(require)函式,這個函式可以接收一個引數:request 函式–這裡的 request 應該是指在 require() 語句中的表示式

匯出的方法有 3 個屬性: resolve, keys, id。

  • resolve 是一個函式,它返回請求被解析後得到的模組 id。
  • keys 也是一個函式,它返回一個陣列,由所有可能被上下文模組處理的請求組成。
  • id 是上下文模組裡面所包含的模組 id. 它可能在你使用 module.hot.accept 的時候被用到

Vue 全域性元件:


module.exports.install = function (Vue) {
 /*
   所有在./components目錄下的.vue元件自動註冊為全域性元件
   以<mv-***></mv-***>為元件標籤名,***是元件的.name,沒有name的時候是元件的檔名
  */

 const requireAll = context => context.keys().map(context);

 const component = require.context('./components', false, /\.vue$/);
 // const directive = require.context('./directives', false, /\.js$/);

 requireAll(component).forEach((item) => {
   const name = (item.name || /(\S+\/)(\S+)\.vue/.exec(item.hotID)[2]).toLowerCase();
   Vue.component(`mv-${name}`, item);
 });

};


複製程式碼

require.context

/**
* The file enables `@/store/index.js` to import all vuex modules
* in a one-shot manner. There should not be any reason to edit this file.
*/

const files = require.context('./modules', false, /\.js$/)
console.log('------------')
console.log(files.keys())
console.log('------------')
const modules = {}

files.keys().forEach(key => { 
   modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
})

console.log('------------')
console.log(modules)
console.log('------------')
export default modules

複製程式碼

require.context

要引入svg下面所有的svg檔案: 在該檔案(icons)目錄下新建一個js檔案index.js 寫如下程式碼:

let requireAll = requireContext => requireContext.keys().map(requireContext)
let req = require.context('./svg', false, /\.svg$/)
requireAll(req) 
複製程式碼

Vue 全域性元件

const requireAll = context => context.keys().map(context);

const component = require.context('./components', false, /\.vue$/);   // false 不遍歷子目錄,true遍歷子目錄


requireAll(component).forEach(({default:item}) => {
	console.log(item)
	Vue.component(`wb-${item.name}`, item);
});
複製程式碼

首字母大寫

Object.keys(components).forEach((key) => {
    var name = key.replace(/(\w)/, (v) => v.toUpperCase()) //首字母大寫
    Vue.component(`v${name}`, components[key])
})
複製程式碼

利用require.context遍歷目錄所有圖片

G:\Code\Vue\vue-global-component\src\assets>tree /f
卷 其它 的資料夾 PATH 列表
卷序列號為 1081-0973
G:.
│  logo.png
└─kittens
        kitten1.jpg
        kitten2.jpg
        kitten3.jpg
        kitten4.jpg
複製程式碼

載入所有的圖片

<template>
	<div id="app">
		<img src="@/assets/logo.png">
		<li v-for="item in images">
			<h3>Image: {{ item }}</h3>
			<img :src="imgUrl(item)">
		</li>
	</div>
</template>

<script>
	var imagesContext = require.context('@/assets/kittens/', false, /\.jpg$/);
	console.log(imagesContext)
	console.log(imagesContext('./kitten1.jpg'))
	console.log(imagesContext.keys())
	export default {
		created: function() {
			this.images = imagesContext.keys();
		},
		name: 'haha',
		data() {
			return {
				images: [],
				msg: 'Welcome to Your Vue.js App'
			}
		},
		methods: {
			imgUrl: function(path) {
				//console.log('Path:' + path);
				return imagesContext(path)
			}
		}
	}
</script>

<style>
	#app {
		font-family: 'Avenir', Helvetica, Arial, sans-serif;
		-webkit-font-smoothing: antialiased;
		-moz-osx-font-smoothing: grayscale;
		text-align: center;
		color: #2c3e50;
		margin-top: 60px;
	}
	
	h1,
	h2 {
		font-weight: normal;
	}
	
	ul {
		list-style-type: none;
		padding: 0;
	}
	
	li {
		display: inline-block;
		margin: 0 10px;
	}
	
	a {
		color: #42b983;
	}
</style>
複製程式碼

import Vue from 'vue'

 

function capitalizeFirstLetter(string) {

  return string.charAt(0).toUpperCase() + string.slice(1)

}

 

const requireComponent = require.context(

  '.', false, /\.vue$/

   //找到components資料夾下以.vue命名的檔案

)

 

requireComponent.keys().forEach(fileName => {

  const componentConfig = requireComponent(fileName)

 

  const componentName = capitalizeFirstLetter(

    fileName.replace(/^\.\//, '').replace(/\.\w+$/, '')

    //因為得到的filename格式是: './baseButton.vue', 所以這裡我們去掉頭和尾,只保留真正的檔名

  )

 

  Vue.component(componentName, componentConfig.default || componentConfig)

})
複製程式碼
import Vue from 'vue'
let contexts = require.context('.', false, /\.vue$/)
contexts.keys().forEach(component => {
  let componentEntity = contexts(component).default
  // 使用內建的元件名稱 進行全域性元件註冊
  Vue.component(componentEntity.name, componentEntity)
})
複製程式碼