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 拥有不同的方式使用模板引用
相关推荐
Mem0rin2 小时前
[Rust]模块关键词和哈希表
开发语言·rust
周淳APP2 小时前
【HTTP之跨域请求以及Cookie携带的限制】
前端·网络·网络协议·http
默 语2 小时前
TypeScrip+React 全栈生态实战:从架构选型到工程落地,告别开发踩坑
前端·react.js·架构
代码丰2 小时前
简历保险箱:一款本地存储、快捷填表的 Chrome 简历助手
前端·chrome
SuperEugene2 小时前
Promise 从入门到实战:同步异步、回调地狱、then/catch/finally 全解
前端·javascript·面试
lars_lhuan2 小时前
Go 方法
开发语言·后端·golang
前端 贾公子2 小时前
uniapp 小程序获取后端的二进制 保存到手机相册
java·前端·javascript
灰色小旋风2 小时前
力扣 12 整数转罗马数字 C++
开发语言·c++·leetcode
qq_437100662 小时前
echarts图表相关 电量进度图
前端·flask·echarts