现代Web开发的黄金搭档:Vue.js与Tailwind CSS(二)
在现代Web开发的舞台上,Vue.js与Tailwind CSS的搭配可谓是一对黄金搭档。它们分别以响应式和实用主义为核心,共同构建了无数高效、美观的Web应用。今天,我们将深入剖析一个基于这两大法宝的简单应用,探讨其背后的技术细节和设计哲学。
1. Tailwind CSS:简约而不简单
根据上一篇文章介绍,这里直接在 tailwind.css
文件中添加以下配置
@tailwind base;
@tailwind components;
@tailwind utilities;
2. gpt.js:异步API调用
gpt.js
文件中的 chat
函数是一个典型的异步函数,它使用 fetch
API向OpenAI的GPT-3.5 API发送请求。这里展示了如何处理HTTP请求,并在出现错误时进行捕获和日志记录。
export async function chat(messageList, apiKey) {
try {
const result = await fetch('https://api.302.ai/v1/chat/completions', {
method:'post',
headers: {
'Content-Type': "application/json",
// 授权
'Authorization': `Bearer ${apiKey}`
},
body:JSON.stringify({
model: 'gpt-3.5-turbo',
messages:messageList
})
})
const data = await result.json()
return data;
} catch (error) {
console.log(error);
throw(error);
}
}
这段代码定义了一个异步函数chat
,用于向特定的API发送POST请求,该API用于处理与GPT-3.5 Turbo模型的交互。以下是该代码的关键知识点分析:
-
异步函数 (
async function
): 函数前的async
关键字表明这是一个异步函数,它可以返回一个Promise,并允许使用await
关键字来等待异步操作的结果。 -
Fetch API:
fetch
函数是现代浏览器中用于发起网络请求的标准API。在这里,它被用来向https://api.302.ai/v1/chat/completions
这个URL发送一个POST请求。 -
请求选项 (
options object
):fetch
函数的第二个参数是一个对象,用于配置请求的详细信息:-
method: 'post'
:指定请求方法为POST。 -
headers
:一个对象,描述了请求头。这里是Content-Type
和Authorization
头:'Content-Type': "application/json"
:表明请求体是一个JSON格式的数据。'Authorization':
Bearer ${apiKey}'
:包含API密钥,用于授权请求。
-
body
:请求体,这里使用JSON.stringify
将JavaScript对象转换为JSON字符串。
-
-
结果处理:
await result.json()
:从响应中读取JSON数据。result
是fetch
返回的Promise的结果,它包含服务器的响应。json()
方法返回另一个Promise,解析响应体为JSON格式。
-
Try-Catch语句:
- 使用
try-catch
结构来捕获和处理fetch
操作中可能出现的错误。这是处理异步操作错误的一种标准方式。
- 使用
-
错误日志和抛出:
console.log(error);
:将错误信息输出到控制台,有助于调试。throw(error);
:重新抛出捕获的错误,这样调用者可以进一步处理或捕获这个错误。
总结:
这段代码展示了如何使用Fetch API向API服务发送POST请求,处理响应和错误的基本流程。它结合了异步编程的最佳实践,如使用async/await
和try-catch
,以及正确的网络请求格式和错误处理机制。在实际应用中,这种模式常用于与后端服务或外部API进行交互。
3. index.js:路由配置
index.js
文件是Vue应用的入口,这里我们使用 vue-router
创建了路由实例,并导出这个路由配置。这使得Vue应用能够处理客户端的导航请求,将用户引导到对应的视图组件。
import { createRouter, createWebHistory } from 'vue-router'
// ...Router configuration
export default router
4. Home.vue:交互的界面
Home.vue
组件是应用的交互中心,它使用Vue的响应式系统和生命周期钩子来实现动态数据绑定和处理用户输入。此外,它还利用了Tailwind CSS提供的类式样式,实现了丰富的视觉效果。
<template>
<!-- h-screen:100vh -->
<!-- http://localhost:5173/ -->
<div class="flex flex-col h-screen">
<div class="flex flex-nowrap fixed w-full items-baseline
top-0 px-6 py-4 bg-gray-100">
<div class="text-2xl font-bold">ChatGPT</div>
<div class="ml-4 text-sm text-gray-500">
人工智能对话
</div>
<div class="ml-auto px-3 py-2 text-sm cursor-pointer hover:bg-white rounded-md">
设置
</div>
<div class="flex-1"></div>
<div class="sticky bottom-0 w-full p-6 pb-8 bg-gray-100">
<div v-if="isConfig" class='mb-2 text-sm text-gray-500'>
请输入 API key:
</div>
<div class="flex">
<input class="input" :type="isConfig ? 'password' : 'text'"
:placehold="isConfig ? 'sk-xxxxxx' : '请输入'" v-model="messageContent"
@keydown.enter="sendOrSave()" />
<button @click="sendOrSave()" class="btn">{{ isConfig ? '保存' : '发送' }}</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { chat } from '../libs/gpt'
let messageContent = ref("")
let isConfig = ref(true) // 是否显示设置
const clickConfig = () => {
// 当前不是配置状态
if (!isConfig.value) {
messageContent.value = getAPIKey()
} else {
clearMessageContent();
}
switchConfigStatus();
}
const getAPIKey = () => {
return localStorage.getItem('apiKey');
}
const clearMessageContent = () => {
messageContent.value = "";
}
const sendOrSave = () => {
if (!messageContent.value.length) return;
if (isConfig.value) {
if (savaAPIKey(messageContent.value.trim()))
switchConfigStatus();
messageContent.value = "";
}
else {
// 发送openai
sendChatMessage()
}
}
const sendChatMessage = async () => {
const apiKey = getAPIKey();
const messageList = [{
role: 'system',
content: '你是一个AI智能助手,你帮助用户解决各种问题'
},
{
role: 'user',
content: messageContent.value
}]
const data = await chat(messageList, apiKey)
console.log(data);
}
const savaAPIKey = (apiKey) => {
localStorage.setItem('apiKey', apiKey)
return true
}
const switchConfigStatus = () => {
isConfig.value = !isConfig.value
}
</script>
<style></style>
这段代码展示了Vue 3中使用组合式API和<script setup>
语法糖编写组件的方法,包括动态属性绑定、条件渲染、响应式数据和事件处理。同时,使用了大量的Tailwind CSS的实用类快速构建布局和样式,提高了开发效率。例如:
flex-col
: 子元素按列方向排列
h-screen
: 让容器高度占据整个屏幕的高度,适合构建全屏应用
w-full
: 使其宽度占满屏幕
items-baseline
: 对齐子元素的基线
px-6 py-4
: 设置内外边距
另外,代码的 20-22 行中,:type
、:placeholder
和v-model
使用动态绑定,根据isConfig
的值改变输入框的类型和提示文字。v-model
实现了双向数据绑定,@keydown.enter
监听回车键事件。
(1)clickConfig
- 功能:处理点击配置按钮的行为。如果应用当前不在配置状态,则从本地存储中获取API Key并将其设置为
messageContent
的值。如果在配置状态,则清空messageContent
,并切换配置状态。 - 调用时机:当用户点击配置按钮时会被调用。
(2)getAPIKey
- 功能:从本地存储中获取API Key。
- 调用时机:当需要从本地存储中读取API Key时调用。
(3)clearMessageContent
- 功能:清空
messageContent
的值。 - 调用时机:在
clickConfig
函数中,当从配置状态切换回来时调用。
(4)sendOrSave
- 功能:根据当前状态(配置或聊天)处理用户输入。如果是配置状态,保存API Key到本地存储,切换状态,并清空输入。如果不是配置状态,则发送消息到AI服务。
- 调用时机:当用户在输入框中按下Enter键或点击发送按钮时调用。
(5)sendChatMessage
- 功能:异步发送消息到AI服务。首先获取API Key,然后准备消息列表(包括系统预设和用户输入),调用
chat
函数发送请求,最后打印返回的数据。 - 调用时机:在
sendOrSave
函数中,当用户在聊天状态下发送消息时调用。
(6)savaAPIKey
- 功能:保存API Key到本地存储。
- 调用时机:在
sendOrSave
函数中,当用户在配置状态下输入API Key并按下Enter键时调用。
(7)switchConfigStatus
- 功能:切换
isConfig
的状态,即切换应用是否处于配置状态。 - 调用时机:在
clickConfig
和sendOrSave
函数中调用,用于切换配置状态。
总结:
这段代码实现了用户与AI聊天应用交互的基本逻辑,包括输入处理、状态管理、与后端服务的通信,以及配置管理。通过Vue的响应式系统,messageContent
和isConfig
的状态变化能够及时反映到UI上,提供流畅的用户体验。
5. App.vue:路由的出口
App.vue
组件作为Vue应用的根组件,它使用 router-view
插槽来渲染当前路由对应的组件。这使得路由系统能够无缝地融入Vue应用的组件结构中。
<script setup>
//GPT 代表整个模块的默认输入
import { chat } from '.libs/gpt.js'
const main = async () => {
};
main();
</script>
<template>
<div class="flex">
<router-view/>
</div>
</template>
<style scoped>
<style>
<router-view/>
是Vue Router提供的组件,用于渲染当前激活的路由视图。这意味着在这个<div>
容器中,将会显示根据当前URL所匹配到的组件。
6. index.html
这段代码是一个基本的HTML文档结构,用于承载一个使用Vite和Vue.js构建的前端应用。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
6. main.js:应用的启动
main.js
是Vue应用的启动文件,它初始化一个Vue应用实例,配置其根组件和路由。导入并应用Tailwind CSS样式。将应用挂载到DOM中,启动应用的生命周期。
import { createApp } from 'vue'
import './assets/tailwind.css'
import App from './App.vue'
import router from './routes/index'
const app = createApp(App)
app
.use(router)
.mount('#app')
(1)createApp
是Vue 3中用于创建应用实例的主要函数,它替代了Vue 2中的new Vue({})
构造函数。createApp
函数返回一个应用实例,可以配置和使用插件。
(2) 最后三行代码完成了应用的配置和挂载:
app.use(router)
:将Vue Router实例注册为应用的插件。一旦注册,router
就成为了全局可用的对象,可以被应用中的任何组件访问和使用。app.mount('#app')
:将应用实例挂载到index.html
文件中<div id="app">
的DOM元素上。挂载后,Vue应用将接管该元素,并根据App
组件的模板渲染内容。
7. tailwind.config.js:自定义Tailwind
tailwind.config.js
文件配置了Tailwind CSS的入口文件和主题扩展,使其能够适用于我们的项目。(详细解释见上篇文章)
export default {
content: [
"./index.html",
".src/**/*.{vue,js,ts,jsx,tsx}"
],
theme: {
extend: {},
},
plugins: [],
}
8. 结果展示
在输入框中输入正确的API key,点击保存,如果API key 值正确,即可将该值保存在 local storage 中。后续还会根据这两篇文章添加功能,使其达到 OpenAI 的聊天效果。
综上所述,这个简单的Vue应用展现了现代Web开发的几个重要方面:组件化架构、异步编程、响应式设计等。而Tailwind CSS的加入,更让这个应用在实用性和美观性之间找到了完美的平衡。希望通过对这个应用的分析,你能对Vue和Tailwind CSS有更深入的理解和灵感。