vue項目路由、組件優化及使用nodeJs自動創建文件


vue項目路由、組件優化及使用nodeJs自動創建文件

我們在使用Vue進行開發的過程中,每次都需要先創建路由,再在主文件中引入模塊路由。如下:

// 目錄結構
- router
--- index.js
--- modules

// 現在我們創建一條新路由

--- modules
----- layout.js

// layout.js
module.export [
  {
    name: '...'
    path: '...',
    component: () => import('@/views/modules/layout')
  }
]

// 然后在index.js文件中引入 layout 模塊的內容
import Layout from './modules/layout.js'

const mainRouter = {
  path: '/',
  componemt: () => import('@/views')
  children: [
    ...Layout
  ]
}

這樣每次創建后進行引入的方式,一方面重復性工作顯得單調,另一方面,index.js中引入過多模塊會導致代碼看起來重復性太多,不夠優雅。為此,我們可以嘗試這樣的思路:主路由文件只引入一個模塊組件,然后這個組件幫助我們自動搜索引入它的上下文路由文件,這時候,我們就需要用到webpack提供的 require.context函數。

/*
*  require.context 函數介紹
*  該函數允許你搜索上下文,從而獲取上下文中的內容
*  接受三個參數
*  directory: 文件路徑
*  useSubdirectories: 是否搜索其子文件
*  regExp: 匹配文件的格式正則 
*/
require.context(directory, useSubdirectories = false, regExp)

// 例如我們現在要獲取 modules 文件夾中的路由文件,可以這樣寫
requrie.context('./', true, /\.js$/)

接下來進行實踐。在modules文件夾中封裝一個 index.js 文件,用來自動遍歷上下文中的路由,這樣之后,我們下次新創建的路由就可以不必去收到添加到主路由文件中了,交給這個封裝函數即可。

// modules/index.js
const files = require.context('./', true, /\/js$/)

let routerList = [] // 存放收集到的路由

// keys函數執行后能獲取到文件名稱
files.keys().forEach(item => {
  // 排除當前文件
  if (item === './index.js') return 

  // item(key).default 獲取文件內容
  routerList = routerList.concat(item(key).default)
})

export default routerList

那么同理,我們也可以自動遍歷組件文件進行注冊

  // modules/index.js
const files = require.context('./', true, /\/js$/)

// keys函數執行后能獲取到文件名稱
files.keys().forEach(item => {
  // 排除當前文件
  if (item === './index.js') return 
  const componentEntity = item(key).default

  // 組件注冊
  Vue.component(componentEntity.name, componentEntity )
  
})

使用nodeJs自動創建文件

上文中使用 require.context 實現了對上下文內容的路由自動收集和全局組件的注冊功能,但還是每次都得自己去一個個創建文件。而且,路由創建完畢之后,還得去創建視圖文件,這也是屬於重復性的工作,可否使用一種方式,讓這一過程變自動化呢?查詢了相關資料后發現,nodejs本來就可以。先創建兩個模板,然后使用 fs 插件負責讀寫文件,講模板內容寫入到新文件中,使用path 插件查找文件路徑,把文件安置在指定位置,這不就完成了自動化了嗎。

為了美觀,我們額外安裝了chalk這個插件。該插件支持輸出不同顏色的文字;例如:

  // 輸出綠色文字的Hello World
  const chalk = require('chalk')
  console.log(chalk.green('Hello World'));

交互方式可以這樣設計。

  • 首先在package.json 創建新模塊的命令"new:view: 'node ./scripts/generatorView.js'"
  • 創建scripts/generatorView.js文件。
  • 需要創建新模塊時,使用npm run new:view,然后輸入模塊名稱就能創建相應的路由、視圖還可以增加api文件.

演示效果

// generatorView.js

const path = require('path')
const fs = require('fs')
const chalk = require('chalk')
const reslove = file => path.resolve(__dirname, '../', file)
// 獲取文件路徑
const RouterSymbol = reslove('src/router/modules')
const ViewsSymbol = reslove('src/views/modules')
const apiSymbol = reslove('api')

// 打印函數封裝
const errorLog = error => console.log(chalk.red(`${error}`))
const defaultLog = log => console.log(chalk.green(`${log}`))

// 視圖層文件模板
const vueFile = module => (`<template>
  <div class="${module}">
    <h2>${module}</h2>
  </div>
</template>

<script>
export default {
  name: '${module}',
  data () {
    return {

    }
  },
  methods: {

  },
  created () {
 
  }
}
</script>

<style scoped>

</style>
`)

// 路由文件模板
const routerFile = module => (`
export default [
  {
    path: '/${module}',
    name: '${module}',
    component: () => import('@/views/modules/${module}/index')
  }
]
`)

// api文件模板
const apiFile = module => (`
import instance from 'axios'
export const get${module}list = (params) => {
  return instance.post('/', params)
}
`)
/**
 * 生成文件函數
 * @param {*} filePath 文件路徑
 * @param {*} content 文件內容
 * @param {*} dirPath 文件夾路徑
 */
const generateFile = async (filePath, content, dirPath = '') => {
  try {
    // 判斷是否存在
    if (dirPath !== '' && !await fs.existsSync(dirPath)) {
      await fs.mkdirSync(dirPath)
      defaultLog(`created ${dirPath}`)
    }
    if (!await fs.existsSync(filePath)) {
      // create file
      await fs.openSync(filePath, 'w')
      defaultLog(`created ${filePath}`)
    }
    await fs.writeFileSync(filePath, content, 'utf8')
  } catch (error) {
    errorLog(error)
  }
}
// map存儲要創建的文件信息
const generates = new Map([
  ['view', async (module) => {
    const filePath = path.join(ViewsSymbol, module)
    const vuePath = path.join(filePath, '/index.vue')
    await generateFile(vuePath, vueFile(module), filePath)
  }],

  ['router', async (module) => {
    const routerPath = path.join(RouterSymbol, `/${module}.js`)
    await generateFile(routerPath, routerFile(module))
  }],

  ['api', async (module) => {
    const apiPath = path.join(apiSymbol, `/${module}.js`)
    await generateFile(apiPath, apiFile(module))
  }]
])
defaultLog(`請輸入模塊名稱(英文):`)

// 創建視圖、路由和api三個文件
const files = ['view', 'router', 'api']

// 監聽輸入內容
process.stdin.on('data', (chunk) => {
  try {
    chunk = chunk.slice(0, -1) // 刪除尾部多余換行符
    defaultLog(`new module name is ${chunk}`)
    files.forEach(async (el, index) => {
      await generates.get(`${el}`)(chunk.toString())
      if (index === files.length - 1) {
        process.stdin.emit('end')
      }
    })
  } catch (error) {
    errorLog(error)
  }
})

// 生成結束,退出流程
process.stdin.on('end', () => {
  defaultLog('create module success')
  process.exit(0)
})

結語

通過nodejs自動創建文件后,再結合require.context進行上下文收集。我們在創立新模塊時,就可以直接進行頁面開發即可。但這個創建方式只能對新路由在一級時管用,如果想在modules內的模塊進行擴展,我們需要先讀取該文件,然后在指定進行重寫。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM