一、创建react项目
npm init vite,初始化之后选择需要创建的项目react,JavaScript语言
创建新的页面展示,防止我们的API_KEY被盗刷
当我们在App.jsx里面打印一次我们调用的API_KEY,发现打印了两次。
当我们将main.jsx中将Strictmode删除后就不会出现上述情况了,在React当中,StrictModel react 默认启动的严格模式,执行一次 ,测试一次。
-import.meta.env.VITE_API_KEY 环境变量对象,系统中的全局变量进行添加,代码运行时可以和环境变量交互,把env 写到代码里。
二、准备页面结构
这里使用className,在react底层需要把下述代码运行,会以原生JS运行。因为class是关键词,在这里使用className回避js当中的关键字。
无障碍访问,label htmlFor + input#id,工作原理:
- 在HTML中对应 for 属性,JSX中因 for 是JavaScript关键字,故使用 htmlFor 替代
- 必须与目标 元素的 id 属性值完全匹配(此处需存在 )
- 点击标签文本等价于直接点击关联的输入控件
为了防止连续点击界面出现页面放大和点不动的情况,需要在index.html文件当中添加上user-scalable=no,这样就可以使页面连击点动不会放大了。
三、执行函数
典型执行流程:
- 用户通过文件选择对话框选择图片/文件
- 文件输入框触发change事件,调用 updateBase64Data 函数
- 函数从事件对象中提取第一个选中的文件
- 打印文件信息到控制台(开发调试阶段)
- (通常后续会添加)将文件转换为Base64格式或上传到服务器
技术亮点:
- 采用 HTML5 FileReader API 实现客户端文件处理,无需后端参与
- 使用 readAsDataURL 方法将图片转换为可直接用于 img 标签的 Base64 格式
- 通过 React 状态管理( setImgBase64Data 和 setIsValid )实现视图与数据的响应式更新
- 包含完整的错误处理和边界条件检查
const updateBase64Data = (e) =>{
// 获取用户选择的第一个文件(HTML5 文件交互 API)
const file = e.target.files[0];
// 调试用:打印文件信息(已注释)
// console.log(file);
// 如果没有选择文件,直接返回
if(!file) return;
// 使用 HTML5 FileReader API 读取文件内容
const reader = new FileReader();
// 以 DataURL 格式读取文件(会转换为 Base64 编码)
reader.readAsDataURL(file);
// 文件读取是异步操作,通过 onload 事件处理加载完成后的逻辑
reader.onload = () =>{
// 调试用:打印 Base64 编码结果(已注释)
// console.log(reader.result);
// 将 Base64 数据保存到组件状态
setImgBase64Data(reader.result)
// 将文件验证状态设为有效
setIsValid(true)
}
}
本地预览 preview(良好且必须的用户体验),图片上传及处理挺慢的,所以需要preview
从静态的html -> 动态模板({data}) -> 状态 State useState
当不选中任何文件时,按钮的状态应设置为禁用状态,
// 将按钮的名字取名为isValid
const [isValid,setIsValid] = useState(false)
reader.onload = () =>{
// 调试用:打印 Base64 编码结果(已注释)
// console.log(reader.result);
// 将 Base64 数据保存到组件状态
setImgBase64Data(reader.result)
// 将文件验证状态设为有效,并且将按钮打开
setIsValid(true)
}
<button onClick={update} disabled={!isValid}>提交</button>
当我们重新打开浏览器选择文件的时候就可以发现按钮件已经打开了。
四、async和await使用
async是asynchronous的缩写,需要请求头的地址,生成需要内容的回答。在请求头当中需要我们的APIKEY,并且需要传过来的元素是json。不带上Content-Type的话,服务器端收到字节流的话就不清楚如何处理内容,在服务器端可以通过json来解析。Authorization授权码,专门带上API_KEY,其中Bearer一般都会带有。
const update = async() =>{
if(!imgBase64Data) return;
const endpoint = 'https://api.moonshot.cn/v1/chat/completions';
const headers = {
'Content-Type': 'application/json',
// 授权码 Bearer 一般都会带
'Authorization': `Bearer ${import.meta.env.VITE_API_KEY}`
}
// 实时反馈给用户
setContent('正在生成...')
await 只能在 async 函数内部使用,使用 await 可以让异步代码看起来更像同步代码,提高可读性和可维护性。GET没有请求体,而POST有请求体,且GET直接明文传输的(url)不安全,而POST更加编码。当key和value一样时可以省略,找到月之暗面的模型。
const response = await fetch(
endpoint,
{
method: 'POST',
headers, // es6中 JSON key value 一样可以省略
body: JSON.stringify({
model: 'moonshot-v1-8k-vision-preview',
messages:[
{
role: 'user',
content: [
{
type: "image_url",
image_url:{
"url": imgBase64Data
}
},
{
type: "text",
text: "请详细描述图片"
}
]
}
]
})
}
)
当我们接收到AI大模型传递回来的数据的时候,需要做的是反序列化。从服务端返回来的数据是二进制字节流,json化过程也是异步的,加上await 异步变成同步。
五、效果展示
5.1界面首页
可以看到按钮的提交按钮是关闭的,可以选择Goole本地的文件内容。那就让我们试试从Google本地的浏览器当中使用看看效果吧。
5.2程序使用中
当我们选择自己想要分析的图片并且上传到程序相关内容时,可以发现当时禁用的提交按钮文件现在可以使用了,到这里已经完成了一大步了,我们看看结果如何把!!!
5.3效果结果
可以看到效果展示,大模型帮我们识别图片并生成了相应的文档流事件。这张图片展示了一个乐高风格的咖啡馆场景。画面中有一个可爱的卡通老鼠坐在吧台后面,吧台上放着一杯咖啡。背景中有一个展示咖啡和甜点的菜单板,上面写着“Coffee”和一些饮品的名称。吧台旁边有一个街灯,增添了城市街道的氛围。整个场景色彩丰富,充满了童趣和创意。
六、智能总结
在这边偷个懒,用Tare,AI根据写的笔记流写下文档总结段落。
在 React 图片识别项目开发中,掌握这些核心技术能显著提升代码质量与用户体验:
1.开发规范 :严格模式下组件会执行两次渲染,需避免副作用代码;保持代码精简,及时移除无用逻辑。
2.环境与异步 :通过 import.meta.env 安全访问环境变量;优先使用 async/await 简化异步流程,比 .then() 更具可读性。
3.React 特性 :用 className 替代 class 关键字;结合 label[htmlFor] 与 input[id] 实现无障碍访问。
4.图片处理 :文件上传后通过 FileReader.readAsDataURL() 转换为 Base64 格式,实现本地预览;利用 useState 管理图片状态,确保 UI 实时响应。
这些实践让前端图片处理更流畅,兼顾性能与用户体验,是现代 React 开发的必备技能