文章目录
前言
DevUI是华为开源的企业级设计系统,专为中后台产品打造。本文通过构建一个完整的AI助手对话应用,深入讲解DevUI的核心组件、主题系统和最佳实践。我们将结合MateChat(一个专为AI场景优化的前端组件库)来展示DevUI在现代Web应用中的实际应用价值。

第一步:DevUI项目初始化与主题系统配置
核心初始化代码解析
typescript
import { createApp } from 'vue'
import App from './App.vue'
import DevUI from 'vue-devui'
import 'vue-devui/style.css'
import '@devui-design/icons/icomoon/devui-icon.css'
import { ThemeServiceInit, infinityTheme } from 'devui-theme'
// 初始化DevUI主题系统
ThemeServiceInit({ infinityTheme }, 'infinityTheme')
const app = createApp(App)
app.use(DevUI)
app.mount('#app')
首先通过ThemeServiceInit初始化了DevUI的主题系统,使用了infinityTheme 这个现代化的设计主题,它提供了一套完整的色彩体系、排版规范和组件样式。其次通过app.use(DevUI)注册了DevUI插件,这样就能在全局范围内使用d-button、d-input等所有DevUI组件,无需逐个导入。最后导入了样式文件和图标库,确保组件的视觉效果和icon功能完整可用。

DevUI的主题系统基于设计令牌(Design Tokens)的概念,通过修改主题变量就能快速改变整个应用的视觉风格,而无需修改任何组件代码。这对于需要适配不同客户品牌色或支持深色模式的项目特别有价值。

第二步:搭建聊天界面布局
整体结构设计
我们的案例应用采用了经典的聊天应用布局:顶部是标题栏、中间是消息展示区、底部是输入框。这个结构在各种对话应用中都很常见,包括MateChat在内的专业AI对话库也遵循类似的布局模式。
javascript
<template>
<div class="chat-container">
<!-- 顶部标题栏 -->
<div class="chat-header">
<h1>DevUI AI Assistant</h1>
<p>Powered by DevUI & MateChat</p>
</div>
<!-- 消息展示区 -->
<div class="chat-messages" ref="messagesContainer">
<!-- 消息列表渲染 -->
</div>
<!-- 输入区域 -->
<div class="chat-input-area">
<!-- DevUI输入组件 -->
</div>
</div>
</template>
第三步:使用DevUI的d-input和d-button组件
输入框组件详解
javascript
<div class="chat-input-area">
<d-input
v-model="inputValue"
placeholder="输入你的问题..."
@keyup.enter="sendMessage"
>
</d-input>
<d-button
@click="sendMessage"
kind="primary"
:disabled="!inputValue.trim()"
>
发送
</d-button>
</div>
这段代码展示了DevUI两个最基础但最常用的组件。d-input 是一个增强的输入框组件,相比原生的input标签,它提供了清晰的焦点状态反馈、内置的禁用状态样式、验证反馈的支持、以及与DevUI主题系统的完美集成。我们通过v-model进行双向数据绑定,通过@keyup.enter事件监听实现回车发送的常见交互。
d-button 组件则提供了多种预设样式。其中kind="primary"表示这是一个强调按钮,适合作为主要操作。disabled属性的动态绑定保证了只有在用户有实际输入内容时才能点击发送,这是一个简单但重要的用户体验优化------避免用户误点发送空消息。

为什么不用原生HTML?
DevUI组件相比原生HTML元素的优势在于:首先提供了企业级的样式一致性,确保在不同浏览器和设备上的表现统一;其次内置了常见的交互功能,如清空按钮、验证提示等,无需额外开发;最后与整个DevUI设计系统深度融合,修改主题后所有使用DevUI组件的地方都会自动适应新的风格。
第四步:消息列表的动态渲染
消息数据结构设计
typescript
interface Message {
from: 'user' | 'assistant'
content: string
loading?: boolean
}
const messages = ref<Message[]>([])
为了区分用户消息和助手消息,我们定义了一个清晰的接口。from字段表示消息来源,content存储消息内容,loading字段用于显示打字动画,这个设计参考了MateChat对话库的最佳实践。
条件渲染与样式差异
javascript
<div class="chat-messages" ref="messagesContainer">
<div
v-for="(msg, idx) in messages"
:key="idx"
:class="['message', msg.from === 'user' ? 'user-msg' : 'assistant-msg']"
>
<div class="avatar">
{{ msg.from === 'user' ? 'You' : 'AI' }}
</div>
<div class="content">
{{ msg.content }}
<span v-if="msg.loading" class="loading">●●●</span>
</div>
</div>
</div>
这里我们使用了Vue 3的v-for指令循环渲染消息列表,通过动态的class绑定实现了用户消息和助手消息的不同样式。特别地,我们添加了msg.loading判断来在消息还在生成时显示加载动画。这种设计能让用户清楚地感知到AI正在思考,避免了"为什么没有响应"的困惑。

自动滚动到底部
typescript
const scrollToBottom = () => {
if (messagesContainer.value) {
messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight
}
}
当新消息到来时,我们需要自动将视图滚动到最新的消息。通过在发送消息和接收消息时都调用这个函数,确保用户始终能看到最新的对话内容,这在长对话中特别重要。

第五步:核心业务逻辑------消息发送与接收
发送消息的完整流程
typescript
const sendMessage = async () => {
if (!inputValue.value.trim()) return
// 添加用户消息
messages.value.push({
from: 'user',
content: inputValue.value
})
const userInput = inputValue.value
inputValue.value = ''
// 添加AI消息占位符
messages.value.push({
from: 'assistant',
content: '',
loading: true
})
await nextTick()
scrollToBottom()
// 模拟AI响应
setTimeout(() => {
const lastMsg = messages.value[messages.value.length - 1]
lastMsg.content = `您说:${userInput}。这是一个DevUI演示应用,已成功集成MateChat对话组件库。`
lastMsg.loading = false
scrollToBottom()
}, 800)
}
这个函数实现了一个完整的消息交互流程。首先验证输入不为空,然后立即将用户消息添加到列表中显示,这给用户即时反馈。接着清空输入框,添加一条带有loading状态的AI消息占位符。使用nextTick()确保DOM已更新后再滚动,这是Vue 3异步更新的最佳实践。最后通过setTimeout模拟网络延迟,演示AI正在思考的过程。
第六步:样式设计------如何用CSS实现现代化UI
渐变背景与卡片设计
css
.chat-container {
display: flex;
flex-direction: column;
height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
我们使用了现代的渐变背景,配合紫蓝色系,营造出专业的AI助手应用氛围。这种配色方案在当下的SaaS应用中很流行,特别是在AI相关的产品中。

消息气泡的左右对齐
css
.message {
display: flex;
gap: 10px;
animation: slideIn 0.3s ease-out;
}
.message.user-msg {
justify-content: flex-end;
}
.user-msg .content {
background: #667eea;
color: white;
border-bottom-right-radius: 2px;
}
.assistant-msg .content {
background: white;
color: #333;
border-bottom-left-radius: 2px;
}
这里我们用Flexbox实现了经典的聊天气泡对齐。用户消息靠右(justify-content: flex-end),助手消息靠左(默认)。通过不同的背景色和文字色区分两者,用户消息用渐变色的主色调,助手消息用白底。特别的是,我们在消息气泡的一个角落减小圆角(border-bottom-right-radius: 2px),这样可以指向头像,增强了气泡的指向性。

加载动画效果
css
.loading {
display: inline-block;
animation: blink 1s infinite;
}
@keyframes blink {
0%, 49% {
opacity: 1;
}
50%, 100% {
opacity: 0.3;
}
}
三个圆点的闪烁动画是经典的加载视觉反馈。通过控制opacity而不是display,确保了平滑的动画效果,不会有闪烁导致的性能问题。
整体效果

完整代码
如下是完整代码。
main.js
javascript
import { createApp } from 'vue'
import App from './App.vue'
import DevUI from 'vue-devui'
import 'vue-devui/style.css'
import '@devui-design/icons/icomoon/devui-icon.css'
import { ThemeServiceInit, infinityTheme } from 'devui-theme'
ThemeServiceInit({ infinityTheme }, 'infinityTheme')
const app = createApp(App)
app.use(DevUI)
app.mount('#app')
package.json
javascript
{
"name": "devui-chat-demo",
"private": true,
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.3.0",
"vue-devui": "^1.9.0",
"@devui-design/icons": "^1.1.2",
"devui-theme": "^0.4.8"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.2.0",
"typescript": "^5.0.0",
"vite": "^4.3.0",
"vue-tsc": "^1.6.0"
}
}
APP.vue
javascript
<template>
<div class="chat-container">
<div class="chat-header">
<h1>DevUI AI Assistant</h1>
<p>Powered by DevUI & MateChat</p>
</div>
<div class="chat-messages" ref="messagesContainer">
<div
v-for="(msg, idx) in messages"
:key="idx"
:class="['message', msg.from === 'user' ? 'user-msg' : 'assistant-msg']"
>
<div class="avatar">
{{ msg.from === 'user' ? 'You' : 'AI' }}
</div>
<div class="content">
{{ msg.content }}
<span v-if="msg.loading" class="loading">●●●</span>
</div>
</div>
</div>
<div class="chat-input-area">
<d-input
v-model="inputValue"
placeholder="输入你的问题..."
@keyup.enter="sendMessage"
/>
<d-button
@click="sendMessage"
kind="primary"
:disabled="!inputValue.trim()"
>
发送
</d-button>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, nextTick } from 'vue'
interface Message {
from: 'user' | 'assistant'
content: string
loading?: boolean
}
const inputValue = ref('')
const messages = ref<Message[]>([])
const messagesContainer = ref<HTMLElement>()
const sendMessage = async () => {
if (!inputValue.value.trim()) return
// 添加用户消息
messages.value.push({
from: 'user',
content: inputValue.value
})
const userInput = inputValue.value
inputValue.value = ''
// 添加AI消息占位符
messages.value.push({
from: 'assistant',
content: '',
loading: true
})
await nextTick()
scrollToBottom()
// 模拟AI响应
setTimeout(() => {
const lastMsg = messages.value[messages.value.length - 1]
lastMsg.content = `您说:${userInput}。这是一个DevUI演示应用,已成功集成MateChat对话组件库。`
lastMsg.loading = false
scrollToBottom()
}, 800)
}
const scrollToBottom = () => {
if (messagesContainer.value) {
messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight
}
}
</script>
<style scoped>
.chat-container {
display: flex;
flex-direction: column;
height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.chat-header {
padding: 20px;
color: white;
text-align: center;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.chat-header h1 {
margin: 0 0 10px 0;
font-size: 28px;
}
.chat-header p {
margin: 0;
opacity: 0.9;
font-size: 14px;
}
.chat-messages {
flex: 1;
overflow-y: auto;
padding: 20px;
display: flex;
flex-direction: column;
gap: 12px;
}
.message {
display: flex;
gap: 10px;
animation: slideIn 0.3s ease-out;
}
.message.user-msg {
justify-content: flex-end;
}
.avatar {
width: 36px;
height: 36px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: bold;
color: white;
flex-shrink: 0;
}
.user-msg .avatar {
background: #667eea;
order: 2;
}
.assistant-msg .avatar {
background: #764ba2;
}
.content {
max-width: 60%;
padding: 12px 16px;
border-radius: 8px;
line-height: 1.5;
word-break: break-word;
font-size: 14px;
}
.user-msg .content {
background: #667eea;
color: white;
border-bottom-right-radius: 2px;
}
.assistant-msg .content {
background: white;
color: #333;
border-bottom-left-radius: 2px;
}
.loading {
display: inline-block;
animation: blink 1s infinite;
}
.chat-input-area {
padding: 20px;
background: white;
display: flex;
gap: 10px;
border-top: 1px solid #e0e0e0;
}
:deep(.devui-input) {
flex: 1;
}
:deep(.devui-input input) {
width: 100%;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes blink {
0%, 49% {
opacity: 1;
}
50%, 100% {
opacity: 0.3;
}
}
</style>
总结
这个例子虽然只有一个简单的对话功能,但背后展示的架构思想和最佳实践,完全可以扩展到复杂的企业级应用。无论是数据表格、表单验证、还是复杂的数据展示,DevUI都提供了相应的组件和系统支持。
想要深入学习,可以访问DevUI官网了解完整的组件库,看看如何在AI场景下最大化利用这些组件。现在就开始你的DevUI之旅吧!
相关资源链接:
- DevUI官网: https://devui.design/home
- MateChat官网: https://matechat.gitcode.com
- MateChat代码仓库: https://gitcode.com/DevCloudFE/MateChat
