yuè - Web 阅读器
前言年初的时候入手了 mini6 用于影音娱乐,在找阅读器的时候, AppStore 里的软件让我眼前一黑
“为什么云功能全是基于 iCloud 的啊?”
然后就有了这个项目
经历了一周的构思和两周的开发,我在 Github 提交了最初的版本,第一个版本的快照如下:
中间踩了非常多的坑,具体可以看这两篇文章:
Epub.js 实践、踩坑
让人头大的 Safari mobile 适配
介绍经过将近一个月的迭代,版本号也来到了 v1.4.0,这是它现在的样子:
线上地址:yue.norah1to.com
仓库地址:NoraH1to/yue
导入支持本地导入和从 webDAV 导入,webDAV 需要配置自己的服务:
格式暂时只支持 epub、pdf
哪天我有看漫画的需求了,会支持 zip 格式
反向代理Web 应用最大的问题就是使用第三方服务时的跨域问题,不巧的是,webDAV 服务的标准实现是存在跨域限制的
假设你要使用坚果云的 webDAV 服务,它的地址为 https://dav.jianguoyun.com/dav,你使用该地址进行配置,是行不通的:
为了解决 ...
灵活度尚可的脚手架
一个脚手架,和其它东西混在一起断断续续做了三个月,总算是能用了(至少我个人用起来很舒服)
特点简单、灵活、高度定制
简单有多简单?就像市面上大部分脚手架那样,它拥有简单的 GUI 来进行交互:
几秒钟时间就能快速构建一个项目框架,这是基本盘
灵活有多灵活?vue-cli 够不够灵活?setup-cli 的灵活程度不比它差
现在都推荐使用 create-vue,但它的灵活性还不如 vue-cli
vue-cli 当初最吸引我的就是 vue add 这种向已有项目引入新能力的功能(可惜它经常会误伤已有代码)
setup-cli 同样也有,但它有着门槛更低的定制能力,所以可以避免上面说的误伤已有代码的问题:
定制vue-cli 的社区特别活跃,给出的特性和模板特别多,如果你要使用 Vue 来进行开发,它是一个不错的选择
但是,这种给出最佳实践预设的方式有着局限性,它不可能满足每一个人的需求
如果每次你生成完项目后,还需要去琢磨其配置从而进一步的客制化,这会令人抓狂
在 setup-cli 中,一切东西都可以定制、然后组合
setup-cli 除了默认提供的特性(就我一个人写那肯定少 ...
Epub.js 实践、踩坑
前言epub.js 是一个强大的库,算是浏览器这块 epub 文件处理的大哥
但是由于项目时间线跨度大(7 年),API 不友好(相对现在的环境来说),再加上只进行了寥寥几次效果不理想的重构,导致这个库的问题非常多,文档非常简陋,类型声明文件更是一塌糊涂
个人在使用中踩了非常非常多的坑,在此记录,方便以后查阅
解析流程构建 epub 实例epub.js 许多接口,其中最直接的使用方法为调用其默认导出的函数,传入文件供其解析
12import Epub from 'epubjs';const epub = Epub(target, options); // 返回 Book 实例
这里的 target 可以是多种类型的数据:
二进制:即 ArrayBuffer
BASE64:base64 字符串,使用该类型需要设置 options.encoding = 'base64'
链接:通过 http 协议获取远程文件
需要注意该链接必须以 .epub 结尾,在源码中 determineType 负责解析输入类型:
12345678determineTyp ...
让人头大的 Safari mobile 适配
最近在做一个 web 端的阅读器,缘由暂且不提,适配 SM (移动端 Safari) 时简直要了 👴 的小命!
浏览器高度首先是浏览器高度,在 SM 中,vh 在计算时会包括顶部的导航栏
也就是说,如果你想让内容填满整个可视区域,用 height: 100vh 会溢出一大截,解决的方式很简单,用 height: 100% 或者别的方式替代(比如 flex 布局)
为什么在我们滚动页面的时候,导航栏可以透过毛玻璃看到滚动到后面的内容,所以 SM 的实际可视区域还包括了导航栏
经过测试,iOS 平台的 Chrome 也能复现高度问题,可以推测出 iOS 平台上的浏览器都需要注意这点,因为 iOS 限制了第三方浏览器只能使用系统内置的 WebKit 内核
上下文菜单这个问题就比较重量级了,通过触屏长按目标触发 contextmenu 事件在 SM 上直接不支持
从图中也可以看出,应该是为了 iOS 中的跨应用拽托功能做出了让步(在以前是为无障碍功能-放大镜让步)
一开始我不信邪,用 Chat-GPT 查了一圈上下文菜单的库,例如 react-contexify、react-menu, ...
前端项目 lint 个人实践
前言之前在公司推行了工程化和项目规范,其中就涉及到了提交校验和代码校验,当时没啥时间写文,这会来补上
我将在文中一步一步构建一个 typescript 模板库,模板细节就不管了,注意力放在规范校验上
代码校验首先是代码的规范问题,这边通过 eslint + prettier + editorconfig 来实现
eslinteslint 用于规范咱们写的代码,接入其实很简单,官方提供了一个 CLI,我们在项目根目录下执行下面命令
1pnpm create @eslint/config
在 CLI 中选择你自己需要的配置和代码格式喜好即可,我这边生成的 .eslintrc.cjs 配置文件如下:
123456789101112131415161718192021module.exports = { env: { browser: true, es2021: true, node: true, }, extends: ['eslint:recommended', 'plugin:@typescript-e ...
new 关键字
在使用 new 关键字的时候进行了以下操作:
创建一个新的空对象 {}
将该对象的 __proto__ 指向构造函数的原型(继承原型)
将该对象作为函数内 this 上下文
如果函数没有返回对象,返回 this
如果函数返回了对象且期望继承原型,则需要手动继承(将对象的 __proto__ 指向 Foo.prototype)
See the Pen
NEW-1 by NoraH1to (@norah1to)
on CodePen.
Vuetify v3(2)- useRender
如果你需要使用 setup + jsx + 暴露组件内部属性
一般来说会在 render 函数里编写 jsx 代码并返回,在 setup 中返回需要用到的属性
下面例子中的 child.tsx 为了满足上面需求,setup 暴露(返回)了所有方法
如果我们需要将 child.tsx 中 reset,init 方法设为私有呢?
好像行不通,渲染函数只能拿到 setup 中返回的内容,此时会出现一个问题:
渲染函数需要的变量均需要在 setup 中返回,导致无法控制组件暴露给外部的变量
你可能会想到 setup 中返回 jsx 渲染函数,并使用 expose 暴露需要暴露的东西
但是这个方法有一个问题,使用 expose 后组件实例中以 $ 开头的成员会被隐藏,导致很多高级的组件用法无法使用
例如如下代码:
1234567891011// test.tsximport { ref } from 'vue';export default { setup(props, { expose }) { c ...
Vuetify v3(1)- defineComponent
前言我个人非常喜欢谷歌的 MD 设计,Vue 组件库这块 vuetify 是该设计的杠把子
尤其是升级到对应 Vue3 的 v3 版本之后,其内部实现让人眼前一亮
大概是因为 Vue2 为数不多的逻辑复用方式 mixin 很容易让人眼前一黑,一对比下来就显得新版的 vuetify 很牛逼
属性透传回到重点,在设计组件库时,嵌套组件的属性透传、默认值复写等一直让人头疼
vuetify 提供了一种较为优雅的解决方法,每个组件都是由二次封装的 defineComponent 方法声明的,例如 v-btn 的源码:
1234567891011import { defineComponent, ... } from '@/util'// 使用了 @util 下二次封装的 defineComponent 方法export const VBtn = defineComponent({ name: 'VBtn', directives: { ... }, props: { ... } ...
栅格格式化上下文(GFC)
是什么字面意思,栅格布局下的格式化上下文
布局规则看文档Grid | MDN
如何创建display: grid/inline-grid 即可
特点没啥特点,至少我在文档里没找到
个人测试与 FFC 特性一致,也是 BFC 的超集
弹性格式化上下文(FFC)
是什么字面意思,弹性布局下的格式化上下文
布局规则大家伙都很熟悉,就不细说了,不懂就看文档Flex | MDN
如何创建display: flex/inline-flex 即可
特点float, clear, vertical-align 属性失效
See the Pen
FFC-1 by NoraH1to (@norah1to)
on CodePen.
其余效果跟 BFC 一致,相当于 BFC 的超集