网站首页 > 技术文章 正文
前段时间发现一个前端的bug:上传文件需要校验MD5,前端每次上传文件的MD5是不变的。
鉴于最近正在学习如何做前端开发,我自己也去搜搜原因可能出在何处。待确认原因并生成正确MD5后,跟前端小哥的结果一对,发现我的想法是正确的。感觉自己似乎已经知道前端在做什么了,于是起笔总结一下最近一段时间(日期跨度是1个月,有时间时便学一学,攒下来的总时长,大概20多个小时)的学习成果。
这总结,大概分为三个部分:茫茫不知所措、复制粘贴复制粘贴、似乎懂点什么了。且按照这步骤,来记录一下我的学习经历吧。
一、茫茫不知所措
我最初设计后端接口时,会经常想省流量(以前做游戏的习惯)将Dict换成List传递,这被好几位前端小哥抵触,于是便反思自己,我是不是不了解Web开发的规则啊?Web开发不需要考虑数据量大小的?
按照《HTTP: The Definitive Guide》书中所说,应该是需要考虑的,不然不会用缓存、拥塞控制等存在。我的猜测是,对比页面中随随便便一张图的大小,来自于数据格式改变的省流,是微不足道的。传Dict,开发效率是会高一些的。(这一点在很多书中都有体现,不能只顾着效率而不考虑代码可读性。)
最近的一个小项目,正好有机会让我学习一下前端开发。该项目的功能只是在页面填入某几个字段,点一个按钮后向数据库中导入许多数据。
从哪里开始呢?我之前经常听到的名词有React、Vue、NodeJS、npm、Yarn、JQuery……
我先按照React的入门教程抄出来一个井字棋。抄完之后,发现依然不知道怎么开始做我想做的事情,但好歹知道React是什么了:React是一个类似Django的开发框架。
再搜搜看,得知Vue跟React是相似的东西,React做偏大型项目,而Vue做一些小东西。
正好前端小哥有一个小项目是用Vue开发的,我便开始照着抄。抄之前,先用以下指令新建了一个项目:
# 1. 创建项目,统统选了默认值
npm init vue@latest
# 2. 按提示启动项目,启动成功后在浏览器上输入提示链接就好
cd vue-project
npm install
npm run dev
二、复制粘贴复制粘贴
我选取一个页面,照着搬过来,发现事情并不像想象的那样顺利。接着将与这个页面相关的内容统统粘贴过来,依然不行。
原来Vue跟Python一样,如果需要用到某些功能,需要安装一些指定的库。
# 1. Python安装md5库
pip install md5hash
# 2. Vue安装一个md5库
npm install blueimp-md5
等到将所有用到的内容都安装上,一个所改即所得的页面出现在我的面前。接着在后端写了一个接口,用自己写的前端代码去调用这个接口。调用成功的时刻,我感觉自己仿佛变成了一个全栈工程师。
三、似乎懂点什么了
复制粘贴的过程中,我发现Vue项目有这么些规律:
- main.js是整个项目的入口点。
- JavaScript与其它语言一样,需要用的函数、控件,都需要导入才能使用。
- *.Vue文件有3个部分:模板、样式和脚本。模板负责网站页面有什么内容,样式觉得这些内容长什么样子,脚本负责这些内容的交互。
- 要让Vue页面能够展示,需要把它配置到router表里面。
我在原有界面中添加一个按钮,点击按钮选择文件,再打印出文件的MD5。好了,有了重现步骤,便定位到问题出在每次参与计算MD5的值并非文件内容,而只是文件对象。
我这么厉害,这么快定位到问题,让我起了写下本篇博客的心思。想着博客代码好看点,便想着新建一个页面来展示我对前端开发的理解,我新建出来的Vue文件是这样的:
<template>
<div>
<AButton @click="uploadFile">
<UploadOutlined />
上传附件
</AButton>
<input ref="uploadRef" type="file" accept=".xlsx,.docx,.pdf,.png,.zip" style="display: none"
@change="beforeUpload" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { UploadOutlined } from '@ant-design/icons-vue';
import md5 from 'blueimp-md5';
import MD5 from "crypto-js/md5";
const uploadRef = ref();
function uploadFile() {
console.log('----------------> uploadFile', uploadRef.value)
uploadRef.value.click();
}
function beforeUpload() {
const file = uploadRef.value?.files[0];
console.log(file)
console.log('md5:', md5(file));
console.log('MD5:', MD5(file).toString());
var reader = new FileReader();
reader.onload = function (e) {
const contents = e.target.result;
console.log('md5 contents:', md5(contents));
console.log('MD5 contents:', MD5(contents).toString());
};
reader.readAsText(file);
}
</script>
<style scoped lang="scss">
</style>
将按钮展示出来后,点击按钮时,报了以下错误:
runtime-core.esm-bundler.js:218 Uncaught TypeError: Cannot read properties of undefined (reading 'click')
at uploadFile (BeforeInsert.vue:29:21)
at callWithErrorHandling (runtime-core.esm-bundler.js:155:22)
at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:164:21)
at emit$1 (runtime-core.esm-bundler.js:718:9)
at runtime-core.esm-bundler.js:7410:53
at handleClick2 (button.js:102:7)
at callWithErrorHandling (runtime-core.esm-bundler.js:155:22)
at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:164:21)
at HTMLButtonElement.invoker (runtime-dom.esm-bundler.js:339:9)
好吧,这卡住了我总结的流程,卡了很久,为什么呢?为什么呢?
放在另一个页面中就ok,为什么新建一个就不行了呢?搜一搜ref的定义,我猜测可能是我这个界面没有挂载到某个“root”上面,那如何挂载呢?
改改改改改改改,乱乱乱乱乱乱乱乱乱改……
竟让我发现这报错不在这个页面,与另一个页面中的一个AModal组件关联起来。如果加了AModal,就报错,不加,就不报错。为什么会这样子呢?
且先看看茫茫多的“Vue warn”是啥。
[Vue warn]: Unhandled error during execution of watcher callback
请教前端小哥哥,他说他从来没有碰到过,搜索的结果,也对不上。我肯定碰到了一个很小的错误……
我自己断断续续来回尝试过好多次,终于是没搞定的。
回到办公室(之前在家办公自己琢磨),再次请教了前端小哥哥,前端小哥哥打断点追进Vue源码,发现问题出在Vue版本上面。待我将Vue版本从3.2.41改到3.2.43后,该问题不再。
本篇整理,便到此处吧,如何打断点,如何追源码,且后面再说。反正我已经可以调用后端接口,可以看文件的MD5,可以开始我的前端开发了。
4. 引用链接
学习过程中用到的一些网站:
- React的入门教程:https://zh-hans.reactjs.org/tutorial/tutorial.html
- 查看JavaScript语言的API:https://developer.mozilla.org/zh-CN/docs/Web/API/File
- 查看可使用的组件:https://antdv.com/components/select
- 我碰见的bug:https://github.com/vuejs/core/issues/7070
- 上一篇: JS 的 六种打断点的方式,你用过几种?
- 下一篇: 一文搞定Netty断开连接原理
猜你喜欢
- 2024-12-05 从交互的角度讲讲弹窗(下)
- 2024-12-05 如何使用弹框,让它弹得「有理有据」?
- 2024-12-05 7个看不见的设计点,产品经理来瞧瞧
- 2024-12-05 接口常用面试题
- 2024-12-05 像素的一生—浏览器渲染流水线简述
- 2024-12-05 你不知道的浏览器渲染原理(图文并茂,深度解读!)
- 2024-12-05 来自一个搬运工的自述
- 2024-12-05 一文搞定Netty断开连接原理
- 2024-12-05 JS 的 六种打断点的方式,你用过几种?
你 发表评论:
欢迎- 07-07使用AI开发招聘网站(100天AI编程实验)
- 07-07Tailwindcss 入门(tailwindcss中文文档)
- 07-07CSS 单位指南(css计量单位)
- 07-07CSS 定位详解(css定位属性的运用)
- 07-07程序员可以作为终身职业吗?什么情况下程序员会开始考虑转行?
- 07-07云和学员有话说:国企转行前端开发,斩获13K高薪!
- 07-0791年转行前端开发,是不是不该转,有啥风险?
- 07-07计算机图形学:变换矩阵(图形学 矩阵变换)
- 596℃几个Oracle空值处理函数 oracle处理null值的函数
- 588℃Oracle分析函数之Lag和Lead()使用
- 576℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 573℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 569℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 562℃【数据统计分析】详解Oracle分组函数之CUBE
- 549℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 542℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- 前端懒加载 (49)
- 前端获取当前时间 (50)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle的函数 (57)
- 前端调试 (52)
本文暂时没有评论,来添加一个吧(●'◡'●)