xzx-chat-kit-vue2
v0.1.7
Published
Vue chat kit component for VUE 2
Maintainers
Readme
xzx-chat-kit
一个跨前端框架的聊天组件库,支持 Vue 2、Vue 3 和 React。
特性
- 🚀 支持 Vue 2.6+ 和 Vue 3
- ⚛️ 支持 React 16.8+
- 📦 使用 TypeScript 编写
- 🎯 零依赖核心库
- 🔧 使用 vue-demi 实现 Vue 版本兼容
- 🎨 样式文件可独立导入
- 🎯 支持自定义插槽
- 💫 支持消息状态管理
- 🎨 支持主题定制
- ⌨️ 内置打字机效果
- 🗑️ 支持消息删除和清空
安装
npm install xzx-chat-kit
# 或
pnpm add xzx-chat-kit
# 或
yarn add xzx-chat-kitVue 2 额外依赖
如果你使用 Vue 2,还需要安装 @vue/composition-api:
npm install @vue/composition-api使用方法
自动导入样式
组件会自动导入所需的样式,无需手动导入。
手动导入样式
如果您希望手动控制样式导入,可以单独导入:
// 导入样式文件
import 'xzx-chat-kit/styles'
// 或
import 'xzx-chat-kit/dist/styles/index.css'Vue 3
<template>
<div>
<ChatBox :chat-core="chatCore">
<!-- 自定义开始区域 -->
<template #start-here>
<div class="start-message">
<span>👋 开始愉快的聊天吧!</span>
</div>
</template>
<!-- 自定义空状态 -->
<template #empty>
<div class="custom-empty-state">
<p>还没有消息哦,快来开始聊天吧!</p>
</div>
</template>
<!-- 自定义消息内容 -->
<template #message="{ content, component, componentProps }">
<span v-if="content?.message || content">{{
content?.message || content
}}</span>
<component v-if="component" :is="component" v-bind="componentProps" />
</template>
<!-- 自定义输入框 -->
<template #input="{ value, onInput, onSend, placeholder }">
<div class="custom-input-wrapper">
<textarea
:value="value"
@input="(e) => onInput(e.target.value)"
:placeholder="placeholder"
@keyup.enter.ctrl="onSend" />
<button @click="onSend">发送</button>
</div>
</template>
</ChatBox>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ChatBox } from 'xzx-chat-kit/vue'
import { ChatCore, typewriterEffect } from 'xzx-chat-kit'
const messages = ref([])
// 创建 ChatCore 实例
const chatCore = new ChatCore({
currentUser: 'user',
placeholder: '请输入您的消息...',
showAvatar: true,
messages: messages.value,
onSendMessage: async (message, history) => {
console.log('发送消息:', message)
console.log('历史记录:', history)
// 模拟机器人回复
await simulateBot(message)
}
})
// 使用打字机效果模拟机器人回复
const simulateBot = async (userMessage) => {
const messageContent = ref('')
// 添加空消息
chatCore.addMessage({
id: Date.now(),
content: messageContent,
sender: 'bot',
timestamp: Date.now(),
type: 'text'
})
// 使用打字机效果
await typewriterEffect(`你说: ${userMessage}`, messageContent, {
speed: 50,
delay: 500
})
}
</script>Vue 2
<template>
<div>
<ChatBox :chat-core="chatCore">
<template #start-here>
<div class="start-message">
<span>👋 开始愉快的聊天吧!</span>
</div>
</template>
<template #empty>
<div class="custom-empty-state">
<p>还没有消息哦,快来开始聊天吧!</p>
</div>
</template>
<template #message="{ content, component, componentProps }">
<span v-if="content.message || content">{{
content.message || content
}}</span>
<component v-if="component" :is="component" v-bind="componentProps" />
</template>
</ChatBox>
</div>
</template>
<script>
import { ref } from 'vue-demi'
import { ChatBox } from 'xzx-chat-kit/vue'
import { ChatCore, typewriterEffect } from 'xzx-chat-kit'
export default {
components: {
ChatBox
},
data() {
const messages = ref([])
return {
chatCore: new ChatCore({
currentUser: 'user',
placeholder: '请输入您的消息...',
showAvatar: true,
messages: messages.value,
onSendMessage: async (message, history) => {
console.log('发送消息:', message)
console.log('历史记录:', history)
// 模拟机器人回复
await this.simulateBot(message)
}
})
}
},
methods: {
async simulateBot(userMessage) {
const messageContent = ref('')
this.chatCore.addMessage({
id: Date.now(),
content: messageContent,
sender: 'bot',
timestamp: Date.now(),
type: 'text'
})
await typewriterEffect(`你说: ${userMessage}`, messageContent, {
speed: 50,
delay: 500
})
}
}
}
</script>React
import React, { useRef, useState } from 'react'
import { ChatBox } from 'xzx-chat-kit/react'
import { ChatCore, typewriterEffect } from 'xzx-chat-kit'
function App() {
const [messages] = useState([])
const chatCoreRef = useRef(null)
// 创建 ChatCore 实例
if (!chatCoreRef.current) {
chatCoreRef.current = new ChatCore({
currentUser: 'user',
placeholder: '请输入您的消息...',
showAvatar: true,
messages: messages,
onSendMessage: async (message, history) => {
console.log('发送消息:', message)
console.log('历史记录:', history)
// 模拟机器人回复
await simulateBot(message)
}
})
}
// 使用打字机效果模拟机器人回复
const simulateBot = async (userMessage) => {
const messageContent = { value: '' }
chatCoreRef.current.addMessage({
id: Date.now(),
content: messageContent,
sender: 'bot',
timestamp: Date.now(),
type: 'text'
})
// 模拟打字机效果(React 版本需要手动实现响应式更新)
const text = `你说: ${userMessage}`
let index = 0
const typeInterval = setInterval(() => {
messageContent.value = text.slice(0, index + 1)
index++
if (index >= text.length) {
clearInterval(typeInterval)
}
}, 50)
}
return (
<div>
<ChatBox
chatCore={chatCoreRef.current}
startHereSlot={
<div className="start-message">
<span>👋 开始愉快的聊天吧!</span>
</div>
}
emptySlot={
<div className="custom-empty-state">
<p>还没有消息哦,快来开始聊天吧!</p>
</div>
}
messageSlot={({ content, component, componentProps }) => (
<>
{content ? <span>{content}</span> : null}
{component && <component {...componentProps} />}
</>
)}
inputSlot={({ value, onChange, onSend, placeholder }) => (
<div className="custom-input-wrapper">
<textarea
value={value}
onChange={onChange}
placeholder={placeholder}
onKeyUp={(e) => e.ctrlKey && e.key === 'Enter' && onSend()}
/>
<button onClick={onSend}>发送</button>
</div>
)}
/>
</div>
)
}
export default App作为插件使用
// Vue 3
import { createApp } from 'vue'
import XzxChatKit from 'xzx-chat-kit/vue'
import App from './App.vue'
const app = createApp(App)
app.use(XzxChatKit)
app.mount('#app')
// Vue 2
import Vue from 'vue'
import XzxChatKit from 'xzx-chat-kit/vue'
import App from './App.vue'
Vue.use(XzxChatKit)
new Vue({
render: (h) => h(App)
}).$mount('#app')
// 使用时仍需要创建 ChatCore 实例
// <template>
// <ChatBox :chat-core="chatCore" />
// </template>插槽
组件提供了以下插槽用于自定义内容:
start-here
在消息列表顶部显示的内容,通常用于显示开始聊天的提示或欢迎信息。
<template>
<ChatBox :chat-core="chatCore">
<template #start-here>
<div class="welcome-message">
<h3>👋 欢迎使用聊天助手</h3>
<p>点击下方按钮开始对话</p>
<button @click="startChat">开始聊天</button>
</div>
</template>
</ChatBox>
</template>empty
当消息列表为空时显示的内容。
message
自定义消息内容的渲染方式。
input
自定义输入框区域的渲染方式。
样式定制
所有的 CSS 类都以 ck- 前缀命名,您可以通过覆盖这些类来自定义样式:
/* 自定义容器样式 */
.ck-chat-box {
background: #f0f0f0;
border-radius: 12px;
}
/* 自定义按钮样式 */
.ck-send-button {
background: #666666;
}
.ck-send-button:hover {
background: #808080;
}CSS 变量
组件使用 CSS 变量来管理主题,您可以通过覆盖这些变量来自定义主题:
:root {
/* 主题色 */
--ck-primary-color: #666666;
--ck-primary-hover: #808080;
--ck-primary-active: #4d4d4d;
/* 背景色 */
--ck-bg-color: #ffffff;
--ck-bg-hover: #f5f5f5;
--ck-bg-active: #e6e6e6;
/* 文字颜色 */
--ck-text-color: #666666;
--ck-text-secondary: #808080;
--ck-text-disabled: #999999;
/* 边框颜色 */
--ck-border-color: #e6e6e6;
--ck-border-hover: #d9d9d9;
/* 消息气泡颜色 */
--ck-message-bg: #f5f5f5;
--ck-message-user-bg: #e6e6e6;
--ck-message-text: #666666;
}API 文档
ChatCore
聊天组件的核心数据管理类。
构造函数
const chatCore = new ChatCore(options)方法
| 方法 | 参数 | 返回值 | 描述 |
| ------------------------------------- | ----------------------------------- | ----------- | ---------------- |
| getState() | - | ChatState | 获取当前状态 |
| getMessages() | - | Message[] | 获取消息列表 |
| addMessage(message) | Message | void | 添加消息 |
| sendMessage(content) | string | void | 发送消息 |
| updateMessageStatus(id, status) | string \| number, MessageStatus | void | 更新消息状态 |
| clearMessages() | - | void | 清空所有消息 |
| deleteMessage(id) | string \| number | boolean | 删除指定消息 |
| setMessagesChangeCallback(callback) | (messages: Message[]) => void | void | 设置消息变化回调 |
ChatOptions
| 属性 | 类型 | 默认值 | 描述 |
| ----------------------- | -------------------------------------------------------------- | ----------------- | -------------------------- |
| currentUser | string | 'user' | 当前用户标识 |
| messages | Message[] | [] | 初始消息列表 |
| placeholder | string | '请输入消息...' | 输入框占位符 |
| showAvatar | boolean | true | 是否显示头像 |
| onSendMessage | (message: string, history: ChatHistoryItem[]) => void | - | 发送消息回调,包含历史记录 |
| onMessageStatusChange | (messageId: string \| number, status: MessageStatus) => void | - | 消息状态变化回调 |
ChatHistoryItem
聊天历史记录项,用于 onSendMessage 回调的第二个参数。
| 属性 | 类型 | 描述 |
| ----------- | --------- | ------------ |
| message | any | 消息内容 |
| isUser | boolean | 是否用户消息 |
| timestamp | number | 时间戳 |
Message
| 属性 | 类型 | 描述 |
| ---------------- | -------------------------------------------- | ---------------------- |
| id | string \| number | 消息唯一标识 |
| content | string \| Ref<string> | 消息内容(支持响应式) |
| sender | string | 发送者 |
| isUser | boolean | 是否为用户消息 |
| timestamp | number | 发送时间戳 |
| type | 'text' \| 'image' \| 'file' \| 'component' | 消息类型 |
| status | 'sending' \| 'sent' \| 'read' \| 'failed' | 消息状态 |
| avatar | string | 头像 URL |
| component | Component | 自定义组件 |
| componentProps | any | 组件属性 |
版本兼容性
| 框架 | 版本要求 | | ----- | --------- | | Vue 2 | >= 2.6.0 | | Vue 3 | >= 3.0.0 | | React | >= 16.8.0 |
开发
# 安装依赖
pnpm install
# 构建
pnpm build
# 构建单独的包
pnpm build:core # 核心库
pnpm build:vue # Vue 组件 (支持 Vue 2 & 3)
pnpm build:react # React 组件
pnpm build:styles # 复制样式文件打字机效果
组件库内置了打字机效果功能,可以让文本逐字显示。
基本用法
import { typewriterEffect, createTypewriter } from 'xzx-chat-kit'
import { ref } from 'vue' // 或 'vue-demi'
// 方式1: 简单的 Promise 方式
const messageContent = ref('')
await typewriterEffect('Hello, World!', messageContent, {
speed: 50, // 每个字符显示间隔(毫秒)
delay: 500, // 开始前延迟(毫秒)
onProgress: (currentText, progress) => {
console.log(`进度: ${Math.round(progress * 100)}%`)
},
onComplete: () => {
console.log('打字完成!')
}
})
// 方式2: 更强的控制方式
const { displayText, controller } = createTypewriter('Hello, World!', {
speed: 50,
delay: 500
})
// 控制打字机
controller.start() // 开始
controller.pause() // 暂停
controller.resume() // 继续
controller.stop() // 停止
controller.reset() // 重置
// 检查状态
console.log(controller.isRunning()) // 是否正在运行
console.log(controller.isPaused()) // 是否已暂停配置选项
| 选项 | 类型 | 默认值 | 描述 |
| ------------ | ------------------------------------------ | ------ | -------------- |
| speed | number | 50 | 每字符间隔(ms) |
| delay | number | 0 | 开始前延迟(ms) |
| onProgress | (text: string, progress: number) => void | - | 进度回调 |
| onComplete | () => void | - | 完成回调 |
许可证
MIT
