功能特性

深入了解 Root 的核心功能和特性

Root 提供了多种强大功能,帮助 Uniapp 开发者解决无法使用根部组件的问题。本文档将详细介绍这些功能及其使用方法。

功能一:自定义虚拟根组件名称

默认情况下,Root 使用 App.ku.vue 作为虚拟根组件的文件名。但您可以根据项目需求自定义这个名称,提高项目的灵活性和可维护性。

配置方法

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. 配置文件名:在 vite.config.(js|ts) 中设置 rootFileName 选项
  2. 创建对应文件:创建与配置名称对应的 Vue 文件(如 KuRoot.vue
  3. 使用视图标签:在新文件中使用 <KuRootView /> 指定视图位置

示例

<!-- KuRoot.vue (替代默认的 App.ku.vue) -->
<script setup lang="ts">
import { ref } from 'vue'
const customRootMessage = ref('Hello from Custom Root!')
</script>

<template>
  <div class="custom-root">
    <h1>{{ customRootMessage }}</h1>
    <!-- 视图标签 -->
    <KuRootView />
  </div>
</template>

<style scoped>
.custom-root {
  padding: 20px;
  background-color: #f5f5f5;
}
</style>

注意事项

  • 文件名不需要包含 .vue 后缀,Root 会自动添加
  • 修改文件名后,原有的 App.ku.vue 将不再生效
  • 确保项目中的所有引用都使用新的文件名

功能二:使用虚拟根组件实例

Root 提供了两种方式获取虚拟根组件实例:局部启用和全局启用。这使得您可以在页面中直接调用根组件的方法和访问其数据。

局部启用

局部启用方式适用于只需要在特定页面中访问根组件实例的场景。

实现步骤

  1. 在根组件中暴露方法和数据
<!-- src/App.ku.vue | App.ku.vue -->
<script setup lang="ts">
import { ref } from 'vue'

const helloKuRoot = ref('Hello AppKuVue')
const exposeRef = ref('this is from app.Ku.vue')

// 定义方法
function showMessage(message: string) {
  console.log('Message from root:', message)
  return `Root received: ${message}`
}

// 暴露给页面使用
defineExpose({
  exposeRef,
  showMessage
})
</script>

<template>
  <div>
    <div>{{ helloKuRoot }}</div>
    <KuRootView />
  </div>
</template>
  1. 在页面中获取引用
<!-- src/pages/*.vue -->
<script setup lang="ts">
import { ref, onMounted } from 'vue'

// 创建 ref 对象,名称需与模板中的 root 属性值一致
const uniKuRoot = ref()
const message = ref('')

onMounted(() => {
  // 通过 ref 访问根组件暴露的方法和数据
  if (uniKuRoot.value) {
    message.value = uniKuRoot.value.exposeRef
  }
})

function callRootMethod() {
  if (uniKuRoot.value) {
    const result = uniKuRoot.value.showMessage('Hello from page!')
    console.log(result)
  }
}
</script>

<!-- 使用 root 属性指定 ref 名称 -->
<template root="uniKuRoot">
  <view>
    <text>Exposed value: {{ message }}</text>
    <button @click="callRootMethod">Call Root Method</button>
  </view>
</template>

全局启用

全局启用方式适用于需要在多个页面中访问根组件实例的场景。

实现步骤

  1. 启用全局自动注入
// 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()
  ]
})
  1. 在根组件中暴露方法和数据
<!-- src/App.ku.vue | App.ku.vue -->
<script setup lang="ts">
import { ref } from 'vue'

const helloKuRoot = ref('Hello AppKuVue')
const globalCounter = ref(0)

function incrementCounter() {
  globalCounter.value++
  return globalCounter.value
}

defineExpose({
  helloKuRoot,
  globalCounter,
  incrementCounter
})
</script>

<template>
  <div>
    <div>{{ helloKuRoot }}</div>
    <KuRootView />
  </div>
</template>
  1. 在页面中获取实例
<!-- src/pages/*.vue -->
<script setup lang="ts">
import { ref, onMounted } from 'vue'

const uniKuRoot = ref()
const counter = ref(0)

onMounted(() => {
  // 通过 getCurrentPages() 获取根组件实例
  const pagesStack = getCurrentPages()
  if (pagesStack.length > 0) {
    uniKuRoot.value = pagesStack[pagesStack.length - 1].$vm.$refs.uniKuRoot
    counter.value = uniKuRoot.value?.globalCounter || 0
  }
})

function increment() {
  if (uniKuRoot.value) {
    counter.value = uniKuRoot.value.incrementCounter()
  }
}
</script>

<template>
  <view>
    <text>Global Counter: {{ counter }}</text>
    <button @click="increment">Increment</button>
  </view>
</template>

两种方式的比较

特性局部启用全局启用
配置复杂度简单,只需在模板中添加属性需要在 vite.config 中配置
使用范围仅限当前页面所有页面均可使用
性能影响最小,按需加载略高,全局注入
适用场景少量页面需要访问根组件多个页面需要访问根组件
代码简洁性需要在每个页面定义 ref一次配置,多处使用

功能三:过滤不需要根组件的页面

在某些情况下,您可能希望某些页面不使用根组件,例如登录页、错误页等特殊页面。Root 提供了 excludePages 选项来满足这一需求。

配置方法

vite.config.(js|ts) 中通过 excludePages 选项进行配置:

// 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: [
        'src/exclude.vue',
        'src/exclude/**/*.vue',
        'src/pages/login.vue',
        'src/pages/error/**/*.vue'
      ],
    }),
    Uni()
  ]
})

Glob 模式支持

excludePages 选项支持使用 Glob 模式进行灵活匹配:

模式描述示例
*.vue匹配当前目录下所有 Vue 文件pages/*.vue
**/*.vue匹配所有子目录中的 Vue 文件pages/**/*.vue
src/login.vue匹配特定文件src/login.vue
src/auth/**匹配特定目录下的所有文件src/auth/**

实际应用示例

1. 排除登录和注册页面

// vite.config.(js|ts)
UniKuRoot({
  excludePages: [
    'src/pages/login.vue',
    'src/pages/register.vue',
    'src/pages/forgot-password.vue'
  ]
})

2. 排除整个错误页面目录

// vite.config.(js|ts)
UniKuRoot({
  excludePages: [
    'src/error-pages/**'
  ]
})

3. 排除特定模式的页面

// vite.config.(js|ts)
UniKuRoot({
  excludePages: [
    'src/pages/modal-*.vue',
    'src/pages/**/popup-*.vue'
  ]
})

注意事项

  • 路径是相对于项目根目录的
  • 使用 Glob 模式时,确保路径匹配准确,避免意外排除需要的页面
  • 排除的页面将不会应用根组件,也不会包含 <KuRootView /> 标签
  • 如果页面中使用了根组件暴露的方法或数据,需要确保这些页面不被排除

功能四:使用 TypeScript 支持

Root 提供了完整的 TypeScript 支持,帮助开发者获得更好的类型检查和代码提示。

类型定义

Root 提供了以下类型定义:

// 根组件实例类型
interface UniKuRootInstance {
  // 用户在根组件中暴露的任何方法和数据
  [key: string]: any
}

// 配置选项类型
interface UniKuRootOptions {
  rootFileName?: string
  enabledGlobalRef?: boolean
  excludePages?: string[]
}

在 TypeScript 项目中使用

  1. 配置 vite.config.ts
// vite.config.ts
import Uni from '@dcloudio/vite-plugin-uni'
import UniKuRoot, { UniKuRootOptions } from '@uni-ku/root'
import { defineConfig } from 'vite'

const options: UniKuRootOptions = {
  rootFileName: 'KuRoot',
  enabledGlobalRef: true,
  excludePages: [
    'src/pages/login.vue'
  ]
}

export default defineConfig({
  plugins: [
    UniKuRoot(options),
    Uni()
  ]
})
  1. 在页面中使用类型
<!-- src/pages/*.vue -->
<script setup lang="ts">
import { ref, onMounted } from 'vue'

// 定义根组件暴露的类型
interface RootComponentExposed {
  helloKuRoot: string
  globalCounter: number
  incrementCounter: () => number
}

const uniKuRoot = ref<RootComponentExposed>()
const counter = ref(0)

onMounted(() => {
  const pagesStack = getCurrentPages()
  if (pagesStack.length > 0) {
    uniKuRoot.value = pagesStack[pagesStack.length - 1].$vm.$refs.uniKuRoot as RootComponentExposed
    counter.value = uniKuRoot.value?.globalCounter || 0
  }
})

function increment() {
  if (uniKuRoot.value) {
    // 现在有了类型提示和检查
    counter.value = uniKuRoot.value.incrementCounter()
  }
}
</script>

<template>
  <view>
    <text>Global Counter: {{ counter }}</text>
    <button @click="increment">Increment</button>
  </view>
</template>

类型安全的好处

使用 TypeScript 带来的好处包括:

  • 代码提示:编辑器会提供根组件暴露的方法和属性的自动补全
  • 类型检查:在编译时发现类型错误,减少运行时错误
  • 更好的文档:类型定义本身就是一种文档,清晰地说明了可用的方法和属性
  • 重构支持:当根组件的 API 发生变化时,TypeScript 会帮助找到所有需要更新的地方

功能五:与 Uniapp 生命周期集成

Root 与 Uniapp 的生命周期完美集成,确保根组件和页面组件的生命周期事件能够正确触发。

生命周期执行顺序

当使用 Root 时,生命周期事件的执行顺序如下:

  1. 根组件的 onLaunch / created
  2. 根组件的 onLoad
  3. 页面组件的 onLoad
  4. 根组件的 onShow
  5. 页面组件的 onShow
  6. 根组件的 onReady
  7. 页面组件的 onReady

在根组件中使用生命周期

<!-- src/App.ku.vue -->
<script setup lang="ts">
import { ref, onLaunch, onLoad, onShow, onReady } from '@dcloudio/uni-app'

const appData = ref('')

onLaunch(() => {
  console.log('Root onLaunch')
  appData.value = 'App initialized'
})

onLoad(() => {
  console.log('Root onLoad')
})

onShow(() => {
  console.log('Root onShow')
})

onReady(() => {
  console.log('Root onReady')
})
</script>

<template>
  <div>
    <div>{{ appData }}</div>
    <KuRootView />
  </div>
</template>

注意事项

  • 根组件的生命周期事件会在所有页面对应的生命周期事件之前触发
  • 如果页面被 excludePages 排除,则不会触发根组件的生命周期事件
  • 确保在根组件中不要执行过多的初始化逻辑,以免影响页面加载性能

功能六:自定义视图标签

除了默认的 <KuRootView /> 标签,Root 还允许您自定义视图标签的名称,以更好地适应项目命名规范。

配置方法

vite.config.(js|ts) 中通过 viewTagName 选项进行配置:

// 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({
      // 自定义视图标签名称
      viewTagName: 'AppView',
    }),
    Uni()
  ]
})

使用自定义标签

<!-- src/App.ku.vue -->
<script setup lang="ts">
import { ref } from 'vue'
const message = ref('Hello from Root with custom view tag!')
</script>

<template>
  <div class="root-container">
    <h1>{{ message }}</h1>
    <!-- 使用自定义视图标签 -->
    <AppView />
  </div>
</template>

<style scoped>
.root-container {
  padding: 20px;
  background-color: #f0f0f0;
}
</style>

注意事项

  • 自定义标签名称不需要包含 <>,Root 会自动处理
  • 确保自定义标签名称不与现有组件或 HTML 元素冲突
  • 修改视图标签名称后,项目中所有使用该标签的地方都需要更新

功能七:调试模式

Root 提供了调试模式,帮助开发者更好地理解和调试根组件的行为。

启用调试模式

vite.config.(js|ts) 中通过 debug 选项进行配置:

// 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({
      // 启用调试模式
      debug: true,
    }),
    Uni()
  ]
})

调试信息

启用调试模式后,Root 会在控制台输出以下信息:

  • 根组件的创建和挂载过程
  • 页面组件的创建和挂载过程
  • 生命周期事件的触发顺序
  • 组件实例的引用信息
  • 排除页面的处理情况

示例输出

[UniKuRoot Debug] Creating root component: App.ku.vue
[UniKuRoot Debug] Root component mounted
[UniKuRoot Debug] Processing page: src/pages/index.vue
[UniKuRoot Debug] Page component mounted
[UniKuRoot Debug] Root ref injected: uniKuRoot
[UniKuRoot Debug] Excluded page: src/pages/login.vue

注意事项

  • 调试模式仅建议在开发环境中使用,生产环境应关闭
  • 调试信息可能会影响性能,特别是在页面数量较多的项目中
  • 可以结合浏览器的开发者工具,更好地理解 Root 的工作原理

总结

Root 提供了丰富的功能特性,帮助 Uniapp 开发者解决无法使用根部组件的问题。通过自定义虚拟根组件名称、使用虚拟根组件实例、过滤不需要根组件的页面、TypeScript 支持、生命周期集成、自定义视图标签和调试模式等功能,开发者可以构建更加灵活、可维护的 Uniapp 应用。

在实际项目中,根据具体需求选择合适的功能组合,可以充分发挥 Root 的优势,提升开发效率和用户体验。