zoukankan      html  css  js  c++  java
  • 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内的模块进行扩展,我们需要先读取该文件,然后在指定进行重写。

  • 相关阅读:
    【oracle ocp知识点一】
    poj 3280 区间dp
    TextView划线 android
    Apple Watch 集成环信SDK
    Android中使用HttpClient实现HTTP通信效果
    js 数组操作大集合
    5.5二叉树的遍历
    oracle学习之路(二)------数组类型/记录类型的使用
    推荐系统个人理解(实践部分)
    openstack之虚拟机创建流程分析
  • 原文地址:https://www.cnblogs.com/miku561/p/13426898.html
Copyright © 2011-2022 走看看