Vuetify0组件详解:如何用Atom、Portal和Presence构建灵活界面基础
Vuetify0组件详解:如何用Atom、Portal和Presence构建灵活界面基础
【免费下载链接】00️⃣ Composable UI engine for Vue. Build complex interfaces with reusable state, logic, and primitives—without being locked into components or styles.项目地址: https://gitcode.com/gh_mirrors/03/0
Vuetify0是一个基于Vue的可组合UI引擎,它允许开发者使用可重用的状态、逻辑和原语构建复杂界面,而不必局限于特定的组件或样式。本文将详细介绍Vuetify0中的三个核心基础组件——Atom、Portal和Presence,它们共同构成了构建灵活界面的基础。
什么是Vuetify0的基础组件?
Vuetify0提供了一系列基础组件,这些组件是构建更复杂UI元素的基石。其中,Atom、Portal和Presence是三个最核心的基础组件,它们分别解决了不同的界面构建问题:
- Atom:提供多态渲染能力,是所有组件的基础
- Portal:实现内容的跨DOM树渲染,解决z-index和定位问题
- Presence:管理组件的挂载生命周期,支持动画过渡效果
这三个组件虽然简单,但组合起来可以创建出非常复杂和灵活的界面效果。
Atom:多态渲染的基础
Atom是Vuetify0中最低级别的原语组件,提供了多态渲染能力,是构建所有其他组件的基础。
Atom的核心功能
Atom组件主要提供以下功能:
- 多态元素渲染:可以渲染为任何HTML元素,通过
as属性指定 - 三种渲染模式:
- 元素模式(默认):渲染为指定的HTML元素
- 无包装模式:直接渲染插槽内容,不添加额外包装
- 空模式:当
as={null}时等同于无包装模式
- 自动属性转发:将组件接收的属性自动转发到渲染的元素
- 自闭合标签检测:自动处理img、input等自闭合标签
Atom的基本用法
<!-- 元素模式 --> <Atom as="button" class="my-button" @click="handleClick"> 点击我 </Atom> <!-- 无包装模式 --> <Atom renderless> <div class="custom-element">直接渲染我</div> </Atom> <!-- 自闭合标签 --> <Atom as="img" src="image.jpg" alt="图片" />Atom的高级应用
Atom的多态特性使其非常适合构建可定制的组件库。例如,你可以基于Atom创建一个通用的按钮组件:
<!-- MyButton.vue --> <template> <Atom :as="as" :class="['my-button', variant, size]" :disabled="disabled" v-bind="$attrs" > <slot /> </Atom> </template> <script setup> import { Atom } from '@vuetify/v0' defineProps({ as: { type: String, default: 'button' }, variant: { type: String, default: 'default' }, size: { type: String, default: 'md' }, disabled: { type: Boolean, default: false } }) </script>通过这种方式,你可以创建一个既灵活又具有一致样式的按钮组件,同时保持了使用原生HTML元素的全部功能。
Atom组件的源代码可以在packages/0/src/components/Atom/Atom.vue找到。
Portal:跨DOM树渲染
Portal组件解决了一个常见的UI问题:如何将组件渲染到DOM树中的不同位置,同时保持组件逻辑上的父子关系。
Portal的核心功能
- 内容传送:将组件内容渲染到指定的DOM节点,而不是当前组件树中
- z-index协调:集成useStack系统,自动管理z-index,避免层叠顺序问题
- 动态目标:可以动态更改渲染目标,包括特殊的"top-layer"目标
- scrim支持:可选的背景遮罩,用于模态框等场景
Portal的基本用法
<Portal to="body"> <div class="fixed bottom-4 right-4 p-4 bg-blue-500 text-white"> 这个内容会被渲染到body元素中 </div> </Portal>Portal的高级应用
Portal非常适合创建模态框、通知、下拉菜单等需要显示在页面顶层的组件。例如,一个简单的模态框实现:
<template> <Portal :disabled="!show" @close="show = false"> <div :style="{ zIndex, position: 'fixed', inset: 0 }"> <div class="absolute inset-0 bg-black/50" @click="close"></div> <div class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 p-6 bg-white rounded-lg"> <h2 class="text-xl font-bold">模态框标题</h2> <p class="mt-2">模态框内容</p> <button class="mt-4 px-4 py-2 bg-blue-500 text-white rounded" @click="close"> 关闭 </button> </div> </div> </Portal> </template> <script setup> import { Portal } from '@vuetify/v0' const show = ref(false) const { zIndex, close } = useSlots() </script>在这个例子中,模态框内容会被渲染到body元素中,并且通过Portal的zIndex属性自动管理层叠顺序,避免被其他元素遮挡。
Portal组件的源代码可以在packages/0/src/components/Portal/Portal.vue找到。
Presence:管理组件生命周期
Presence组件用于管理组件的挂载和卸载过程,特别适合需要动画过渡效果的场景。
Presence的核心功能
- 生命周期管理:通过v-model控制组件的显示/隐藏状态
- 动画支持:提供进入和离开状态,支持CSS或JS动画
- 延迟卸载:在离开动画完成前保持组件在DOM中
- 懒加载:支持延迟初始挂载,直到第一次需要显示时
Presence的基本用法
<Presence v-model="show" v-slot="{ attrs, done }"> <div v-bind="attrs" class="transition-opacity duration-300" :class="{ 'opacity-0': !isPresent, 'opacity-100': isPresent }" @transitionend="done" > 这个内容会平滑地显示和隐藏 </div> </Presence>Presence的状态管理
Presence提供了以下状态,通过slot props暴露:
- isPresent:内容是否应该显示
- isLeaving:离开过程是否正在进行
- done:通知Presence离开动画已完成的回调函数
- attrs:包含data-state属性的属性对象,可用于CSS选择器
Presence的高级应用
结合CSS过渡,Presence可以创建复杂的动画效果:
<template> <Presence v-model="show" v-slot="{ attrs, isPresent, done }"> <div v-bind="attrs" class="fixed top-4 left-1/2 transform -translate-x-1/2 p-4 bg-green-500 text-white rounded shadow-lg transition-all duration-500" :class="{ 'opacity-0 translate-y-[-20px]': !isPresent, 'opacity-100 translate-y-0': isPresent }" @transitionend="done" > 操作成功! </div> </Presence> </template> <script setup> import { Presence } from '@vuetify/v0' const show = ref(false) // 显示通知 function showNotification() { show.value = true setTimeout(() => show.value = false, 3000) } </script>这个例子创建了一个会从顶部滑入并自动消失的通知组件,过渡动画通过CSS实现,Presence负责管理组件的生命周期。
Presence组件的源代码可以在packages/0/src/components/Presence/Presence.vue找到。
组合使用Atom、Portal和Presence
这三个基础组件可以组合使用,创建出功能强大的UI组件。例如,一个完整的模态框组件:
<template> <Portal :disabled="!show" @close="show = false" v-slot="{ zIndex, close }"> <Presence v-model="show" v-slot="{ attrs: presenceAttrs, done: presenceDone }"> <div v-bind="presenceAttrs" :style="{ zIndex, position: 'fixed', inset: 0 }" > <!-- 背景遮罩 --> <Atom as="div" class="absolute inset-0 bg-black/50 transition-opacity duration-300" :class="{ 'opacity-0': !isPresent, 'opacity-100': isPresent }" @click="close" @transitionend="presenceDone" /> <!-- 模态框内容 --> <Presence v-model="show" v-slot="{ attrs: contentAttrs, done: contentDone }"> <Atom as="div" v-bind="contentAttrs" class="absolute top-1/2 left-1/2 transform transition-all duration-300" :class="{ 'opacity-0 translate-y-[-20px] scale-95': !isPresent, 'opacity-100 translate-y-[-50%] scale-100': isPresent }" @transitionend="contentDone" > <div class="p-6 bg-white rounded-lg shadow-xl"> <h2 class="text-xl font-bold">模态框标题</h2> <p class="mt-2">模态框内容</p> <button class="mt-4 px-4 py-2 bg-blue-500 text-white rounded" @click="close"> 关闭 </button> </div> </Atom> </Presence> </div> </Presence> </Portal> </template> <script setup> import { Atom, Portal, Presence } from '@vuetify/v0' const show = ref(false) </script>在这个例子中:
- Portal确保模态框渲染在body元素中,并管理z-index
- Presence控制背景遮罩和模态框内容的进入/离开动画
- Atom提供多态渲染能力,将组件渲染为适当的HTML元素
通过这种组合,我们创建了一个具有平滑过渡效果、正确层叠顺序的模态框组件。
总结
Atom、Portal和Presence是Vuetify0的三个核心基础组件,它们分别解决了不同的界面构建问题:
- Atom提供了灵活的多态渲染能力,是所有组件的基础
- Portal解决了内容跨DOM树渲染和z-index管理问题
- Presence管理组件的挂载生命周期,支持平滑的动画过渡
这三个组件虽然简单,但它们的组合可以创建出非常复杂和灵活的界面效果。掌握这些基础组件对于使用Vuetify0构建高质量的用户界面至关重要。
无论你是构建简单的UI元素还是复杂的交互组件,Atom、Portal和Presence都将成为你工具箱中不可或缺的工具。通过这些组件,你可以构建出既灵活又具有一致用户体验的应用程序界面。
要开始使用这些组件,你可以通过以下命令克隆仓库:
git clone https://gitcode.com/gh_mirrors/03/0然后参考官方文档和示例代码,开始你的Vuetify0之旅!
【免费下载链接】00️⃣ Composable UI engine for Vue. Build complex interfaces with reusable state, logic, and primitives—without being locked into components or styles.项目地址: https://gitcode.com/gh_mirrors/03/0
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
