uni-app 也能使用 App.vue?解决 uniapp 无法使用公共组件问题

借助 Vite 模拟出虚拟根组件(支持SFC的App.vue),解决 uniapp 无法使用公共组件问题

  • 自定义虚拟根组件文件命名(App.ku.vue文件命名支持更换)
  • 更高灵活度的获取虚拟根组件实例(获取KuRootView的Ref)
  • 自动提取PageMeta到页面顶层(自动提升小程序PageMeta[用于阻止滚动穿透]组件)

📦 安装

复制代码
pnpm add -D @uni-ku/root

yarn add -D @uni-ku/root

npm install -D @uni-ku/root

🚀 使用

1. 引入 @uni-ku/root

复制代码
// vite.config.(js|ts)

import Uni from '@dcloudio/vite-plugin-uni'
import UniKuRoot from '@uni-ku/root'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [
    // 若存在改变 pages.json 的插件,请将 UniKuRoot 放置其后
    UniKuRoot(),
    Uni()
  ]
})

Note

CLI直接编写 根目录下的 vite.config.(js|ts)

HBuilderX :在根目录下 创建 vite.config.(js|ts) 并写入

2. 创建 App.ku.vue(可自定义此根组件名称,请下拉至功能参考设置)

通过标签 <KuRootView /><ku-root-view /> 指定视图存放位置,并且可以将该标签放置到 template 内任意位置,但仅可有一个

复制代码
<!-- src/App.ku.vue | App.ku.vue -->

<script setup lang="ts">
import { ref } from 'vue'

const helloKuRoot = ref('Hello AppKuVue')
</script>

<template>
  <div>{{ helloKuRoot }}</div>
  <!-- 顶级 KuRootView -->
  <KuRootView />

  <!-- 或内部 KuRootView,无论放置哪一个层级都被允许,但仅可有一个! -->
  <div>
    <KuRootView />
  </div>
</template>

Note

CLI: 需要在 src目录 下创建下 App.ku.vue (或自定义名称)

HBuilderX: 直接在 根目录 下创建 App.ku.vue (或自定义名称)

Important

该标签与 VueRouter 中的 RouterView 功能类似,但请注意,由于Uniapp-Vue的局限性,该功能并不完全等同于VueRouter的 RouterView

功能

功能一:自定义虚拟根组件名称(默认:App.ku.vue)
  1. 通过设置 vite.config.(js|ts) 下插件的参数 rootFileName 来自定义虚拟根组件名称
复制代码
// vite.config.(js|ts)

import Uni from '@dcloudio/vite-plugin-uni'
import UniKuRoot from '@uni-ku/root'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [
    UniKuRoot({
      // 默认含后缀 .vue,直接设置命名即可
      rootFileName: 'KuRoot',
    }),
    // ...other plugins
  ]
})
  1. 创建/修改虚拟根组件为 KuRoot.vue,即可实现自定义,其余功能不变
复制代码
// App.ku.vue 文件重命名为 KuRoot.vue
功能二:使用虚拟根组件实例(即:App.ku.vue)

有两种启用方式,局部或全部启用

一、 局部启用

  1. 暴露出 App.ku.vue 里所要被使用的变量或方法

    <script setup lang="ts"> import { ref } from 'vue'

    const helloKuRoot = ref('Hello AppKuVue')

    const exposeRef = ref('this is form app.Ku.vue')

    defineExpose({
    exposeRef,
    })
    </script>

    <template>
    {{ helloKuRoot }}
    <KuRootView />
    </template>
  2. 在 template 内编写 root="uniKuRoot",并通过 const uniKuRoot = ref() 获取模板引用

uniKuRoot 仅是一个变量,你可以根据你习惯重新命名

复制代码
<!-- src/pages/*.vue -->

<script setup lang="ts">
import { ref } from 'vue'

const uniKuRoot = ref()
</script>

<template root="uniKuRoot">
  <view>
    Hello UniKuRoot
  </view>
</template>

二、全局启用

  1. 通过配置 enabledGlobalRef 开启全局自动注入 App.ku 实例

    // vite.config.(js|ts)

    import Uni from '@dcloudio/vite-plugin-uni'
    import UniKuRoot from '@uni-ku/root'
    import { defineConfig } from 'vite'

    export default defineConfig({
    plugins: [
    UniKuRoot({
    enabledGlobalRef: true
    }),
    Uni()
    ]
    })

  2. 暴露出 App.ku 里所要被使用的变量或方法

    <script setup lang="ts"> import { ref } from 'vue'

    const helloKuRoot = ref('Hello UniKuRoot')

    const exposeRef = ref('this is from App.ku.vue')

    defineExpose({
    exposeRef,
    })
    </script>

    <template>
    {{ helloKuRoot }}
    <KuRootView />
    </template>
  3. 通过特有内置方法 getCurrentPages()= 获取暴露的数据

    <script setup lang="ts"> import { onMounted, ref } from 'vue'

    const pagesStack = getCurrentPages()
    const uniKuRoot = ref()

    onMounted(() => {
    uniKuRoot.value = pagesStack[pagesStack.length - 1].vm.refs.uniKuRoot
    })
    </script>

    <template> <view> Hello UniKuRoot </view> </template>
功能三:过滤掉不需要根组件的页面

如果遇到一些不需要根组件的页面,可以设置 excludePages 选项来过滤

excludePages 选项支持采用 glob 模式进行编写

复制代码
// vite.config.(js|ts)

import Uni from '@dcloudio/vite-plugin-uni'
import UniKuRoot from '@uni-ku/root'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [
    UniKuRoot({
      excludePages: [
        'pages/exclude.vue',
        'pages/exclude/**/*.vue'
      ],
    }),
    Uni()
  ]
})

✨ 例子

以下例子均以 CLI 创建项目为例, HBuilderX 项目设置同理, 只要注意是否需要包含 src目录 即可

不仅是 Toast 组件,还可以是 Message、LoginPopup 等等

  1. 编写 Toast 组件

    <script setup lang="ts"> import { useToast } from '@/composables/useToast'

    const { globalToastState, hideToast } = useToast()
    </script>

    <template>
    welcome to use @uni-ku/root
    </template> <style scoped> .toast-wrapper{ position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; }

    .toast-box{
    background: white;
    color: black;
    }
    </style>

  2. 实现 Toast 组合式API

    // src/composables/useToast

    import { ref } from 'vue'

    const globalToastState = ref(false)

    export function useToast() {
    function showToast() {
    globalToastState.value = true
    }

    function hideToast() {
    globalToastState.value = false
    }

    return {
    globalToastState,
    showToast,
    hideToast,
    }
    }

  3. 挂载至 App.ku.vue

    <script setup lang="ts"> import GlobalToast from '@/components/GlobalToast.vue' </script> <template> <KuRootView /> <GlobalToast /> </template>
  4. 视图内部触发全局 Toast 组件

    <script setup lang="ts"> import { useToast } from '@/composables/useToast'

    const { showToast } = useToast()
    </script>

    <template> <view> Hello UniKuRoot </view> <button @click="showToast"> 视图内触发展示Toast </button> </template>

与uni-helper-layouts的区别

root的核心理念就是尽可能的靠近Vue中的App.vue,layouts 则是类nuxt的布局系统

  • root 是 layouts 之上,提供更多的自由度,能够实现layouts的效果,更加容易控制布局组件
  • root 能够使用PageMeta,自动提取到页面顶层节点
  • root 拥有不同的方式使用模板引用
相关推荐
南境十里·墨染春水2 分钟前
C++ 笔记 友元(面向对象)
开发语言·c++·笔记
TT_44194 分钟前
python程序实现图片截图溯源功能
开发语言·python
笨笨饿18 分钟前
20_Git 仓库使用手册 - 初学者指南
c语言·开发语言·嵌入式硬件·mcu·学习
人间打气筒(Ada)22 分钟前
go实战案例:如何通过 Service Meh 实现熔断和限流
java·开发语言·golang·web·istio·service mesh·熔断限流
小小小小宇30 分钟前
前端转后端基础- 变量和类型
前端
Cobyte1 小时前
1.基于依赖追踪和触发的响应式系统的本质
前端·javascript·vue.js
桦01 小时前
[C++复习]:STL
开发语言·c++
主宰者1 小时前
C# CommunityToolkit.Mvvm全局事件
java·前端·c#
老神在在0011 小时前
【Selenium 自动化精讲】浏览器弹窗与登录界面的本质区别 & 实操指南
javascript·学习·selenium·测试工具·自动化
前端小咸鱼一条2 小时前
16.迭代器 和 生成器
开发语言·前端·javascript