uniapp+vue3+vite+ts 全局工具类函数动态自动引入注册,无需页面引入直接使用

1,068 阅读4分钟

前言

发一下牢骚,2024年3月,这个月我很疲惫,长时间的精神紧绷,除了好像每天的工作时间是我可以稍微让我忘掉生活琐事的救赎。自2024年1月,我在老家买了房,当然我也已经做好了房贷的准备,可是听到那些不理解的声音,我不去反驳,我觉得世上没有那么多感同身受。我也只是个普通人,听多了也会失望,也是偶尔的迷失自我,怀疑自己。好在还有人帮助我,支持我。在这段昏暗的日子里,我弄了很多东西,其中这个是我一直很喜欢的东西,算是一劳永逸的一个东西

技术栈 uniapp+vue3+vite+ts

utils全局工具类函数动态自动引入,无需页面引入直接使用

utils创建

这里项目创建就省略了,在src里创建utils文件夹,然后在创建一个文件夹tool,在tool里面写公共的函数

// /tool/basicsA.ts
/**
 * 是否数组
 */
export const array = (value: any) =>{
  if (typeof Array.isArray === 'function') {
    return Array.isArray(value);
  }
  return Object.prototype.toString.call(value) === '[object Array]';
}


// /tool/basicsB.ts
/**
 * 金额,只允许2位小数
 */
export const amount = (value: any) => {
  // 金额,只允许保留两位小数
  return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value);
}

这时候我们有两个文件写的公共函数,如果我们要使用这两个函数呢 我们需要去main.ts里面逐个引入注册

// main.ts
import { createSSRApp  } from 'vue';
import App from './App.vue';
import { array } from '@/utils/tool/basicsA'
import { amount } from '@/utils/tool/basicsB'
export function createApp() {
  const app = createSSRApp(App);
  app.config.globalProperties.$array = array
  app.config.globalProperties.$amount = amount
  return {
    app
  };
}

然后会发现一个问题 当我们的公共函数多了,我们就要写很多引入很多注册,这是一个我们不愿意见到的问题,这时候我们会想到一个方法,创建一个index.ts让他们在index里面注册不就好了而且不用全部函数名都写

// src/utils/index.ts
import * as basicsA from './tool/basicsA';
import * as basicsB from './tool/basicsB';

当然这样引入也可以解决问题,不过我想如果后面我的tool文件越来越多,那每次都要去引入声明就很麻烦,所以就想到能不能动态的去读取tool里的ts文件,然后获取里面的函数然后在自动声明呢。

///utils/index.ts
const modules:any = {}
// 读取tool里面的ts
const files = import.meta.glob('./tool/*.ts')
// 循环获取里面的函数组
for( const key in files ) {
  await files[key]().then((res:any) => {
      // 将所有的函数集合到modules中去
      for(const funName in res) {
          modules[funName] = res[funName]
      }
  })
}

export default modules
// main.ts

import { createSSRApp  } from 'vue';
import App from './App.vue';
import utils from '@/utils/index'

export function createApp() {
  const app = createSSRApp(App);
  app.config.globalProperties.$utils = utils
  return {
    app
  };
}
// 页面中使用
<script setup lang="ts">
import { onMounted, getCurrentInstance } from 'vue'
const { proxy }:any = getCurrentInstance()
onMounted(() => {
    let num = 3.1415
    proxy.$utils.amount(num)
})
</script>

到这里就完成了,我执行了run dev:h5查看没问题,然后我执行run dev:mp-weixin问题就来了,就会出现一个报错Module format "cjs" does not support top-level await. Use the "es" or "syste 这个错误是因为 CommonJS(CJS)模块格式不支持顶层的 await,你需要使用 ES 模块或 SystemJS 输出格式来解决这个问题。

有问题就得解决所以我又想了一个办法去解决,仔细翻阅了一下viteimport.meta.glob的使用,使用eager: true 可以自己去了解一下import.meta.glob

///utils/index.ts
import type { App } from 'vue';
export default {
  install(app: App) {
    const files:any = import.meta.glob('./tool/*.ts', { eager: true })
    for(const path in files) {
     console.log('files[path]==', files[path])
     let module: any = files[path]
     Object.keys(module).forEach(key=> {
       console.log('key==', key)
       app.config.globalProperties['$' + key] = module[key]
     })
    }
  }
}
import { createSSRApp  } from 'vue';
import App from './App.vue';

import utils from '@/utils/index'
export function createApp() {
  const app = createSSRApp(App);
  app.use(utils)
  return {
    app
  };
}
//页面使用
<script setup lang="ts">
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app';
import { onMounted, getCurrentInstance } from 'vue'
const { proxy }:any = getCurrentInstance()

onShow(() => {
   let num = 3.1415 
   proxy.$amount(num)
})

</script>

好了到这里就结束了,其实中间做了很多方式都成功了,可是我在实验的时候一直改错了位置console.log('proxy.$priceFormat', proxy.$priceFormat(num,2)),因为看起来一样一直改的都是前面的那个字符串,就一直有问题很懵逼的搞了一天 到最后才发现使用的时候没写对位置。

感慨

自2023年疫情放开后,我总会感觉上班能让我很踏实,好像是因为它能让我获得报酬,是我生活的一份保障,同时做前端也是我很喜欢的事。写到这里我会很开心,与很多人相比,我的工作就是在做自己喜欢的事情。所以那些声音永远不会停止,我与他们也并非感同身受,相信自己,但也要听人劝。