vue项目的一些自动化操作写法。

vue项目中,我们经常会引入路由模块,api模块,vuex模块,还有一些公用组件模块。
每次都手动输入模块和路径,自然难免心生厌恶,只是个名字不一样,每次都得重新写一堆东西。
于是自动化注册和自动化引入,就显得非常重要了。

但是,其实所谓的自动化注册,核心思路就是通过require.context()函数拿到文件夹结构,然后处理数据,生成我们需要的对象或数组,再注册上。

1、自动化导入api模块。

假设我们有一个apiModules文件夹,里面存放我们的各个板块的api地址,如果不使用自动化导出,那么一定是这样的结构,一条条的引入,然后统一导出。
在这里插入图片描述

使用自动化导入之后,则是这样的:

在这里插入图片描述

可复制代码如下:

// https://webpack.js.org/guides/dependency-management/#requirecontext
// require.context(publicPath, true, /\.js$/), 三个参数分别为:
// 其组件目录的相对路径,是否查询其子目录,匹配基础组件文件名的正则表达式
const modulesFiles = require.context('./apiModules', true, /\.js$/)

// you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file
const apiModules = modulesFiles.keys().reduce((modules, modulePath) => {
  // set './app.js' => 'app'
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
  const value = modulesFiles(modulePath)
  modules[moduleName] = value.default
  return modules
}, {})

// console.log('auto modules', apiModules)

export default apiModules

2、自动化导入注册vuex中的modules模块。

这个其实和上面的导入api的操作一样,就不放代码了,上图就行。
在这里插入图片描述

3、利用vuex的plugins,实现自动同步vuex的数据到本地存储,或者从本地存储中恢复数据到vuex中。

此操作可以避免vuex刷新数据丢失,也方便查看本地存储中的数据。
但是注意安全措施,也可以做个加密处理再使用。

/**
 * 1、自动化恢复session中的数据到store,
 * 2、自动同步vuex中的数据到session
 * @param {*} store
 */

const sessionStoragePlugin = store => {
  // 自动化恢复session中的数据到store
  const sessionState = {}
  Object.keys(window.sessionStorage).forEach(sessionName => {
    const obj = {}
    obj[sessionName] = JSON.parse(window.sessionStorage.getItem(sessionName))
    Object.assign(sessionState, obj)
  })
  console.log('sessionState', sessionState)
  store.replaceState(Object.assign({}, store.state, sessionState))

  // 自动同步vuex中的数据到session
  store.subscribe((mutation, state) => {
    console.log('mutation', mutation)
    console.log('state', state)

    Object.keys(state).forEach((stateName, index) => {
      window.sessionStorage.setItem(
        stateName,
        JSON.stringify(state[stateName])
      )
    })

    console.log('mutation mutation', mutation)
    console.log('state state', state)
  })
}

export default [sessionStoragePlugin]

4.1、自动化注册路由。

如果是一些简单的路由结构,例如没有子层级children,那么同上一样,能够实现自动注册。这里就不赘述了。
但是实际情况却是,我们经常会遇到带有children的情况,而且还有动态路由的情况,所以这里我就不展开了,因为要考虑的情况太多 ,之前也尝试过写一些这方面的自动化,但是要考虑的东西太多。而且路由文件夹必须按照规格书写,限制太大。另外,非常的不灵活,如我们想针对某些特定路由添加一些meta信息什么的,那就哦豁了。
所以这里不建议路由使用自动化,而是按部就班的分模块引入,分模块管理,如果某一些模块的内容符合自动化注册的条件,再考虑针对该模块进行自动化。
这里只展示一下外面index的自动化模块管理,而具体到每个模块的路由实际上还需要手动书写。
在这里插入图片描述

—更新—————————————————————————————————————

4.2 自动化注册路由2,自动化注册子路由。

在这里插入图片描述

本来是不想这样做的,但是自己手动写相同的代码只是名称不一样,实在是难受。因此还是写了一个自动化注册子路由的简单示例,不涉及到继续嵌套子路由,所以也比较简单。

const VrView = () =>
  import(
    /* webpackChunkName: "VrView" */ '@/pages/vrView/vrView'
  )
const modulesFiles = require.context('@/pages/vrView', true, /(?<!View)(\.vue$)/)
const childRoutes = modulesFiles.keys().reduce((modules, modulePath) => {
  const value = modulesFiles(modulePath)
  const childConponent = value.default
  const path = modulePath.replace(/^\.\/(\w+)\.vue$/g, '$1')
  const name = path.replace(/^./, path[0].toUpperCase())
  const childRoute = {
    path: path,
    name: name,
    component: childConponent
  }

  return [...modules, childRoute]
}, [])

// reimburse/xxx
export default [
  {
    path: '/vrView',
    name: 'VrView',
    component: VrView,
    children: childRoutes
  }
]

路由文件夹结构为:
在这里插入图片描述
这里剔除了xxxView.vue结尾的组件。
当然了,如果写到极致xxxView文件也可以省掉,以后再说吧。
但是这样还是有个问题,我记得这样处理的结果是非按需加载,还需要研究一下如何变成按需加载才行。
在这里插入图片描述
打包后一看,果然尼玛非按需加载的。

—更新————————————————————————————————————

4.3 自动化注册路由3,require.context实现自动化的同时,使用require.ensure完成按需加载和分割代码。

终于,还是找到了解决方案,不要直接使用default导出的模块来作为component,而是要使用require.ensure或者require来实现按需加载。

关键代码如下:

const VrView = () =>
  import(
    /* webpackChunkName: "VrView" */ '@/pages/vrView/vrView'
  )
// const VrViewTest = () =>
//   import(
//     /* webpackChunkName: "VrViewTest" */ '@/pages/vrView/vrViewTest'
//   )
const modulesFiles = require.context('@/pages/vrView', false, /(?<!View)(\.vue$)/)
const childRoutes = modulesFiles.keys().reduce((modules, modulePath) => {
  const value = modulesFiles(modulePath)
  const childConponent = value.default
  const path = modulePath.replace(/^\.\/(\w+)\.vue$/g, '$1')
  const name = path.replace(/^./, path[0].toUpperCase())
  const aliasChildConponent = childConponent.__file.replace('src/', '')

  const childRoute = {
    path: path,
    name: name,
    // component: childConponent // 此种方式无法按需加载和分割代码。
    // component: resolve => require([`@/${ aliasChildConponent }`], resolve) // 可以按需加载,但是无法命名chunk。
    component: resolve => require.ensure([], () => resolve(require(`@/${ aliasChildConponent }`)), `vrView`)
  }
  return [...modules, childRoute]
}, [])

打包查看结果。
在这里插入图片描述
确实分包了。

但是查看分析图,发现业务代码是分包了,但是第三方库的分包机制却十分混乱,调试了很久依然无果。。。

5、自动化导出和注册基础模块。

require.context()函数非常好用,但是一定请不要滥用。

下例中,就是我实际遇到的项目中的情况。在这里插入图片描述
也许当初写代码的人只是为了偷个懒,一次性导出所有的公用组件。
但是结果就是后续维护的人不断往里面添加组件,各种组件,管它公不公用,是否有必要统一导出,导致components文件夹非常庞大。
正常情况下,components文件夹大点也无所谓,其他页面需要就引入,问题不大。
但是这样写了自动导出之后,其他页面是这样来引入所需组件的。
在这里插入图片描述
明明只是为了使用其中一个按钮,结果引入了整个componens文件夹下的全部组件对象。
更恶心的是,当后续开发人员想知道这个组件的路径来源,对组件进行维护时,会一脸懵逼,因为他必须打开components文件夹,一个个的去找。
对了,还不能同名。
。。。

那么正确的做法是什么样的呢 ?

1、首先明确,只有非常基础的,使用频率很高的组件,才建议使用自动导出。例如可以在components文件夹下新建一个base文件夹,然后创建一个index.js来自动导出base文件夹中的所有基础组件。
2、针对这些自动导出的组件,可以进行全局注册,当然,还是建议慎用全局。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值