前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >UniApp 的全局组件注入的问题记录

UniApp 的全局组件注入的问题记录

原创
作者头像
永恒的财宝
修改2024-11-26 14:20:04
修改2024-11-26 14:20:04
1660
举报

文章开始之前,推荐一些别人写的很好的文章!感兴趣的也可以去读一下哦!

今日推荐:JS代码之混淆

文章链接:https://cloud.tencent.com/developer/article/2200754

作者讲得很具体,从使用插件到手写混淆步步为营,也顺带回顾一下 AST 相关的知识。

在给 UniApp 注入全局组件时,发现有些优化比如只是改动了文件结构都会报错,所以将这个探索过程记录下来,以实战角度选择最佳的方案。

可用方案1

代码语言:ts
复制
// main.ts
import { createSSRApp } from 'vue'
import BaseIcon from './global-components/base-icon.vue'
import App from './App.vue'

export function createApp () {
  const app = createSSRApp(App)
  app.components('base-icon', BaseIcon)
  return { app }
}

在这种方式下,打包后组件才位于 app.json 中,是真正的全局组件

代码语言:json
复制
{
  "usingComponents": {
    "base-icon": "/global-components/base-icon"
  }
}

错误方案1

新建 /global-components/index.ts 去集合所有组件,然后 import 全部,再遍历注册。

但是,最终没有注册成功。

代码语言:ts
复制
// ./global-components/index.ts
export { default as BaseIcon } from './base-icon.vue'
代码语言:ts
复制
// main.ts
import { createSSRApp } from 'vue'
import type { Component, App as Vue } from 'vue'
import * as globalComps from './global-components/index'

type GlobalComponents = Record<string, Component & { __name: string }>
function installGlobalComponents (app: Vue, comps: GlobalComponents) {
  Object.keys(comps).forEach((key) => {
    const comp = comps[key]
    const name = comp.__name || key
    console.log('全局注册组件:', name, comp)
    app.component(key, comp)
  })
}

export function createApp () {
  const app = createSSRApp(App)
  installGlobalComponents(app, globalComps)
  return { app }
}

错误方案2

使用 import.meta.glob 也是与上面类似的思路。

但是,最终也没有注册成功。

代码语言:ts
复制
import type { Component, App as Vue } from 'vue'

function installGlobalComponents (app: Vue) {
  type GlobalComponents = Record<string, { default: Component }>
  const modules: GlobalComponents = import.meta.glob('./global-components/*.vue', { eager: true })

  Object.keys(modules).forEach((url) => {
    const baseName = url.split('/').pop() || ''
    const name = baseName.slice(0, -4)
    const comp = modules[url].default

    if (!name) return

    console.log('全局注册组件:', name, comp)
    app.component(name, comp)
  })
}

错误方案3

此时有点意识到,恐怕只是将 app.component() 提取到别处,都会是注册不成功的表现。

代码语言:ts
复制
// main.ts
import installGlobalComponents from './global-components/install.ts'

export function createApp () {
  installGlobalComponents(app)
}
代码语言:ts
复制
// ./global-components/install.ts
import { default as BaseIcon } from './base-icon.vue'

export default function installGlobalComponents (app: any) {
  app.component('base-icon', BaseIcon)
}

结果来看,果然如此,不得不吐槽 UniApp 竟然限定如此死,只能在 main.ts 中注册。

以后得闲再翻翻它的源码看下。

可用方案2

https://uniapp.dcloud.net.cn/collocation/pages.html#easycom

UniApp 中有个 easycom 的机制,可以以此来自动导入组件。需在 pages.json 中进行配置:

代码语言:json
复制
{
  "globalStyle": {},
  "easycom": {
    "autoscan": true,
    "custom": {
      "^base-(.*)": "@/global-components/base-$1.vue"
    }
  }
}

但它与 可用方案1 的区别在于,打包后该组件是位于 src/pages/xx/x.json 页面中的。

代码语言:json
复制
{
  "navigationBarTitleText": "某页面",
  "usingComponents": {
    "base-icon": "../../global-components/base-icon"
  }
}

总结

鉴于以下几点,最终选择 可用方案2

  1. 主包体积比分包体积更珍贵,所以组件置于页面中比全局更好
  2. 可用方案1 只能在 main.ts 中不断增加 import,可能不太好看

邀请人:一起重学前端

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 可用方案1
  • 错误方案1
  • 错误方案2
  • 错误方案3
  • 可用方案2
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档