最后
本人分享一下这次字节跳动、美团、头条等大厂的面试真题涉及到的知识点,以及我个人的学习方法、学习路线等,当然也整理了一些学习文档资料出来是给大家的。知识点涉及比较全面,包括但不限于前端基础,HTML,CSS,JavaScript,Vue,ES6,HTTP,浏览器,算法等等
前端视频资料:
开源项目
项目最新进展(2023年12月1日):
Vue2版本代码全面同步Vue3所有特性,支持vite快速开发,bug修复和功能整合
全版本正式发布中央仓库,搜索 @flyfish-group/file-viewer,基于Apache2.0协议免费供大家使用
新增支持 xls,xlsm, xlsb, csv, ods, fods, numbers 等表格格式。
中央仓库直达:@flyfish-group - npm search
Vue2版本组件仓库直达:@flyfish-group/file-viewer - npm
项目进展(2023年4月10日):
1. Vue3版本重构了Xlsx模块,使用Worker加载,增加了体验性,能够秒级打开千万行的Excel
2. 增加了Markdown文档的渲染,能够美观的渲染md文档,使用了github风格
- 新版文档增加视频演示,更直观展示功能。
项目进展(2023年4月4日):
Vue3+TypeScript+Vite版本发布,完全重构,性能飞跃,超高代码质量
重构了Xlsx对于主题颜色的获取和计算,能够完美显示颜色
重构了Pptx底层部分逻辑,解耦了图表部分,并优化了显示性能
新版文档已经上线,demo部分替换部署了Vue3版本
2023年2月28日全面升级说明
鉴于很多朋友呼吁文档的问题,目前使用文档已更新,请参考
本次更新属于突破更新,完成了项目组件化改造,嵌入项目中使用更加容易,具体请拉取最新代码体验一下吧!
更新日志
1. 优化了pptx嵌套块溢出效果,比之前好很多
2. 增加了文件标题显示
3. 进行了组件化拆分设计,提供标准的Vue组件,方便接入
4. 优化了底层的一些代码,运行更加稳定
== 公众号上线!==
此外,博主的公众号上线了,大家在微信搜索 “飞鱼开源”。关注“飞鱼开源WorkShop”公众号,可以获取最新源码,同时不定期更新技术福利!
有大家的支持我才有更新的动力,感谢大家一直以来的支持!❤❤❤
仓库地址: https://git.flyfish.group,请下载过资源的大家注册后获取最新源码!
2022年8月1日更新,重大升级。
1. 重构大部分pptx逻辑,优化背景样式,块文字样式和图表。
2. 优化PDF展现逻辑,基于官网demo使用官方pdfViewer组件实现懒加载,虚拟滚动,大幅度提高性能,可以秒开超大PDF文件!
- 优化框架和升级依赖版本
福利:注册git私库并发送账号给博主,博主会帮忙开放本项目的git仓库权限,永久更新!记得是下载过资源的小伙伴哦,开发不易,请予以点滴支持,不尽感激!
git仓库地址:飞鱼开源工作室
2022年5月31日更新。增加文件url输入预览,可以访问文件在线预览DEMO体验。由于很多小伙伴提的问题都是关于服务器URL预览文件怎么预览,这次的demo集成了这部分功能,大家可以参照源码进行理解和修改。
因demo使用ajax加载,在测试时请保证文件资源响应Header包含允许跨域的头部。建议头部如下:
Access-Control-Allow-Origin * Access-Control-Allow-Headers X-Requested-With Access-Control-Allow-Methods GET 功能入口如下:
实现效果
word文档预览
Excel文档预览
PPT文档预览
PDF文档预览
Markdown预览
图片预览
文本预览
视频预览
看完了之后,废话不多说,来给大家梳理梳理实现思路。
现存的方案和不足
笔者在接到这个功能需求后,对市面上目前的实现方案进行了归纳和梳理,不外乎就三种:
- PDF预览使用pdfjs,Office文档使用微软的提供的预览URL。该方案确实省事,而且效果是最好的,但是有个很大的问题,文件链接必须是公网链接,这对于在企业网或局域网部署的系统来说,基本上是不可行的方案,pass
- 使用Java后端统一转换为PDF,然后在前端预览。该方案兼容性较好,效果仅次于在线Office,但是对于服务器的压力比较大,在动辄要“高并发,高可用,高吞吐量”的互联网场景下总是不那么合适,基于OpenOffice的文件转换非常耗费IO,pass
- 客户端本地安装Office,利用浏览器的Office插件进行预览。这种实现方式对客户端要求较高,基本上不考虑,毕竟我们是web预览嘛,谁知道客户用的是啥浏览器,pass
意外的收获
到此为止,所有的方案都被pass掉了,非常绝望。无果后,我搭上梯子,疯狂Google,终于找到了一个jquery的开源插件,叫做officeToHtml,出于对开源的尊重,这里提供一下人家的访问链接:OfficeJs | Demos
这个开源项目非常好用,引用它的demo就能直接预览主流格式,但是它是基于JQuery的。事实上,当时我都已经通过这个方案实现了,结果我们领导说不是Vue,而且用的组件也太老了,强行pass掉了。现实总是残酷的,看着我头顶所剩不多的秀发,深深叹了口气,准备自己再次开整。
有了国外大佬的思路提供,我的思路也渐渐清晰:
- 要解决这个问题,还是得用Vue实现
- 大佬的项目是jquery写的,我用Vue实现,也没说不让引用jQuery呀
- 分析一下大佬使用的开源组件,去GitHub上找最新的或者效果最好的,说不定有Vue版本呢
- 自己封装渲染入口,根据扩展名动态匹配渲染器,解析需要的格式。
OK,思路清晰了,我们开始撸代码。
开始实现
一、找替代框架
大佬的框架已经老得不被待见了,大致整理后,笔者找到的最贴近且效果最好的框架都在下面的表里了:
文档格式 | 老的开源组件 | 替代开源组件 |
word(docx) | mammoth | docx-preview(npm) |
powerpoint(pptx) | pptxjs | pptxjs改造开发 |
excel(xlsx) | sheetjs、handsontable | exceljs(npm)、handsontable(npm) |
pdf(pdf) | pdfjs | pdfjs(npm) |
图片 | jquery.verySimpleImageViewer | v-viewer(npm) |
升级后的组件完全兼容npm,唯一不兼容的pptxjs也被我改造了,能够完美兼容。以下是package.json中相关的依赖。
"@handsontable/vue": "^11.1.0",
"docx-preview": "^0.1.8",
"exceljs": "^4.3.0",
"handsontable": "^11.1.0",
"pdfjs-dist": "^2.12.313",
"v-viewer": "^1.6.4",
"vue": "^2.6.11"
二、搭建简单的视图组件
框架找好了,接下来我们开工。老样子,用vue-cli创建一个hello-world项目,把脚手架初始化出来。如果没安装过,先全局安装一下:
npm install -g @vue/cli-service-global
创建项目,名字就叫file-viewer吧!
cd ~/Projects
vue create file-viewer
然后我们在 src/components/HelloWorld.vue中,给他加一个容器,用于承载文档视图。再弄一个简单的loading容器,ok。
注意,这里的 @/components/util是一些常用工具类,主要做二进制数据和字节码、字符串互转的。当然,文档渲染入口也在里面,我们后面说。
<template>
<div :class="{hidden}">
<div class="banner">
<div class="container">
<h1><a href="/">Vue在线文档查看器<input class="file-select" type="file" @change="handleChange"/></a></h1>
</div>
</div>
<div class="container">
<div v-show="loading" class="well loading">正在加载中,请耐心等待...</div>
<div v-show="!loading" class="well" ref="output"></div>
</div>
</div>
</template>
<script>
import { getExtend, readBuffer, render } from '@/components/util';
import { parse } from 'qs';
/**
* 支持嵌入式显示,基于postMessage支持跨域
* 示例代码:
*
*/
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
// 加载状态跟踪
loading: false,
// 上个渲染实例
last: null,
// 隐藏头部,当基于消息机制渲染,将隐藏
hidden: false,
}
},
methods: {
async handleChange(e) {
this.loading = true;
try {
const [ file ] = e.target.files;
const arrayBuffer = await readBuffer(file);
this.loading = false
this.last = await this.displayResult(arrayBuffer, file)
} catch (e) {
console.error(e)
} finally {
this.loading = false
}
},
displayResult(buffer, file) {
// 取得文件名
const { name } = file;
### 最后
**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/topics/618166371)**
>![](https://img-blog.csdnimg.cn/img_convert/09d4fe6ef19ed09a875310b9ffbd1cad.webp?x-oss-process=image/format,png)
= false
this.last = await this.displayResult(arrayBuffer, file)
} catch (e) {
console.error(e)
} finally {
this.loading = false
}
},
displayResult(buffer, file) {
// 取得文件名
const { name } = file;
### 最后
**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/topics/618166371)**
>[外链图片转存中...(img-44ugwypt-1715273444206)]