From c504c7792cd31f1e49a7e732ad91c981e894d363 Mon Sep 17 00:00:00 2001 From: ZiuChen <457353192@qq.com> Date: Wed, 22 Feb 2023 14:12:05 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20ZiuChen/?= =?UTF-8?q?ZiuChen.github.io@6cd860549fe885105feeda9c269d620903acc990=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 404.html | 2 +- .../【2023】青训营 - 前端练习题汇总解析.html | 6 ++--- article/【字节跳动】前端面试题总结.html | 6 ++--- article/【快手】深入理解前端面试题.html | 6 ++--- article/【用友金融】前端面试题总结.html | 6 ++--- article/一文读懂事件冒泡与事件捕获.html | 6 ++--- article/一文读懂伪类与伪元素.html | 6 ++--- article/一文读懂函数中this指向问题.html | 6 ++--- article/从0实现一个年度报告.html | 6 ++--- ...懂对象的数据属性描述符、存储属性描述符.html | 6 ++--- ...析defineProperty与Proxy实现的双向绑定.html | 6 ++--- article/深入JavaScript数据类型.html | 6 ++--- ...Vue3源码,看看Vue.use后究竟发生了什么?.html | 6 ++--- article/深入理解Proxy与Reflect.html | 6 ++--- article/深入理解浏览器缓存机制.html | 6 ++--- article/深入理解浏览器运行原理.html | 6 ++--- ...icle_【2023】青训营 - 前端练习题汇总解析.md.8d7e9b9c.js} | 2 +- ...【2023】青训营 - 前端练习题汇总解析.md.8d7e9b9c.lean.js} | 2 +- ...s => article_【字节跳动】前端面试题总结.md.8b64abc5.js} | 2 +- ...article_【字节跳动】前端面试题总结.md.8b64abc5.lean.js} | 2 +- ...s => article_【快手】深入理解前端面试题.md.9bd6db9f.js} | 2 +- ...article_【快手】深入理解前端面试题.md.9bd6db9f.lean.js} | 2 +- ...s => article_【用友金融】前端面试题总结.md.8730c019.js} | 2 +- ...article_【用友金融】前端面试题总结.md.8730c019.lean.js} | 2 +- ...s => article_一文读懂事件冒泡与事件捕获.md.c2d9cd1b.js} | 2 +- ...article_一文读懂事件冒泡与事件捕获.md.c2d9cd1b.lean.js} | 2 +- ...9.js => article_一文读懂伪类与伪元素.md.dd034dbf.js} | 2 +- ...=> article_一文读懂伪类与伪元素.md.dd034dbf.lean.js} | 2 +- ...=> article_一文读懂函数中this指向问题.md.3025c285.js} | 2 +- ...ticle_一文读懂函数中this指向问题.md.3025c285.lean.js} | 2 +- ...d.js => article_从0实现一个年度报告.md.7ba24283.js} | 2 +- ...=> article_从0实现一个年度报告.md.7ba24283.lean.js} | 2 +- ...cle_彻底搞懂对象的数据属性描述符、存储属性描述符.md.b7a6c275.js} | 2 +- ...底搞懂对象的数据属性描述符、存储属性描述符.md.b7a6c275.lean.js} | 2 +- ...析defineProperty与Proxy实现的双向绑定.md.02c8f56e.js} | 2 +- ...fineProperty与Proxy实现的双向绑定.md.02c8f56e.lean.js} | 2 +- ...> article_深入JavaScript数据类型.md.80fd8af0.js} | 2 +- ...icle_深入JavaScript数据类型.md.80fd8af0.lean.js} | 2 +- ...入Vue3源码,看看Vue.use后究竟发生了什么?.md.cd9b1cff.js} | 2 +- ...Vue3源码,看看Vue.use后究竟发生了什么?.md.cd9b1cff.lean.js} | 2 +- ... article_深入理解Proxy与Reflect.md.9c5a6cd1.js} | 2 +- ...cle_深入理解Proxy与Reflect.md.9c5a6cd1.lean.js} | 2 +- ....js => article_深入理解浏览器缓存机制.md.e7e22bb1.js} | 2 +- ...> article_深入理解浏览器缓存机制.md.e7e22bb1.lean.js} | 2 +- ....js => article_深入理解浏览器运行原理.md.f13b2b23.js} | 2 +- ...> article_深入理解浏览器运行原理.md.f13b2b23.lean.js} | 2 +- ...ex.md.e391bcbf.js => index.md.00c51c0e.js} | 2 +- ...bcbf.lean.js => index.md.00c51c0e.lean.js} | 2 +- ...md.2c88cba1.js => note_CSS.md.a4f3e631.js} | 2 +- ...1.lean.js => note_CSS.md.a4f3e631.lean.js} | 2 +- ...note_Front-end Engineering.md.939c2eef.js} | 18 +++++++-------- ...Front-end Engineering.md.939c2eef.lean.js} | 2 +- ...95de.js => note_JavaScript.md.e58e866f.js} | 2 +- ...js => note_JavaScript.md.e58e866f.lean.js} | 2 +- ...=> note_JavaScriptEnhanced.md.b46ba179.js} | 2 +- ...te_JavaScriptEnhanced.md.b46ba179.lean.js} | 2 +- ...md.eafce674.js => note_SSR.md.5b580a05.js} | 2 +- ...4.lean.js => note_SSR.md.5b580a05.lean.js} | 2 +- ...ipboardManager_guide_index.md.caf90979.js} | 2 +- ...rdManager_guide_index.md.caf90979.lean.js} | 2 +- ...ect_ClipboardManager_index.md.fcacbc6c.js} | 2 +- ...lipboardManager_index.md.fcacbc6c.lean.js} | 2 +- ..._ClipboardManager_log_index.md.4ee5fe53.js | 1 - ...boardManager_log_index.md.4ee5fe53.lean.js | 1 - ..._ClipboardManager_log_index.md.9bd18ae1.js | 1 + ...boardManager_log_index.md.9bd18ae1.lean.js | 1 + ...ardManager_statement_index.md.fddb5934.js} | 2 +- ...nager_statement_index.md.fddb5934.lean.js} | 2 +- ...ClipboardManager_vip_index.md.8d894bfc.js} | 2 +- ...oardManager_vip_index.md.8d894bfc.lean.js} | 2 +- ...oject_SmartWordBreak_index.md.6364a91a.js} | 2 +- ..._SmartWordBreak_index.md.6364a91a.lean.js} | 2 +- ...t_SmartWordBreak_log_index.md.02ecbe98.js} | 2 +- ...rtWordBreak_log_index.md.02ecbe98.lean.js} | 2 +- ...tWordBreak_statement_index.md.4c33c737.js} | 2 +- ...Break_statement_index.md.4c33c737.lean.js} | 2 +- ....5b8fe7b6.js => self_index.md.e7b0b4e0.js} | 2 +- ...lean.js => self_index.md.e7b0b4e0.lean.js} | 2 +- ...6.js => works_contribution.md.13a9eaa9.js} | 2 +- ...=> works_contribution.md.13a9eaa9.lean.js} | 2 +- ...5f0.js => works_opensource.md.04c9693c.js} | 2 +- ...s => works_opensource.md.04c9693c.lean.js} | 2 +- hashmap.json | 2 +- index.html | 4 ++-- note/CSS.html | 6 ++--- note/Front-end Engineering.html | 22 +++++++++---------- note/JavaScript.html | 6 ++--- note/JavaScriptEnhanced.html | 6 ++--- note/SSR.html | 6 ++--- project/ClipboardManager/guide/index.html | 6 ++--- project/ClipboardManager/index.html | 6 ++--- project/ClipboardManager/log/index.html | 6 ++--- project/ClipboardManager/statement/index.html | 6 ++--- project/ClipboardManager/vip/index.html | 6 ++--- project/SmartWordBreak/index.html | 6 ++--- project/SmartWordBreak/log/index.html | 6 ++--- project/SmartWordBreak/statement/index.html | 6 ++--- self/index.html | 6 ++--- works/contribution.html | 6 ++--- works/opensource.html | 6 ++--- 100 files changed, 177 insertions(+), 177 deletions(-) rename assets/{article_【2023】青训营 - 前端练习题汇总解析.md.87c3ec71.js => article_【2023】青训营 - 前端练习题汇总解析.md.8d7e9b9c.js} (99%) rename assets/{article_【2023】青训营 - 前端练习题汇总解析.md.87c3ec71.lean.js => article_【2023】青训营 - 前端练习题汇总解析.md.8d7e9b9c.lean.js} (95%) rename assets/{article_【字节跳动】前端面试题总结.md.11aa2b5a.js => article_【字节跳动】前端面试题总结.md.8b64abc5.js} (99%) rename assets/{article_【字节跳动】前端面试题总结.md.11aa2b5a.lean.js => article_【字节跳动】前端面试题总结.md.8b64abc5.lean.js} (96%) rename assets/{article_【快手】深入理解前端面试题.md.5f4ef7a3.js => article_【快手】深入理解前端面试题.md.9bd6db9f.js} (99%) rename assets/{article_【快手】深入理解前端面试题.md.5f4ef7a3.lean.js => article_【快手】深入理解前端面试题.md.9bd6db9f.lean.js} (98%) rename assets/{article_【用友金融】前端面试题总结.md.69243f39.js => article_【用友金融】前端面试题总结.md.8730c019.js} (99%) rename assets/{article_【用友金融】前端面试题总结.md.69243f39.lean.js => article_【用友金融】前端面试题总结.md.8730c019.lean.js} (97%) rename assets/{article_一文读懂事件冒泡与事件捕获.md.a9dedb6d.js => article_一文读懂事件冒泡与事件捕获.md.c2d9cd1b.js} (99%) rename assets/{article_一文读懂事件冒泡与事件捕获.md.a9dedb6d.lean.js => article_一文读懂事件冒泡与事件捕获.md.c2d9cd1b.lean.js} (97%) rename assets/{article_一文读懂伪类与伪元素.md.18a4ea39.js => article_一文读懂伪类与伪元素.md.dd034dbf.js} (99%) rename assets/{article_一文读懂伪类与伪元素.md.18a4ea39.lean.js => article_一文读懂伪类与伪元素.md.dd034dbf.lean.js} (95%) rename assets/{article_一文读懂函数中this指向问题.md.d4e27bc7.js => article_一文读懂函数中this指向问题.md.3025c285.js} (99%) rename assets/{article_一文读懂函数中this指向问题.md.d4e27bc7.lean.js => article_一文读懂函数中this指向问题.md.3025c285.lean.js} (95%) rename assets/{article_从0实现一个年度报告.md.4e06b81d.js => article_从0实现一个年度报告.md.7ba24283.js} (99%) rename assets/{article_从0实现一个年度报告.md.4e06b81d.lean.js => article_从0实现一个年度报告.md.7ba24283.lean.js} (97%) rename assets/{article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.9865de7d.js => article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.b7a6c275.js} (99%) rename assets/{article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.9865de7d.lean.js => article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.b7a6c275.lean.js} (93%) rename assets/{article_浅析defineProperty与Proxy实现的双向绑定.md.f2072102.js => article_浅析defineProperty与Proxy实现的双向绑定.md.02c8f56e.js} (99%) rename assets/{article_浅析defineProperty与Proxy实现的双向绑定.md.f2072102.lean.js => article_浅析defineProperty与Proxy实现的双向绑定.md.02c8f56e.lean.js} (91%) rename assets/{article_深入JavaScript数据类型.md.ed246d99.js => article_深入JavaScript数据类型.md.80fd8af0.js} (99%) rename assets/{article_深入JavaScript数据类型.md.ed246d99.lean.js => article_深入JavaScript数据类型.md.80fd8af0.lean.js} (95%) rename assets/{article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.e6b03974.js => article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.cd9b1cff.js} (99%) rename assets/{article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.e6b03974.lean.js => article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.cd9b1cff.lean.js} (93%) rename assets/{article_深入理解Proxy与Reflect.md.368d9aed.js => article_深入理解Proxy与Reflect.md.9c5a6cd1.js} (99%) rename assets/{article_深入理解Proxy与Reflect.md.368d9aed.lean.js => article_深入理解Proxy与Reflect.md.9c5a6cd1.lean.js} (94%) rename assets/{article_深入理解浏览器缓存机制.md.be15491a.js => article_深入理解浏览器缓存机制.md.e7e22bb1.js} (99%) rename assets/{article_深入理解浏览器缓存机制.md.be15491a.lean.js => article_深入理解浏览器缓存机制.md.e7e22bb1.lean.js} (95%) rename assets/{article_深入理解浏览器运行原理.md.4b1c1d16.js => article_深入理解浏览器运行原理.md.f13b2b23.js} (99%) rename assets/{article_深入理解浏览器运行原理.md.4b1c1d16.lean.js => article_深入理解浏览器运行原理.md.f13b2b23.lean.js} (97%) rename assets/{index.md.e391bcbf.js => index.md.00c51c0e.js} (92%) rename assets/{index.md.e391bcbf.lean.js => index.md.00c51c0e.lean.js} (92%) rename assets/{note_CSS.md.2c88cba1.js => note_CSS.md.a4f3e631.js} (99%) rename assets/{note_CSS.md.2c88cba1.lean.js => note_CSS.md.a4f3e631.lean.js} (99%) rename assets/{note_Front-end Engineering.md.e321faed.js => note_Front-end Engineering.md.939c2eef.js} (98%) rename assets/{note_Front-end Engineering.md.e321faed.lean.js => note_Front-end Engineering.md.939c2eef.lean.js} (97%) rename assets/{note_JavaScript.md.6a2d95de.js => note_JavaScript.md.e58e866f.js} (91%) rename assets/{note_JavaScript.md.6a2d95de.lean.js => note_JavaScript.md.e58e866f.lean.js} (91%) rename assets/{note_JavaScriptEnhanced.md.209d0c05.js => note_JavaScriptEnhanced.md.b46ba179.js} (99%) rename assets/{note_JavaScriptEnhanced.md.209d0c05.lean.js => note_JavaScriptEnhanced.md.b46ba179.lean.js} (99%) rename assets/{note_SSR.md.eafce674.js => note_SSR.md.5b580a05.js} (99%) rename assets/{note_SSR.md.eafce674.lean.js => note_SSR.md.5b580a05.lean.js} (94%) rename assets/{project_ClipboardManager_guide_index.md.cbb1b2e8.js => project_ClipboardManager_guide_index.md.caf90979.js} (99%) rename assets/{project_ClipboardManager_guide_index.md.cbb1b2e8.lean.js => project_ClipboardManager_guide_index.md.caf90979.lean.js} (98%) rename assets/{project_ClipboardManager_index.md.c8cba791.js => project_ClipboardManager_index.md.fcacbc6c.js} (98%) rename assets/{project_ClipboardManager_index.md.c8cba791.lean.js => project_ClipboardManager_index.md.fcacbc6c.lean.js} (95%) delete mode 100644 assets/project_ClipboardManager_log_index.md.4ee5fe53.js delete mode 100644 assets/project_ClipboardManager_log_index.md.4ee5fe53.lean.js create mode 100644 assets/project_ClipboardManager_log_index.md.9bd18ae1.js create mode 100644 assets/project_ClipboardManager_log_index.md.9bd18ae1.lean.js rename assets/{project_ClipboardManager_statement_index.md.6751fd19.js => project_ClipboardManager_statement_index.md.fddb5934.js} (99%) rename assets/{project_ClipboardManager_statement_index.md.6751fd19.lean.js => project_ClipboardManager_statement_index.md.fddb5934.lean.js} (97%) rename assets/{project_ClipboardManager_vip_index.md.00c8bdb1.js => project_ClipboardManager_vip_index.md.8d894bfc.js} (98%) rename assets/{project_ClipboardManager_vip_index.md.00c8bdb1.lean.js => project_ClipboardManager_vip_index.md.8d894bfc.lean.js} (94%) rename assets/{project_SmartWordBreak_index.md.8198941b.js => project_SmartWordBreak_index.md.6364a91a.js} (97%) rename assets/{project_SmartWordBreak_index.md.8198941b.lean.js => project_SmartWordBreak_index.md.6364a91a.lean.js} (93%) rename assets/{project_SmartWordBreak_log_index.md.3ca84f95.js => project_SmartWordBreak_log_index.md.02ecbe98.js} (97%) rename assets/{project_SmartWordBreak_log_index.md.3ca84f95.lean.js => project_SmartWordBreak_log_index.md.02ecbe98.lean.js} (92%) rename assets/{project_SmartWordBreak_statement_index.md.08faf5e0.js => project_SmartWordBreak_statement_index.md.4c33c737.js} (96%) rename assets/{project_SmartWordBreak_statement_index.md.08faf5e0.lean.js => project_SmartWordBreak_statement_index.md.4c33c737.lean.js} (85%) rename assets/{self_index.md.5b8fe7b6.js => self_index.md.e7b0b4e0.js} (99%) rename assets/{self_index.md.5b8fe7b6.lean.js => self_index.md.e7b0b4e0.lean.js} (96%) rename assets/{works_contribution.md.f1f31ee6.js => works_contribution.md.13a9eaa9.js} (95%) rename assets/{works_contribution.md.f1f31ee6.lean.js => works_contribution.md.13a9eaa9.lean.js} (90%) rename assets/{works_opensource.md.d00905f0.js => works_opensource.md.04c9693c.js} (98%) rename assets/{works_opensource.md.d00905f0.lean.js => works_opensource.md.04c9693c.lean.js} (95%) diff --git a/404.html b/404.html index f8705bc3..f82cf06c 100644 --- a/404.html +++ b/404.html @@ -13,7 +13,7 @@
Skip to content

404

PAGE NOT FOUND

But if you don't change your direction, and if you keep looking, you may end up where you are heading.

Released under the MIT License.

- + diff --git a/article/【2023】青训营 - 前端练习题汇总解析.html b/article/【2023】青训营 - 前端练习题汇总解析.html index 340df4eb..329a7a84 100644 --- a/article/【2023】青训营 - 前端练习题汇总解析.html +++ b/article/【2023】青训营 - 前端练习题汇总解析.html @@ -8,7 +8,7 @@ - + @@ -307,8 +307,8 @@ return true } } - - + + diff --git a/article/【字节跳动】前端面试题总结.html b/article/【字节跳动】前端面试题总结.html index 48d6a47d..46bf16de 100644 --- a/article/【字节跳动】前端面试题总结.html +++ b/article/【字节跳动】前端面试题总结.html @@ -8,7 +8,7 @@ - + @@ -55,8 +55,8 @@ false

问答题

HTTP缓存的请求头与响应头有哪些

宏任务与微任务有哪些区别?简述他们的应用场景

宏任务与微任务优先级不同

常见的宏任务与微任务

算法

中文数字转为阿拉伯数字

给定一个字符串,返回该字符串的所有组合

js
输入 abc 
 输出 ['abc', 'acb', 'bac', 'bca', 'cab', 'cba']
-

回溯算法

- +

回溯算法

+ diff --git a/article/【快手】深入理解前端面试题.html b/article/【快手】深入理解前端面试题.html index 100adf23..be6f7192 100644 --- a/article/【快手】深入理解前端面试题.html +++ b/article/【快手】深入理解前端面试题.html @@ -8,7 +8,7 @@ - + @@ -193,8 +193,8 @@ console.log(twoSum([1, 2, 3, 4, 4], 5)) // 2 console.log(twoSum([1, 1, 2, 3, 4, 4], 5)) // 3 - - + + diff --git a/article/【用友金融】前端面试题总结.html b/article/【用友金融】前端面试题总结.html index 3a1bea37..93d90d56 100644 --- a/article/【用友金融】前端面试题总结.html +++ b/article/【用友金融】前端面试题总结.html @@ -8,7 +8,7 @@ - + @@ -82,8 +82,8 @@

CSS权重的优先级

内联样式 > ID选择器 > 类选择器 > 标签选择器 > 通配符

HTTP状态码

越多越好

BFC(块级格式上下文)

下列选项对产生BFC描述错误的是:

元素浮动

设置元素浮动后,元素的display值哪个是正确的?

HTTP请求方法

下面哪个选项不是HTTP的请求方法

HTTP请求方法有:

GET POST DELETE PUT OPTIONSCONNECT HEAD PATCH TRACE

跨域问题

通常有哪些方法解决跨域问题?

了解Webpack的哪些配置项

判断变量类型

直接使用typeof无法判断引用类型变量的类型

js
console.log(typeof []) // object
 console.log(typeof {}) // object
 console.log(typeof null) // object
-

JS浮点数相加精度问题

简单讲讲Vue Router原理

ES6熟悉吗

ES6教程

CSS如何实现水平居中与垂直居中

参见CSS学习笔记

- +

JS浮点数相加精度问题

简单讲讲Vue Router原理

ES6熟悉吗

ES6教程

CSS如何实现水平居中与垂直居中

参见CSS学习笔记

+ diff --git a/article/一文读懂事件冒泡与事件捕获.html b/article/一文读懂事件冒泡与事件捕获.html index 08ecfba9..429065e6 100644 --- a/article/一文读懂事件冒泡与事件捕获.html +++ b/article/一文读懂事件冒泡与事件捕获.html @@ -8,7 +8,7 @@ - + @@ -58,8 +58,8 @@ // some code ... e.preventDefault() }); -

相关链接

事件冒泡及捕获

- +

相关链接

事件冒泡及捕获

+ diff --git a/article/一文读懂伪类与伪元素.html b/article/一文读懂伪类与伪元素.html index f75e52b1..9184fa05 100644 --- a/article/一文读懂伪类与伪元素.html +++ b/article/一文读懂伪类与伪元素.html @@ -8,7 +8,7 @@ - + @@ -80,8 +80,8 @@ .father { width: 100px; } -

相关链接

代码片段

CSS选择器

- +

相关链接

代码片段

CSS选择器

+ diff --git a/article/一文读懂函数中this指向问题.html b/article/一文读懂函数中this指向问题.html index 8a2c004c..368c44e0 100644 --- a/article/一文读懂函数中this指向问题.html +++ b/article/一文读懂函数中this指向问题.html @@ -8,7 +8,7 @@ - + @@ -167,8 +167,8 @@ person1.foo4()() // 隐式绑定: person1 person1.foo4.call(person2)() // 显式绑定: person2 person1.foo4().call(person2) // 隐式绑定: person1 - - + + diff --git a/article/从0实现一个年度报告.html b/article/从0实现一个年度报告.html index ad2b0bc5..09523c54 100644 --- a/article/从0实现一个年度报告.html +++ b/article/从0实现一个年度报告.html @@ -8,7 +8,7 @@ - + @@ -107,8 +107,8 @@ nextPage() } }) -

代码打包

由于最后需要将项目放到码上掘金平台运行,所以需要考虑静态资源的加载问题

这里我使用到了Vite提供的类似file-loader的功能,可以将大小在指定阈值下的图片资源直接转为行内的DataURL,配置选项是config.build.assetsInlineLimit,这样所有的图片资源都不必考虑外部引入的问题,直接内嵌进代码。

技术介绍

主界面使用的是Vue3的SFC,主要逻辑都在单文件组件中完成。通过JSX语法编写不同页面的内容,这样更方便我们为每个节点添加不同的动画。

JSX编写的组件通过全局注册后,在SFC中通过<Component>动态加载。

图片资源方面,使用到了雪碧图,部署后可以降低客户端发起HTTP请求频次,提高性能

代码复用方面,样式代码都抽离为单个的xxxx.less文件,哪里用到了直接导入即可

使用到了Pinia状态管理库,将switching pageId audioStatus等全局状态放到其中管理非常方便,避免了provideinject的繁琐

功能介绍

Demo展示

Demo(Vercel)

jcode

- +

代码打包

由于最后需要将项目放到码上掘金平台运行,所以需要考虑静态资源的加载问题

这里我使用到了Vite提供的类似file-loader的功能,可以将大小在指定阈值下的图片资源直接转为行内的DataURL,配置选项是config.build.assetsInlineLimit,这样所有的图片资源都不必考虑外部引入的问题,直接内嵌进代码。

技术介绍

主界面使用的是Vue3的SFC,主要逻辑都在单文件组件中完成。通过JSX语法编写不同页面的内容,这样更方便我们为每个节点添加不同的动画。

JSX编写的组件通过全局注册后,在SFC中通过<Component>动态加载。

图片资源方面,使用到了雪碧图,部署后可以降低客户端发起HTTP请求频次,提高性能

代码复用方面,样式代码都抽离为单个的xxxx.less文件,哪里用到了直接导入即可

使用到了Pinia状态管理库,将switching pageId audioStatus等全局状态放到其中管理非常方便,避免了provideinject的繁琐

功能介绍

Demo展示

Demo(Vercel)

jcode

+ diff --git a/article/彻底搞懂对象的数据属性描述符、存储属性描述符.html b/article/彻底搞懂对象的数据属性描述符、存储属性描述符.html index 7a93ae75..4710f050 100644 --- a/article/彻底搞懂对象的数据属性描述符、存储属性描述符.html +++ b/article/彻底搞懂对象的数据属性描述符、存储属性描述符.html @@ -8,7 +8,7 @@ - + @@ -86,8 +86,8 @@ function foo() { console.log("resetted address value once") } - - + + diff --git a/article/浅析defineProperty与Proxy实现的双向绑定.html b/article/浅析defineProperty与Proxy实现的双向绑定.html index 0120f990..6ce3e6f9 100644 --- a/article/浅析defineProperty与Proxy实现的双向绑定.html +++ b/article/浅析defineProperty与Proxy实现的双向绑定.html @@ -8,7 +8,7 @@ - + @@ -34,8 +34,8 @@ }) </script> </body> -

通过 defineProperty 实现的响应式,不能检测数组和对象的变化:

对于对象:

Vue 无法检测 property 的添加或移除。

var vm = new Vue({ data:{ a:1 } }) // vm.a 是响应式的 vm.b = 2 // vm.b 是非响应式的

对于数组:

  1. 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时,例如:vm.items.length = newLength

🔰 Vue3的响应式原理

- +

通过 defineProperty 实现的响应式,不能检测数组和对象的变化:

对于对象:

Vue 无法检测 property 的添加或移除。

var vm = new Vue({ data:{ a:1 } }) // vm.a 是响应式的 vm.b = 2 // vm.b 是非响应式的

对于数组:

  1. 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时,例如:vm.items.length = newLength

🔰 Vue3的响应式原理

+ diff --git a/article/深入JavaScript数据类型.html b/article/深入JavaScript数据类型.html index 6c94be76..1a516022 100644 --- a/article/深入JavaScript数据类型.html +++ b/article/深入JavaScript数据类型.html @@ -8,7 +8,7 @@ - + @@ -52,8 +52,8 @@ } console.log(classof({})) // Object -

核心原理

深入Object.prototype.toString

参考ECMA6规范文档:Object.prototype.toString()

ES5标准下 Object.prototype.toString 执行原理

ES6标准下 Object.prototype.toString 执行原理

Object.prototype.toString()被调用时,会进行如下步骤:

Object.prototype.toString()

在ES6里,之前的内部属性 [[Class]] 不再使用,取而代之的是一系列的 internal slot

- +

核心原理

深入Object.prototype.toString

参考ECMA6规范文档:Object.prototype.toString()

ES5标准下 Object.prototype.toString 执行原理

ES6标准下 Object.prototype.toString 执行原理

Object.prototype.toString()被调用时,会进行如下步骤:

Object.prototype.toString()

在ES6里,之前的内部属性 [[Class]] 不再使用,取而代之的是一系列的 internal slot

+ diff --git a/article/深入Vue3源码,看看Vue.use后究竟发生了什么?.html b/article/深入Vue3源码,看看Vue.use后究竟发生了什么?.html index dd602576..42c52653 100644 --- a/article/深入Vue3源码,看看Vue.use后究竟发生了什么?.html +++ b/article/深入Vue3源码,看看Vue.use后究竟发生了什么?.html @@ -8,7 +8,7 @@ - + @@ -120,8 +120,8 @@ const app = createApp(App).use(registerElement) app.mount('#app') -

当有新的需要使用的组件时,只需要到register-element.ts文件中引入一次即可。

参考阅读

Vue文档: App.use

Vue文档: Plugins

- +

当有新的需要使用的组件时,只需要到register-element.ts文件中引入一次即可。

参考阅读

Vue文档: App.use

Vue文档: Plugins

+ diff --git a/article/深入理解Proxy与Reflect.html b/article/深入理解Proxy与Reflect.html index 960bb51b..18f4bc89 100644 --- a/article/深入理解Proxy与Reflect.html +++ b/article/深入理解Proxy与Reflect.html @@ -8,7 +8,7 @@ - + @@ -172,8 +172,8 @@ const stu = new Reflect.construct(Person, ['ziu', 18], Student) console.log(stu) - - + + diff --git a/article/深入理解浏览器缓存机制.html b/article/深入理解浏览器缓存机制.html index 5ba54f66..ba01ad97 100644 --- a/article/深入理解浏览器缓存机制.html +++ b/article/深入理解浏览器缓存机制.html @@ -8,7 +8,7 @@ - + @@ -24,8 +24,8 @@ // 数字都用16进制表示 return `${fileLength.toString(16)}-${fileLastModifiedTime.toString(16)}` } -

Last-Modified与If-Modified-Since

Last-Modified是该资源文件最后一次更改时间,服务器会在ResponseHeader里返回,同时浏览器会将这个值保存起来,在下一次发送请求时,放到RequestHeader里的If-Modified-Since里,服务器在接收到后也会做比对,如果相同则命中协商缓存。

If-None-Match的优先级要高于If-Modified-Since,即:如果浏览器同时存在

两种协商缓存的区别

内存缓存与硬盘缓存

当我们打开一个新网页,服务器返回200,将资源发送给浏览器,浏览器做本地缓存

当我们刷新标签页,浏览器从内存缓存获得资源

当我们关闭标签页重新打开,浏览器从硬盘缓存获得资源

在浏览器中,浏览器会在js和图片等文件解析执行后直接存入内存缓存中,那么当刷新页面时只需直接从内存缓存中读取(MemoryCache);而css文件则会存入硬盘文件中,所以每次渲染页面都需要从硬盘读取缓存(DiskCache)。

用户对浏览器缓存的控制

参考资料

[稀土掘金] 彻底理解浏览器的缓存机制

[微信公众号] 浏览器的缓存机制小结

[微信公众号] 浏览器缓存机制剖析

[RFC-9111] Expires

[MDN] Expires

[MDN] Cache-Control

[MDN] ETag

- +

Last-Modified与If-Modified-Since

Last-Modified是该资源文件最后一次更改时间,服务器会在ResponseHeader里返回,同时浏览器会将这个值保存起来,在下一次发送请求时,放到RequestHeader里的If-Modified-Since里,服务器在接收到后也会做比对,如果相同则命中协商缓存。

If-None-Match的优先级要高于If-Modified-Since,即:如果浏览器同时存在

两种协商缓存的区别

内存缓存与硬盘缓存

当我们打开一个新网页,服务器返回200,将资源发送给浏览器,浏览器做本地缓存

当我们刷新标签页,浏览器从内存缓存获得资源

当我们关闭标签页重新打开,浏览器从硬盘缓存获得资源

在浏览器中,浏览器会在js和图片等文件解析执行后直接存入内存缓存中,那么当刷新页面时只需直接从内存缓存中读取(MemoryCache);而css文件则会存入硬盘文件中,所以每次渲染页面都需要从硬盘读取缓存(DiskCache)。

用户对浏览器缓存的控制

参考资料

[稀土掘金] 彻底理解浏览器的缓存机制

[微信公众号] 浏览器的缓存机制小结

[微信公众号] 浏览器缓存机制剖析

[RFC-9111] Expires

[MDN] Expires

[MDN] Cache-Control

[MDN] ETag

+ diff --git a/article/深入理解浏览器运行原理.html b/article/深入理解浏览器运行原理.html index 887c0b9b..82ad5289 100644 --- a/article/深入理解浏览器运行原理.html +++ b/article/深入理解浏览器运行原理.html @@ -8,7 +8,7 @@ - + @@ -74,8 +74,8 @@

上述代码在控制台的输出为:

script enter
 defer script enter
 DOMContentLoaded enter
-

async属性

async属性也可以做到:让脚本异步加载而不阻塞DOM树的构建,它与defer的区别:

要使用async属性标记的script操作DOM,必须在其中使用DOMContentLoaded监听器的回调函数,在该事件触发(DOM树构建完毕)后,执行相应的回调函数

- +

async属性

async属性也可以做到:让脚本异步加载而不阻塞DOM树的构建,它与defer的区别:

要使用async属性标记的script操作DOM,必须在其中使用DOMContentLoaded监听器的回调函数,在该事件触发(DOM树构建完毕)后,执行相应的回调函数

+ diff --git a/assets/article_【2023】青训营 - 前端练习题汇总解析.md.87c3ec71.js b/assets/article_【2023】青训营 - 前端练习题汇总解析.md.8d7e9b9c.js similarity index 99% rename from assets/article_【2023】青训营 - 前端练习题汇总解析.md.87c3ec71.js rename to assets/article_【2023】青训营 - 前端练习题汇总解析.md.8d7e9b9c.js index fa96139d..64d950b8 100644 --- a/assets/article_【2023】青训营 - 前端练习题汇总解析.md.87c3ec71.js +++ b/assets/article_【2023】青训营 - 前端练习题汇总解析.md.8d7e9b9c.js @@ -1,4 +1,4 @@ -import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const A=JSON.parse('{"title":"【2023】青训营 - 前端练习题汇总解析","description":"","frontmatter":{},"headers":[{"level":2,"title":"选择题","slug":"选择题","link":"#选择题","children":[{"level":3,"title":"DAY 1","slug":"day-1","link":"#day-1","children":[]},{"level":3,"title":"DAY 2","slug":"day-2","link":"#day-2","children":[]},{"level":3,"title":"DAY 3","slug":"day-3","link":"#day-3","children":[]},{"level":3,"title":"DAY 4","slug":"day-4","link":"#day-4","children":[]},{"level":3,"title":"DAY 5","slug":"day-5","link":"#day-5","children":[]},{"level":3,"title":"DAY 6","slug":"day-6","link":"#day-6","children":[]},{"level":3,"title":"DAY 7","slug":"day-7","link":"#day-7","children":[]},{"level":3,"title":"DAY 8","slug":"day-8","link":"#day-8","children":[]},{"level":3,"title":"DAY 9","slug":"day-9","link":"#day-9","children":[]}]},{"level":2,"title":"编程题","slug":"编程题","link":"#编程题","children":[{"level":3,"title":"题目 1","slug":"题目-1","link":"#题目-1","children":[]},{"level":3,"title":"题目 2","slug":"题目-2","link":"#题目-2","children":[]},{"level":3,"title":"题目 3","slug":"题目-3","link":"#题目-3","children":[]}]}],"relativePath":"article/【2023】青训营 - 前端练习题汇总解析.md","lastUpdated":1676737739000}'),p={name:"article/【2023】青训营 - 前端练习题汇总解析.md"},e=l(`

【2023】青训营 - 前端练习题汇总解析

汇总了青训营官方账号每天发布的练习题,并且给出了答案、做了简单解析与知识扩充,有不足之处欢迎一起交流学习。

每天的选择题不同,而编程题是一样的,直接去Leetcode刷题即可。

选择题

DAY 1

题目描述

选择题 1:  
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const A=JSON.parse('{"title":"【2023】青训营 - 前端练习题汇总解析","description":"","frontmatter":{},"headers":[{"level":2,"title":"选择题","slug":"选择题","link":"#选择题","children":[{"level":3,"title":"DAY 1","slug":"day-1","link":"#day-1","children":[]},{"level":3,"title":"DAY 2","slug":"day-2","link":"#day-2","children":[]},{"level":3,"title":"DAY 3","slug":"day-3","link":"#day-3","children":[]},{"level":3,"title":"DAY 4","slug":"day-4","link":"#day-4","children":[]},{"level":3,"title":"DAY 5","slug":"day-5","link":"#day-5","children":[]},{"level":3,"title":"DAY 6","slug":"day-6","link":"#day-6","children":[]},{"level":3,"title":"DAY 7","slug":"day-7","link":"#day-7","children":[]},{"level":3,"title":"DAY 8","slug":"day-8","link":"#day-8","children":[]},{"level":3,"title":"DAY 9","slug":"day-9","link":"#day-9","children":[]}]},{"level":2,"title":"编程题","slug":"编程题","link":"#编程题","children":[{"level":3,"title":"题目 1","slug":"题目-1","link":"#题目-1","children":[]},{"level":3,"title":"题目 2","slug":"题目-2","link":"#题目-2","children":[]},{"level":3,"title":"题目 3","slug":"题目-3","link":"#题目-3","children":[]}]}],"relativePath":"article/【2023】青训营 - 前端练习题汇总解析.md","lastUpdated":1676979063000}'),p={name:"article/【2023】青训营 - 前端练习题汇总解析.md"},e=l(`

【2023】青训营 - 前端练习题汇总解析

汇总了青训营官方账号每天发布的练习题,并且给出了答案、做了简单解析与知识扩充,有不足之处欢迎一起交流学习。

每天的选择题不同,而编程题是一样的,直接去Leetcode刷题即可。

选择题

DAY 1

题目描述

选择题 1:  
 下列哪些是 HTML5 的新特性?  
 A. 语义标签  
 B. Canvas 绘图  
diff --git a/assets/article_【2023】青训营 - 前端练习题汇总解析.md.87c3ec71.lean.js b/assets/article_【2023】青训营 - 前端练习题汇总解析.md.8d7e9b9c.lean.js
similarity index 95%
rename from assets/article_【2023】青训营 - 前端练习题汇总解析.md.87c3ec71.lean.js
rename to assets/article_【2023】青训营 - 前端练习题汇总解析.md.8d7e9b9c.lean.js
index 468193b7..bd6e8b67 100644
--- a/assets/article_【2023】青训营 - 前端练习题汇总解析.md.87c3ec71.lean.js	
+++ b/assets/article_【2023】青训营 - 前端练习题汇总解析.md.8d7e9b9c.lean.js	
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const A=JSON.parse('{"title":"【2023】青训营 - 前端练习题汇总解析","description":"","frontmatter":{},"headers":[{"level":2,"title":"选择题","slug":"选择题","link":"#选择题","children":[{"level":3,"title":"DAY 1","slug":"day-1","link":"#day-1","children":[]},{"level":3,"title":"DAY 2","slug":"day-2","link":"#day-2","children":[]},{"level":3,"title":"DAY 3","slug":"day-3","link":"#day-3","children":[]},{"level":3,"title":"DAY 4","slug":"day-4","link":"#day-4","children":[]},{"level":3,"title":"DAY 5","slug":"day-5","link":"#day-5","children":[]},{"level":3,"title":"DAY 6","slug":"day-6","link":"#day-6","children":[]},{"level":3,"title":"DAY 7","slug":"day-7","link":"#day-7","children":[]},{"level":3,"title":"DAY 8","slug":"day-8","link":"#day-8","children":[]},{"level":3,"title":"DAY 9","slug":"day-9","link":"#day-9","children":[]}]},{"level":2,"title":"编程题","slug":"编程题","link":"#编程题","children":[{"level":3,"title":"题目 1","slug":"题目-1","link":"#题目-1","children":[]},{"level":3,"title":"题目 2","slug":"题目-2","link":"#题目-2","children":[]},{"level":3,"title":"题目 3","slug":"题目-3","link":"#题目-3","children":[]}]}],"relativePath":"article/【2023】青训营 - 前端练习题汇总解析.md","lastUpdated":1676737739000}'),p={name:"article/【2023】青训营 - 前端练习题汇总解析.md"},e=l("",150),o=[e];function r(c,t,i,y,C,d){return n(),a("div",null,o)}const b=s(p,[["render",r]]);export{A as __pageData,b as default};
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const A=JSON.parse('{"title":"【2023】青训营 - 前端练习题汇总解析","description":"","frontmatter":{},"headers":[{"level":2,"title":"选择题","slug":"选择题","link":"#选择题","children":[{"level":3,"title":"DAY 1","slug":"day-1","link":"#day-1","children":[]},{"level":3,"title":"DAY 2","slug":"day-2","link":"#day-2","children":[]},{"level":3,"title":"DAY 3","slug":"day-3","link":"#day-3","children":[]},{"level":3,"title":"DAY 4","slug":"day-4","link":"#day-4","children":[]},{"level":3,"title":"DAY 5","slug":"day-5","link":"#day-5","children":[]},{"level":3,"title":"DAY 6","slug":"day-6","link":"#day-6","children":[]},{"level":3,"title":"DAY 7","slug":"day-7","link":"#day-7","children":[]},{"level":3,"title":"DAY 8","slug":"day-8","link":"#day-8","children":[]},{"level":3,"title":"DAY 9","slug":"day-9","link":"#day-9","children":[]}]},{"level":2,"title":"编程题","slug":"编程题","link":"#编程题","children":[{"level":3,"title":"题目 1","slug":"题目-1","link":"#题目-1","children":[]},{"level":3,"title":"题目 2","slug":"题目-2","link":"#题目-2","children":[]},{"level":3,"title":"题目 3","slug":"题目-3","link":"#题目-3","children":[]}]}],"relativePath":"article/【2023】青训营 - 前端练习题汇总解析.md","lastUpdated":1676979063000}'),p={name:"article/【2023】青训营 - 前端练习题汇总解析.md"},e=l("",150),o=[e];function r(c,t,i,y,C,d){return n(),a("div",null,o)}const b=s(p,[["render",r]]);export{A as __pageData,b as default};
diff --git a/assets/article_【字节跳动】前端面试题总结.md.11aa2b5a.js b/assets/article_【字节跳动】前端面试题总结.md.8b64abc5.js
similarity index 99%
rename from assets/article_【字节跳动】前端面试题总结.md.11aa2b5a.js
rename to assets/article_【字节跳动】前端面试题总结.md.8b64abc5.js
index df369e70..5b942b4f 100644
--- a/assets/article_【字节跳动】前端面试题总结.md.11aa2b5a.js
+++ b/assets/article_【字节跳动】前端面试题总结.md.8b64abc5.js
@@ -1,4 +1,4 @@
-import{_ as s,o as a,c as n,a as l}from"./app.33820b61.js";const A=JSON.parse('{"title":"【字节跳动】前端面试题总结","description":"","frontmatter":{},"headers":[{"level":2,"title":"看代码说结果","slug":"看代码说结果","link":"#看代码说结果","children":[{"level":3,"title":"代码输出结果1","slug":"代码输出结果1","link":"#代码输出结果1","children":[]},{"level":3,"title":"代码输出结果2","slug":"代码输出结果2","link":"#代码输出结果2","children":[]},{"level":3,"title":"代码输出结果3","slug":"代码输出结果3","link":"#代码输出结果3","children":[]},{"level":3,"title":"代码输出结果4","slug":"代码输出结果4","link":"#代码输出结果4","children":[]},{"level":3,"title":"代码输出结果5","slug":"代码输出结果5","link":"#代码输出结果5","children":[]},{"level":3,"title":"代码输出结果6","slug":"代码输出结果6","link":"#代码输出结果6","children":[]},{"level":3,"title":"代码输出结果7","slug":"代码输出结果7","link":"#代码输出结果7","children":[]}]},{"level":2,"title":"问答题","slug":"问答题","link":"#问答题","children":[{"level":3,"title":"HTTP缓存的请求头与响应头有哪些","slug":"http缓存的请求头与响应头有哪些","link":"#http缓存的请求头与响应头有哪些","children":[]},{"level":3,"title":"宏任务与微任务有哪些区别?简述他们的应用场景","slug":"宏任务与微任务有哪些区别-简述他们的应用场景","link":"#宏任务与微任务有哪些区别-简述他们的应用场景","children":[]}]},{"level":2,"title":"算法","slug":"算法","link":"#算法","children":[]}],"relativePath":"article/【字节跳动】前端面试题总结.md","lastUpdated":1676737739000}'),p={name:"article/【字节跳动】前端面试题总结.md"},e=l(`

【字节跳动】前端面试题总结

看代码说结果

代码输出结果1

js
console.log(['1', '2', '3'].map(parseInt))
+import{_ as s,o as a,c as n,a as l}from"./app.33820b61.js";const A=JSON.parse('{"title":"【字节跳动】前端面试题总结","description":"","frontmatter":{},"headers":[{"level":2,"title":"看代码说结果","slug":"看代码说结果","link":"#看代码说结果","children":[{"level":3,"title":"代码输出结果1","slug":"代码输出结果1","link":"#代码输出结果1","children":[]},{"level":3,"title":"代码输出结果2","slug":"代码输出结果2","link":"#代码输出结果2","children":[]},{"level":3,"title":"代码输出结果3","slug":"代码输出结果3","link":"#代码输出结果3","children":[]},{"level":3,"title":"代码输出结果4","slug":"代码输出结果4","link":"#代码输出结果4","children":[]},{"level":3,"title":"代码输出结果5","slug":"代码输出结果5","link":"#代码输出结果5","children":[]},{"level":3,"title":"代码输出结果6","slug":"代码输出结果6","link":"#代码输出结果6","children":[]},{"level":3,"title":"代码输出结果7","slug":"代码输出结果7","link":"#代码输出结果7","children":[]}]},{"level":2,"title":"问答题","slug":"问答题","link":"#问答题","children":[{"level":3,"title":"HTTP缓存的请求头与响应头有哪些","slug":"http缓存的请求头与响应头有哪些","link":"#http缓存的请求头与响应头有哪些","children":[]},{"level":3,"title":"宏任务与微任务有哪些区别?简述他们的应用场景","slug":"宏任务与微任务有哪些区别-简述他们的应用场景","link":"#宏任务与微任务有哪些区别-简述他们的应用场景","children":[]}]},{"level":2,"title":"算法","slug":"算法","link":"#算法","children":[]}],"relativePath":"article/【字节跳动】前端面试题总结.md","lastUpdated":1676979063000}'),p={name:"article/【字节跳动】前端面试题总结.md"},e=l(`

【字节跳动】前端面试题总结

看代码说结果

代码输出结果1

js
console.log(['1', '2', '3'].map(parseInt))
 
[1, NaN, NaN]
 

代码输出结果2

js
let [a = 1, b] = []
 console.log(a, b)
diff --git a/assets/article_【字节跳动】前端面试题总结.md.11aa2b5a.lean.js b/assets/article_【字节跳动】前端面试题总结.md.8b64abc5.lean.js
similarity index 96%
rename from assets/article_【字节跳动】前端面试题总结.md.11aa2b5a.lean.js
rename to assets/article_【字节跳动】前端面试题总结.md.8b64abc5.lean.js
index 1d7db4ae..4a5123a8 100644
--- a/assets/article_【字节跳动】前端面试题总结.md.11aa2b5a.lean.js
+++ b/assets/article_【字节跳动】前端面试题总结.md.8b64abc5.lean.js
@@ -1 +1 @@
-import{_ as s,o as a,c as n,a as l}from"./app.33820b61.js";const A=JSON.parse('{"title":"【字节跳动】前端面试题总结","description":"","frontmatter":{},"headers":[{"level":2,"title":"看代码说结果","slug":"看代码说结果","link":"#看代码说结果","children":[{"level":3,"title":"代码输出结果1","slug":"代码输出结果1","link":"#代码输出结果1","children":[]},{"level":3,"title":"代码输出结果2","slug":"代码输出结果2","link":"#代码输出结果2","children":[]},{"level":3,"title":"代码输出结果3","slug":"代码输出结果3","link":"#代码输出结果3","children":[]},{"level":3,"title":"代码输出结果4","slug":"代码输出结果4","link":"#代码输出结果4","children":[]},{"level":3,"title":"代码输出结果5","slug":"代码输出结果5","link":"#代码输出结果5","children":[]},{"level":3,"title":"代码输出结果6","slug":"代码输出结果6","link":"#代码输出结果6","children":[]},{"level":3,"title":"代码输出结果7","slug":"代码输出结果7","link":"#代码输出结果7","children":[]}]},{"level":2,"title":"问答题","slug":"问答题","link":"#问答题","children":[{"level":3,"title":"HTTP缓存的请求头与响应头有哪些","slug":"http缓存的请求头与响应头有哪些","link":"#http缓存的请求头与响应头有哪些","children":[]},{"level":3,"title":"宏任务与微任务有哪些区别?简述他们的应用场景","slug":"宏任务与微任务有哪些区别-简述他们的应用场景","link":"#宏任务与微任务有哪些区别-简述他们的应用场景","children":[]}]},{"level":2,"title":"算法","slug":"算法","link":"#算法","children":[]}],"relativePath":"article/【字节跳动】前端面试题总结.md","lastUpdated":1676737739000}'),p={name:"article/【字节跳动】前端面试题总结.md"},e=l("",36),o=[e];function r(c,t,i,y,D,C){return a(),n("div",null,o)}const d=s(p,[["render",r]]);export{A as __pageData,d as default};
+import{_ as s,o as a,c as n,a as l}from"./app.33820b61.js";const A=JSON.parse('{"title":"【字节跳动】前端面试题总结","description":"","frontmatter":{},"headers":[{"level":2,"title":"看代码说结果","slug":"看代码说结果","link":"#看代码说结果","children":[{"level":3,"title":"代码输出结果1","slug":"代码输出结果1","link":"#代码输出结果1","children":[]},{"level":3,"title":"代码输出结果2","slug":"代码输出结果2","link":"#代码输出结果2","children":[]},{"level":3,"title":"代码输出结果3","slug":"代码输出结果3","link":"#代码输出结果3","children":[]},{"level":3,"title":"代码输出结果4","slug":"代码输出结果4","link":"#代码输出结果4","children":[]},{"level":3,"title":"代码输出结果5","slug":"代码输出结果5","link":"#代码输出结果5","children":[]},{"level":3,"title":"代码输出结果6","slug":"代码输出结果6","link":"#代码输出结果6","children":[]},{"level":3,"title":"代码输出结果7","slug":"代码输出结果7","link":"#代码输出结果7","children":[]}]},{"level":2,"title":"问答题","slug":"问答题","link":"#问答题","children":[{"level":3,"title":"HTTP缓存的请求头与响应头有哪些","slug":"http缓存的请求头与响应头有哪些","link":"#http缓存的请求头与响应头有哪些","children":[]},{"level":3,"title":"宏任务与微任务有哪些区别?简述他们的应用场景","slug":"宏任务与微任务有哪些区别-简述他们的应用场景","link":"#宏任务与微任务有哪些区别-简述他们的应用场景","children":[]}]},{"level":2,"title":"算法","slug":"算法","link":"#算法","children":[]}],"relativePath":"article/【字节跳动】前端面试题总结.md","lastUpdated":1676979063000}'),p={name:"article/【字节跳动】前端面试题总结.md"},e=l("",36),o=[e];function r(c,t,i,y,D,C){return a(),n("div",null,o)}const d=s(p,[["render",r]]);export{A as __pageData,d as default};
diff --git a/assets/article_【快手】深入理解前端面试题.md.5f4ef7a3.js b/assets/article_【快手】深入理解前端面试题.md.9bd6db9f.js
similarity index 99%
rename from assets/article_【快手】深入理解前端面试题.md.5f4ef7a3.js
rename to assets/article_【快手】深入理解前端面试题.md.9bd6db9f.js
index d600cbeb..8cd90cd2 100644
--- a/assets/article_【快手】深入理解前端面试题.md.5f4ef7a3.js
+++ b/assets/article_【快手】深入理解前端面试题.md.9bd6db9f.js
@@ -1,4 +1,4 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const A=JSON.parse('{"title":"【快手】深入理解前端面试题","description":"","frontmatter":{},"headers":[{"level":2,"title":"快手一面","slug":"快手一面","link":"#快手一面","children":[{"level":3,"title":"Vue生命周期","slug":"vue生命周期","link":"#vue生命周期","children":[]},{"level":3,"title":"网络请求一般在什么时候发起,为什么","slug":"网络请求一般在什么时候发起-为什么","link":"#网络请求一般在什么时候发起-为什么","children":[]},{"level":3,"title":"setup的执行时机相当于哪个生命周期","slug":"setup的执行时机相当于哪个生命周期","link":"#setup的执行时机相当于哪个生命周期","children":[]},{"level":3,"title":"Vue2和Vue3的响应式原理","slug":"vue2和vue3的响应式原理","link":"#vue2和vue3的响应式原理","children":[]},{"level":3,"title":"Proxy相比于defineProperty有何优势","slug":"proxy相比于defineproperty有何优势","link":"#proxy相比于defineproperty有何优势","children":[]},{"level":3,"title":"Vue3数据双向绑定原理","slug":"vue3数据双向绑定原理","link":"#vue3数据双向绑定原理","children":[]},{"level":3,"title":"ref与reactive区别与适用场景","slug":"ref与reactive区别与适用场景","link":"#ref与reactive区别与适用场景","children":[]},{"level":3,"title":"Vue3功能上相比于Vue2有哪些优点","slug":"vue3功能上相比于vue2有哪些优点","link":"#vue3功能上相比于vue2有哪些优点","children":[]},{"level":3,"title":"Vue组件传参方法","slug":"vue组件传参方法","link":"#vue组件传参方法","children":[]},{"level":3,"title":"Vuex异步操作如何同时修改多个state","slug":"vuex异步操作如何同时修改多个state","link":"#vuex异步操作如何同时修改多个state","children":[]},{"level":3,"title":"ES6特性了解哪些","slug":"es6特性了解哪些","link":"#es6特性了解哪些","children":[]},{"level":3,"title":"let & const的特性","slug":"let-const的特性","link":"#let-const的特性","children":[]},{"level":3,"title":"Promise介绍一下","slug":"promise介绍一下","link":"#promise介绍一下","children":[]},{"level":3,"title":"Promise.all .race .any功能及区别","slug":"promise-all-race-any功能及区别","link":"#promise-all-race-any功能及区别","children":[]},{"level":3,"title":"Promise看代码写结果","slug":"promise看代码写结果","link":"#promise看代码写结果","children":[]},{"level":3,"title":"手写Promise.all()","slug":"手写promise-all","link":"#手写promise-all","children":[]},{"level":3,"title":"Cookie localStorage SessionStorage区别及使用场景","slug":"cookie-localstorage-sessionstorage区别及使用场景","link":"#cookie-localstorage-sessionstorage区别及使用场景","children":[]},{"level":3,"title":"localStorage常用方法","slug":"localstorage常用方法","link":"#localstorage常用方法","children":[]},{"level":3,"title":"跨域解决方法","slug":"跨域解决方法","link":"#跨域解决方法","children":[]},{"level":3,"title":"介绍一下事件循环","slug":"介绍一下事件循环","link":"#介绍一下事件循环","children":[]},{"level":3,"title":"事件循环代码运行结果","slug":"事件循环代码运行结果","link":"#事件循环代码运行结果","children":[]},{"level":3,"title":"介绍一下Flex布局","slug":"介绍一下flex布局","link":"#介绍一下flex布局","children":[]}]},{"level":2,"title":"快手二面","slug":"快手二面","link":"#快手二面","children":[{"level":3,"title":"CSS主题切换方案","slug":"css主题切换方案","link":"#css主题切换方案","children":[]},{"level":3,"title":"Proxy与defineProperty实现数据劫持","slug":"proxy与defineproperty实现数据劫持","link":"#proxy与defineproperty实现数据劫持","children":[]},{"level":3,"title":"算法: 两数之和-修改版","slug":"算法-两数之和-修改版","link":"#算法-两数之和-修改版","children":[]}]}],"relativePath":"article/【快手】深入理解前端面试题.md","lastUpdated":1676737739000}'),p={name:"article/【快手】深入理解前端面试题.md"},e=l(`

【快手】深入理解前端面试题

快手一面

Vue生命周期

beforeCreate created beforeMount mounted

beforeUpdate updated

beforeDestory destoryed

Vue3移除了beforeCreate created两个声明周期钩子,这是因为setup发生在开始创建组件之前,在beforeCreatecreated之前执行

可以在setup中使用的生命周期函数:onMounted onUpdated onUnmounted onBeforeUpdate这几个,

Vue 生命周期

网络请求一般在什么时候发起,为什么

越早越好,一般是放在createdonMounted或者setup

  • created(vue2) 此时组件内的基本数据已经创建好,组件的模板结构尚未生成
  • mounted(vue2) onMounted(vue3) 组件挂载到DOM树上,可以获取到DOM
  • setup(vue3) 时机要早于beforeCreatedcreated 所以在setup中发起网络请求也可以

setup的执行时机相当于哪个生命周期

setup的执行要早于beforeCreatedcreated,可以认为相当于这两个生命周期

Vue2和Vue3的响应式原理

Vue2响应式原理

全部使用Object.defineProperty()中的set与get函数

Vue3响应式原理

ref使用的是Object.defineProperty(),而reactive使用的是Proxy

Proxy可以直接深度代理一个对象,通过设置handler中的捕获器可以对对象创建一个代理,将各种行为监听并且同步到对象本身上

js
const obj = {
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const A=JSON.parse('{"title":"【快手】深入理解前端面试题","description":"","frontmatter":{},"headers":[{"level":2,"title":"快手一面","slug":"快手一面","link":"#快手一面","children":[{"level":3,"title":"Vue生命周期","slug":"vue生命周期","link":"#vue生命周期","children":[]},{"level":3,"title":"网络请求一般在什么时候发起,为什么","slug":"网络请求一般在什么时候发起-为什么","link":"#网络请求一般在什么时候发起-为什么","children":[]},{"level":3,"title":"setup的执行时机相当于哪个生命周期","slug":"setup的执行时机相当于哪个生命周期","link":"#setup的执行时机相当于哪个生命周期","children":[]},{"level":3,"title":"Vue2和Vue3的响应式原理","slug":"vue2和vue3的响应式原理","link":"#vue2和vue3的响应式原理","children":[]},{"level":3,"title":"Proxy相比于defineProperty有何优势","slug":"proxy相比于defineproperty有何优势","link":"#proxy相比于defineproperty有何优势","children":[]},{"level":3,"title":"Vue3数据双向绑定原理","slug":"vue3数据双向绑定原理","link":"#vue3数据双向绑定原理","children":[]},{"level":3,"title":"ref与reactive区别与适用场景","slug":"ref与reactive区别与适用场景","link":"#ref与reactive区别与适用场景","children":[]},{"level":3,"title":"Vue3功能上相比于Vue2有哪些优点","slug":"vue3功能上相比于vue2有哪些优点","link":"#vue3功能上相比于vue2有哪些优点","children":[]},{"level":3,"title":"Vue组件传参方法","slug":"vue组件传参方法","link":"#vue组件传参方法","children":[]},{"level":3,"title":"Vuex异步操作如何同时修改多个state","slug":"vuex异步操作如何同时修改多个state","link":"#vuex异步操作如何同时修改多个state","children":[]},{"level":3,"title":"ES6特性了解哪些","slug":"es6特性了解哪些","link":"#es6特性了解哪些","children":[]},{"level":3,"title":"let & const的特性","slug":"let-const的特性","link":"#let-const的特性","children":[]},{"level":3,"title":"Promise介绍一下","slug":"promise介绍一下","link":"#promise介绍一下","children":[]},{"level":3,"title":"Promise.all .race .any功能及区别","slug":"promise-all-race-any功能及区别","link":"#promise-all-race-any功能及区别","children":[]},{"level":3,"title":"Promise看代码写结果","slug":"promise看代码写结果","link":"#promise看代码写结果","children":[]},{"level":3,"title":"手写Promise.all()","slug":"手写promise-all","link":"#手写promise-all","children":[]},{"level":3,"title":"Cookie localStorage SessionStorage区别及使用场景","slug":"cookie-localstorage-sessionstorage区别及使用场景","link":"#cookie-localstorage-sessionstorage区别及使用场景","children":[]},{"level":3,"title":"localStorage常用方法","slug":"localstorage常用方法","link":"#localstorage常用方法","children":[]},{"level":3,"title":"跨域解决方法","slug":"跨域解决方法","link":"#跨域解决方法","children":[]},{"level":3,"title":"介绍一下事件循环","slug":"介绍一下事件循环","link":"#介绍一下事件循环","children":[]},{"level":3,"title":"事件循环代码运行结果","slug":"事件循环代码运行结果","link":"#事件循环代码运行结果","children":[]},{"level":3,"title":"介绍一下Flex布局","slug":"介绍一下flex布局","link":"#介绍一下flex布局","children":[]}]},{"level":2,"title":"快手二面","slug":"快手二面","link":"#快手二面","children":[{"level":3,"title":"CSS主题切换方案","slug":"css主题切换方案","link":"#css主题切换方案","children":[]},{"level":3,"title":"Proxy与defineProperty实现数据劫持","slug":"proxy与defineproperty实现数据劫持","link":"#proxy与defineproperty实现数据劫持","children":[]},{"level":3,"title":"算法: 两数之和-修改版","slug":"算法-两数之和-修改版","link":"#算法-两数之和-修改版","children":[]}]}],"relativePath":"article/【快手】深入理解前端面试题.md","lastUpdated":1676979063000}'),p={name:"article/【快手】深入理解前端面试题.md"},e=l(`

【快手】深入理解前端面试题

快手一面

Vue生命周期

beforeCreate created beforeMount mounted

beforeUpdate updated

beforeDestory destoryed

Vue3移除了beforeCreate created两个声明周期钩子,这是因为setup发生在开始创建组件之前,在beforeCreatecreated之前执行

可以在setup中使用的生命周期函数:onMounted onUpdated onUnmounted onBeforeUpdate这几个,

Vue 生命周期

网络请求一般在什么时候发起,为什么

越早越好,一般是放在createdonMounted或者setup

  • created(vue2) 此时组件内的基本数据已经创建好,组件的模板结构尚未生成
  • mounted(vue2) onMounted(vue3) 组件挂载到DOM树上,可以获取到DOM
  • setup(vue3) 时机要早于beforeCreatedcreated 所以在setup中发起网络请求也可以

setup的执行时机相当于哪个生命周期

setup的执行要早于beforeCreatedcreated,可以认为相当于这两个生命周期

Vue2和Vue3的响应式原理

Vue2响应式原理

全部使用Object.defineProperty()中的set与get函数

Vue3响应式原理

ref使用的是Object.defineProperty(),而reactive使用的是Proxy

Proxy可以直接深度代理一个对象,通过设置handler中的捕获器可以对对象创建一个代理,将各种行为监听并且同步到对象本身上

js
const obj = {
   name: 'Ziu',
   age: 18
 }
diff --git a/assets/article_【快手】深入理解前端面试题.md.5f4ef7a3.lean.js b/assets/article_【快手】深入理解前端面试题.md.9bd6db9f.lean.js
similarity index 98%
rename from assets/article_【快手】深入理解前端面试题.md.5f4ef7a3.lean.js
rename to assets/article_【快手】深入理解前端面试题.md.9bd6db9f.lean.js
index 757340e0..7c356af8 100644
--- a/assets/article_【快手】深入理解前端面试题.md.5f4ef7a3.lean.js
+++ b/assets/article_【快手】深入理解前端面试题.md.9bd6db9f.lean.js
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const A=JSON.parse('{"title":"【快手】深入理解前端面试题","description":"","frontmatter":{},"headers":[{"level":2,"title":"快手一面","slug":"快手一面","link":"#快手一面","children":[{"level":3,"title":"Vue生命周期","slug":"vue生命周期","link":"#vue生命周期","children":[]},{"level":3,"title":"网络请求一般在什么时候发起,为什么","slug":"网络请求一般在什么时候发起-为什么","link":"#网络请求一般在什么时候发起-为什么","children":[]},{"level":3,"title":"setup的执行时机相当于哪个生命周期","slug":"setup的执行时机相当于哪个生命周期","link":"#setup的执行时机相当于哪个生命周期","children":[]},{"level":3,"title":"Vue2和Vue3的响应式原理","slug":"vue2和vue3的响应式原理","link":"#vue2和vue3的响应式原理","children":[]},{"level":3,"title":"Proxy相比于defineProperty有何优势","slug":"proxy相比于defineproperty有何优势","link":"#proxy相比于defineproperty有何优势","children":[]},{"level":3,"title":"Vue3数据双向绑定原理","slug":"vue3数据双向绑定原理","link":"#vue3数据双向绑定原理","children":[]},{"level":3,"title":"ref与reactive区别与适用场景","slug":"ref与reactive区别与适用场景","link":"#ref与reactive区别与适用场景","children":[]},{"level":3,"title":"Vue3功能上相比于Vue2有哪些优点","slug":"vue3功能上相比于vue2有哪些优点","link":"#vue3功能上相比于vue2有哪些优点","children":[]},{"level":3,"title":"Vue组件传参方法","slug":"vue组件传参方法","link":"#vue组件传参方法","children":[]},{"level":3,"title":"Vuex异步操作如何同时修改多个state","slug":"vuex异步操作如何同时修改多个state","link":"#vuex异步操作如何同时修改多个state","children":[]},{"level":3,"title":"ES6特性了解哪些","slug":"es6特性了解哪些","link":"#es6特性了解哪些","children":[]},{"level":3,"title":"let & const的特性","slug":"let-const的特性","link":"#let-const的特性","children":[]},{"level":3,"title":"Promise介绍一下","slug":"promise介绍一下","link":"#promise介绍一下","children":[]},{"level":3,"title":"Promise.all .race .any功能及区别","slug":"promise-all-race-any功能及区别","link":"#promise-all-race-any功能及区别","children":[]},{"level":3,"title":"Promise看代码写结果","slug":"promise看代码写结果","link":"#promise看代码写结果","children":[]},{"level":3,"title":"手写Promise.all()","slug":"手写promise-all","link":"#手写promise-all","children":[]},{"level":3,"title":"Cookie localStorage SessionStorage区别及使用场景","slug":"cookie-localstorage-sessionstorage区别及使用场景","link":"#cookie-localstorage-sessionstorage区别及使用场景","children":[]},{"level":3,"title":"localStorage常用方法","slug":"localstorage常用方法","link":"#localstorage常用方法","children":[]},{"level":3,"title":"跨域解决方法","slug":"跨域解决方法","link":"#跨域解决方法","children":[]},{"level":3,"title":"介绍一下事件循环","slug":"介绍一下事件循环","link":"#介绍一下事件循环","children":[]},{"level":3,"title":"事件循环代码运行结果","slug":"事件循环代码运行结果","link":"#事件循环代码运行结果","children":[]},{"level":3,"title":"介绍一下Flex布局","slug":"介绍一下flex布局","link":"#介绍一下flex布局","children":[]}]},{"level":2,"title":"快手二面","slug":"快手二面","link":"#快手二面","children":[{"level":3,"title":"CSS主题切换方案","slug":"css主题切换方案","link":"#css主题切换方案","children":[]},{"level":3,"title":"Proxy与defineProperty实现数据劫持","slug":"proxy与defineproperty实现数据劫持","link":"#proxy与defineproperty实现数据劫持","children":[]},{"level":3,"title":"算法: 两数之和-修改版","slug":"算法-两数之和-修改版","link":"#算法-两数之和-修改版","children":[]}]}],"relativePath":"article/【快手】深入理解前端面试题.md","lastUpdated":1676737739000}'),p={name:"article/【快手】深入理解前端面试题.md"},e=l("",87),o=[e];function r(c,t,y,F,i,D){return n(),a("div",null,o)}const d=s(p,[["render",r]]);export{A as __pageData,d as default};
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const A=JSON.parse('{"title":"【快手】深入理解前端面试题","description":"","frontmatter":{},"headers":[{"level":2,"title":"快手一面","slug":"快手一面","link":"#快手一面","children":[{"level":3,"title":"Vue生命周期","slug":"vue生命周期","link":"#vue生命周期","children":[]},{"level":3,"title":"网络请求一般在什么时候发起,为什么","slug":"网络请求一般在什么时候发起-为什么","link":"#网络请求一般在什么时候发起-为什么","children":[]},{"level":3,"title":"setup的执行时机相当于哪个生命周期","slug":"setup的执行时机相当于哪个生命周期","link":"#setup的执行时机相当于哪个生命周期","children":[]},{"level":3,"title":"Vue2和Vue3的响应式原理","slug":"vue2和vue3的响应式原理","link":"#vue2和vue3的响应式原理","children":[]},{"level":3,"title":"Proxy相比于defineProperty有何优势","slug":"proxy相比于defineproperty有何优势","link":"#proxy相比于defineproperty有何优势","children":[]},{"level":3,"title":"Vue3数据双向绑定原理","slug":"vue3数据双向绑定原理","link":"#vue3数据双向绑定原理","children":[]},{"level":3,"title":"ref与reactive区别与适用场景","slug":"ref与reactive区别与适用场景","link":"#ref与reactive区别与适用场景","children":[]},{"level":3,"title":"Vue3功能上相比于Vue2有哪些优点","slug":"vue3功能上相比于vue2有哪些优点","link":"#vue3功能上相比于vue2有哪些优点","children":[]},{"level":3,"title":"Vue组件传参方法","slug":"vue组件传参方法","link":"#vue组件传参方法","children":[]},{"level":3,"title":"Vuex异步操作如何同时修改多个state","slug":"vuex异步操作如何同时修改多个state","link":"#vuex异步操作如何同时修改多个state","children":[]},{"level":3,"title":"ES6特性了解哪些","slug":"es6特性了解哪些","link":"#es6特性了解哪些","children":[]},{"level":3,"title":"let & const的特性","slug":"let-const的特性","link":"#let-const的特性","children":[]},{"level":3,"title":"Promise介绍一下","slug":"promise介绍一下","link":"#promise介绍一下","children":[]},{"level":3,"title":"Promise.all .race .any功能及区别","slug":"promise-all-race-any功能及区别","link":"#promise-all-race-any功能及区别","children":[]},{"level":3,"title":"Promise看代码写结果","slug":"promise看代码写结果","link":"#promise看代码写结果","children":[]},{"level":3,"title":"手写Promise.all()","slug":"手写promise-all","link":"#手写promise-all","children":[]},{"level":3,"title":"Cookie localStorage SessionStorage区别及使用场景","slug":"cookie-localstorage-sessionstorage区别及使用场景","link":"#cookie-localstorage-sessionstorage区别及使用场景","children":[]},{"level":3,"title":"localStorage常用方法","slug":"localstorage常用方法","link":"#localstorage常用方法","children":[]},{"level":3,"title":"跨域解决方法","slug":"跨域解决方法","link":"#跨域解决方法","children":[]},{"level":3,"title":"介绍一下事件循环","slug":"介绍一下事件循环","link":"#介绍一下事件循环","children":[]},{"level":3,"title":"事件循环代码运行结果","slug":"事件循环代码运行结果","link":"#事件循环代码运行结果","children":[]},{"level":3,"title":"介绍一下Flex布局","slug":"介绍一下flex布局","link":"#介绍一下flex布局","children":[]}]},{"level":2,"title":"快手二面","slug":"快手二面","link":"#快手二面","children":[{"level":3,"title":"CSS主题切换方案","slug":"css主题切换方案","link":"#css主题切换方案","children":[]},{"level":3,"title":"Proxy与defineProperty实现数据劫持","slug":"proxy与defineproperty实现数据劫持","link":"#proxy与defineproperty实现数据劫持","children":[]},{"level":3,"title":"算法: 两数之和-修改版","slug":"算法-两数之和-修改版","link":"#算法-两数之和-修改版","children":[]}]}],"relativePath":"article/【快手】深入理解前端面试题.md","lastUpdated":1676979063000}'),p={name:"article/【快手】深入理解前端面试题.md"},e=l("",87),o=[e];function r(c,t,y,F,i,D){return n(),a("div",null,o)}const d=s(p,[["render",r]]);export{A as __pageData,d as default};
diff --git a/assets/article_【用友金融】前端面试题总结.md.69243f39.js b/assets/article_【用友金融】前端面试题总结.md.8730c019.js
similarity index 99%
rename from assets/article_【用友金融】前端面试题总结.md.69243f39.js
rename to assets/article_【用友金融】前端面试题总结.md.8730c019.js
index f31eac51..698221da 100644
--- a/assets/article_【用友金融】前端面试题总结.md.69243f39.js
+++ b/assets/article_【用友金融】前端面试题总结.md.8730c019.js
@@ -1,4 +1,4 @@
-import{_ as s,o as a,c as n,a as l}from"./app.33820b61.js";const D=JSON.parse('{"title":"【用友金融】前端面试题总结","description":"","frontmatter":{},"headers":[{"level":2,"title":"回流与重绘","slug":"回流与重绘","link":"#回流与重绘","children":[]},{"level":2,"title":"CSS属性","slug":"css属性","link":"#css属性","children":[]},{"level":2,"title":"函数执行结果","slug":"函数执行结果","link":"#函数执行结果","children":[{"level":3,"title":"题目1","slug":"题目1","link":"#题目1","children":[]},{"level":3,"title":"题目2","slug":"题目2","link":"#题目2","children":[]},{"level":3,"title":"题目3","slug":"题目3","link":"#题目3","children":[]},{"level":3,"title":"题目4","slug":"题目4","link":"#题目4","children":[]},{"level":3,"title":"题目5","slug":"题目5","link":"#题目5","children":[]},{"level":3,"title":"题目6","slug":"题目6","link":"#题目6","children":[]},{"level":3,"title":"题目7","slug":"题目7","link":"#题目7","children":[]},{"level":3,"title":"题目8","slug":"题目8","link":"#题目8","children":[]}]},{"level":2,"title":"CSS权重的优先级","slug":"css权重的优先级","link":"#css权重的优先级","children":[]},{"level":2,"title":"HTTP状态码","slug":"http状态码","link":"#http状态码","children":[]},{"level":2,"title":"BFC(块级格式上下文)","slug":"bfc-块级格式上下文","link":"#bfc-块级格式上下文","children":[]},{"level":2,"title":"元素浮动","slug":"元素浮动","link":"#元素浮动","children":[]},{"level":2,"title":"HTTP请求方法","slug":"http请求方法","link":"#http请求方法","children":[]},{"level":2,"title":"跨域问题","slug":"跨域问题","link":"#跨域问题","children":[]},{"level":2,"title":"了解Webpack的哪些配置项","slug":"了解webpack的哪些配置项","link":"#了解webpack的哪些配置项","children":[]},{"level":2,"title":"判断变量类型","slug":"判断变量类型","link":"#判断变量类型","children":[]},{"level":2,"title":"JS浮点数相加精度问题","slug":"js浮点数相加精度问题","link":"#js浮点数相加精度问题","children":[]},{"level":2,"title":"简单讲讲Vue Router原理","slug":"简单讲讲vue-router原理","link":"#简单讲讲vue-router原理","children":[]},{"level":2,"title":"ES6熟悉吗","slug":"es6熟悉吗","link":"#es6熟悉吗","children":[]},{"level":2,"title":"CSS如何实现水平居中与垂直居中","slug":"css如何实现水平居中与垂直居中","link":"#css如何实现水平居中与垂直居中","children":[]}],"relativePath":"article/【用友金融】前端面试题总结.md","lastUpdated":1676737739000}'),e={name:"article/【用友金融】前端面试题总结.md"},p=l(`

【用友金融】前端面试题总结

回流与重绘

下列关于回流和重绘的说法错误的是

  • 回流的性能开销大于重绘的性能开销

  • 当页面结构、尺寸等改变时会发生回流

  • 回流一定会引起重绘,重绘也一定会引起回流(x)

  • 当页面结构不改变只是样式发生改变时会发生重绘,例如背景颜色改变时会发生重绘

  • display: none 指的是元素完全不陈列出来,不占据空间,涉及到了DOM结构,故产生reflow与repaint

  • visibility: hidden 指的是元素不可见但存在,保留空间,不影响结构,故只产生repaint,但不可触发绑定事件

  • opacity: 0 指的是元素不可见但存在,保留空间,不影响结构,并且,如果该元素已经绑定一些事件,如click事件,那么点击该区域,也能触发点击事件的

CSS属性

下列选项中哪个描述对于visibility: hidden;与display: none;是正确的

  • visibility属性不可继承
  • visibility: hidden; 不占据页面空间
  • display: none; 不占据页面空间(√)
  • 都无法通过DOM交互

函数执行结果

题目1

js
(function () {
+import{_ as s,o as a,c as n,a as l}from"./app.33820b61.js";const D=JSON.parse('{"title":"【用友金融】前端面试题总结","description":"","frontmatter":{},"headers":[{"level":2,"title":"回流与重绘","slug":"回流与重绘","link":"#回流与重绘","children":[]},{"level":2,"title":"CSS属性","slug":"css属性","link":"#css属性","children":[]},{"level":2,"title":"函数执行结果","slug":"函数执行结果","link":"#函数执行结果","children":[{"level":3,"title":"题目1","slug":"题目1","link":"#题目1","children":[]},{"level":3,"title":"题目2","slug":"题目2","link":"#题目2","children":[]},{"level":3,"title":"题目3","slug":"题目3","link":"#题目3","children":[]},{"level":3,"title":"题目4","slug":"题目4","link":"#题目4","children":[]},{"level":3,"title":"题目5","slug":"题目5","link":"#题目5","children":[]},{"level":3,"title":"题目6","slug":"题目6","link":"#题目6","children":[]},{"level":3,"title":"题目7","slug":"题目7","link":"#题目7","children":[]},{"level":3,"title":"题目8","slug":"题目8","link":"#题目8","children":[]}]},{"level":2,"title":"CSS权重的优先级","slug":"css权重的优先级","link":"#css权重的优先级","children":[]},{"level":2,"title":"HTTP状态码","slug":"http状态码","link":"#http状态码","children":[]},{"level":2,"title":"BFC(块级格式上下文)","slug":"bfc-块级格式上下文","link":"#bfc-块级格式上下文","children":[]},{"level":2,"title":"元素浮动","slug":"元素浮动","link":"#元素浮动","children":[]},{"level":2,"title":"HTTP请求方法","slug":"http请求方法","link":"#http请求方法","children":[]},{"level":2,"title":"跨域问题","slug":"跨域问题","link":"#跨域问题","children":[]},{"level":2,"title":"了解Webpack的哪些配置项","slug":"了解webpack的哪些配置项","link":"#了解webpack的哪些配置项","children":[]},{"level":2,"title":"判断变量类型","slug":"判断变量类型","link":"#判断变量类型","children":[]},{"level":2,"title":"JS浮点数相加精度问题","slug":"js浮点数相加精度问题","link":"#js浮点数相加精度问题","children":[]},{"level":2,"title":"简单讲讲Vue Router原理","slug":"简单讲讲vue-router原理","link":"#简单讲讲vue-router原理","children":[]},{"level":2,"title":"ES6熟悉吗","slug":"es6熟悉吗","link":"#es6熟悉吗","children":[]},{"level":2,"title":"CSS如何实现水平居中与垂直居中","slug":"css如何实现水平居中与垂直居中","link":"#css如何实现水平居中与垂直居中","children":[]}],"relativePath":"article/【用友金融】前端面试题总结.md","lastUpdated":1676979063000}'),e={name:"article/【用友金融】前端面试题总结.md"},p=l(`

【用友金融】前端面试题总结

回流与重绘

下列关于回流和重绘的说法错误的是

  • 回流的性能开销大于重绘的性能开销

  • 当页面结构、尺寸等改变时会发生回流

  • 回流一定会引起重绘,重绘也一定会引起回流(x)

  • 当页面结构不改变只是样式发生改变时会发生重绘,例如背景颜色改变时会发生重绘

  • display: none 指的是元素完全不陈列出来,不占据空间,涉及到了DOM结构,故产生reflow与repaint

  • visibility: hidden 指的是元素不可见但存在,保留空间,不影响结构,故只产生repaint,但不可触发绑定事件

  • opacity: 0 指的是元素不可见但存在,保留空间,不影响结构,并且,如果该元素已经绑定一些事件,如click事件,那么点击该区域,也能触发点击事件的

CSS属性

下列选项中哪个描述对于visibility: hidden;与display: none;是正确的

  • visibility属性不可继承
  • visibility: hidden; 不占据页面空间
  • display: none; 不占据页面空间(√)
  • 都无法通过DOM交互

函数执行结果

题目1

js
(function () {
   var a = (b = 5);
 })();
 
diff --git a/assets/article_【用友金融】前端面试题总结.md.69243f39.lean.js b/assets/article_【用友金融】前端面试题总结.md.8730c019.lean.js
similarity index 97%
rename from assets/article_【用友金融】前端面试题总结.md.69243f39.lean.js
rename to assets/article_【用友金融】前端面试题总结.md.8730c019.lean.js
index 2d49bc96..005316f7 100644
--- a/assets/article_【用友金融】前端面试题总结.md.69243f39.lean.js
+++ b/assets/article_【用友金融】前端面试题总结.md.8730c019.lean.js
@@ -1 +1 @@
-import{_ as s,o as a,c as n,a as l}from"./app.33820b61.js";const D=JSON.parse('{"title":"【用友金融】前端面试题总结","description":"","frontmatter":{},"headers":[{"level":2,"title":"回流与重绘","slug":"回流与重绘","link":"#回流与重绘","children":[]},{"level":2,"title":"CSS属性","slug":"css属性","link":"#css属性","children":[]},{"level":2,"title":"函数执行结果","slug":"函数执行结果","link":"#函数执行结果","children":[{"level":3,"title":"题目1","slug":"题目1","link":"#题目1","children":[]},{"level":3,"title":"题目2","slug":"题目2","link":"#题目2","children":[]},{"level":3,"title":"题目3","slug":"题目3","link":"#题目3","children":[]},{"level":3,"title":"题目4","slug":"题目4","link":"#题目4","children":[]},{"level":3,"title":"题目5","slug":"题目5","link":"#题目5","children":[]},{"level":3,"title":"题目6","slug":"题目6","link":"#题目6","children":[]},{"level":3,"title":"题目7","slug":"题目7","link":"#题目7","children":[]},{"level":3,"title":"题目8","slug":"题目8","link":"#题目8","children":[]}]},{"level":2,"title":"CSS权重的优先级","slug":"css权重的优先级","link":"#css权重的优先级","children":[]},{"level":2,"title":"HTTP状态码","slug":"http状态码","link":"#http状态码","children":[]},{"level":2,"title":"BFC(块级格式上下文)","slug":"bfc-块级格式上下文","link":"#bfc-块级格式上下文","children":[]},{"level":2,"title":"元素浮动","slug":"元素浮动","link":"#元素浮动","children":[]},{"level":2,"title":"HTTP请求方法","slug":"http请求方法","link":"#http请求方法","children":[]},{"level":2,"title":"跨域问题","slug":"跨域问题","link":"#跨域问题","children":[]},{"level":2,"title":"了解Webpack的哪些配置项","slug":"了解webpack的哪些配置项","link":"#了解webpack的哪些配置项","children":[]},{"level":2,"title":"判断变量类型","slug":"判断变量类型","link":"#判断变量类型","children":[]},{"level":2,"title":"JS浮点数相加精度问题","slug":"js浮点数相加精度问题","link":"#js浮点数相加精度问题","children":[]},{"level":2,"title":"简单讲讲Vue Router原理","slug":"简单讲讲vue-router原理","link":"#简单讲讲vue-router原理","children":[]},{"level":2,"title":"ES6熟悉吗","slug":"es6熟悉吗","link":"#es6熟悉吗","children":[]},{"level":2,"title":"CSS如何实现水平居中与垂直居中","slug":"css如何实现水平居中与垂直居中","link":"#css如何实现水平居中与垂直居中","children":[]}],"relativePath":"article/【用友金融】前端面试题总结.md","lastUpdated":1676737739000}'),e={name:"article/【用友金融】前端面试题总结.md"},p=l("",71),o=[p];function r(c,t,i,d,y,C){return a(),n("div",null,o)}const F=s(e,[["render",r]]);export{D as __pageData,F as default};
+import{_ as s,o as a,c as n,a as l}from"./app.33820b61.js";const D=JSON.parse('{"title":"【用友金融】前端面试题总结","description":"","frontmatter":{},"headers":[{"level":2,"title":"回流与重绘","slug":"回流与重绘","link":"#回流与重绘","children":[]},{"level":2,"title":"CSS属性","slug":"css属性","link":"#css属性","children":[]},{"level":2,"title":"函数执行结果","slug":"函数执行结果","link":"#函数执行结果","children":[{"level":3,"title":"题目1","slug":"题目1","link":"#题目1","children":[]},{"level":3,"title":"题目2","slug":"题目2","link":"#题目2","children":[]},{"level":3,"title":"题目3","slug":"题目3","link":"#题目3","children":[]},{"level":3,"title":"题目4","slug":"题目4","link":"#题目4","children":[]},{"level":3,"title":"题目5","slug":"题目5","link":"#题目5","children":[]},{"level":3,"title":"题目6","slug":"题目6","link":"#题目6","children":[]},{"level":3,"title":"题目7","slug":"题目7","link":"#题目7","children":[]},{"level":3,"title":"题目8","slug":"题目8","link":"#题目8","children":[]}]},{"level":2,"title":"CSS权重的优先级","slug":"css权重的优先级","link":"#css权重的优先级","children":[]},{"level":2,"title":"HTTP状态码","slug":"http状态码","link":"#http状态码","children":[]},{"level":2,"title":"BFC(块级格式上下文)","slug":"bfc-块级格式上下文","link":"#bfc-块级格式上下文","children":[]},{"level":2,"title":"元素浮动","slug":"元素浮动","link":"#元素浮动","children":[]},{"level":2,"title":"HTTP请求方法","slug":"http请求方法","link":"#http请求方法","children":[]},{"level":2,"title":"跨域问题","slug":"跨域问题","link":"#跨域问题","children":[]},{"level":2,"title":"了解Webpack的哪些配置项","slug":"了解webpack的哪些配置项","link":"#了解webpack的哪些配置项","children":[]},{"level":2,"title":"判断变量类型","slug":"判断变量类型","link":"#判断变量类型","children":[]},{"level":2,"title":"JS浮点数相加精度问题","slug":"js浮点数相加精度问题","link":"#js浮点数相加精度问题","children":[]},{"level":2,"title":"简单讲讲Vue Router原理","slug":"简单讲讲vue-router原理","link":"#简单讲讲vue-router原理","children":[]},{"level":2,"title":"ES6熟悉吗","slug":"es6熟悉吗","link":"#es6熟悉吗","children":[]},{"level":2,"title":"CSS如何实现水平居中与垂直居中","slug":"css如何实现水平居中与垂直居中","link":"#css如何实现水平居中与垂直居中","children":[]}],"relativePath":"article/【用友金融】前端面试题总结.md","lastUpdated":1676979063000}'),e={name:"article/【用友金融】前端面试题总结.md"},p=l("",71),o=[p];function r(c,t,i,d,y,C){return a(),n("div",null,o)}const F=s(e,[["render",r]]);export{D as __pageData,F as default};
diff --git a/assets/article_一文读懂事件冒泡与事件捕获.md.a9dedb6d.js b/assets/article_一文读懂事件冒泡与事件捕获.md.c2d9cd1b.js
similarity index 99%
rename from assets/article_一文读懂事件冒泡与事件捕获.md.a9dedb6d.js
rename to assets/article_一文读懂事件冒泡与事件捕获.md.c2d9cd1b.js
index ed87c264..bac84d32 100644
--- a/assets/article_一文读懂事件冒泡与事件捕获.md.a9dedb6d.js
+++ b/assets/article_一文读懂事件冒泡与事件捕获.md.c2d9cd1b.js
@@ -1,4 +1,4 @@
-import{_ as s,o as n,c as a,a as e}from"./app.33820b61.js";const u=JSON.parse('{"title":"一文读懂事件冒泡与事件捕获","description":"","frontmatter":{},"headers":[{"level":2,"title":"💡 从例子入手","slug":"💡-从例子入手","link":"#💡-从例子入手","children":[]},{"level":2,"title":"🤔 什么是事件冒泡机制?事件捕获又是什么?","slug":"🤔-什么是事件冒泡机制-事件捕获又是什么","link":"#🤔-什么是事件冒泡机制-事件捕获又是什么","children":[{"level":3,"title":"📌 用例子验证结论","slug":"📌-用例子验证结论","link":"#📌-用例子验证结论","children":[]}]},{"level":2,"title":"🧐 为什么有两个阶段?它们有什么用?","slug":"🧐-为什么有两个阶段-它们有什么用","link":"#🧐-为什么有两个阶段-它们有什么用","children":[{"level":3,"title":"📌 历史渊源","slug":"📌-历史渊源","link":"#📌-历史渊源","children":[]},{"level":3,"title":"📌 事件代理 (Event delegation)","slug":"📌-事件代理-event-delegation","link":"#📌-事件代理-event-delegation","children":[]},{"level":3,"title":"📌 事件对象中的target与currentTarget","slug":"📌-事件对象中的target与currenttarget","link":"#📌-事件对象中的target与currenttarget","children":[]}]},{"level":2,"title":"🥳 如何阻止事件冒泡?","slug":"🥳-如何阻止事件冒泡","link":"#🥳-如何阻止事件冒泡","children":[{"level":3,"title":"📌 .stopPropagation()","slug":"📌-stoppropagation","link":"#📌-stoppropagation","children":[]},{"level":3,"title":"📌 e.target == e.currentTarget","slug":"📌-e-target-e-currenttarget","link":"#📌-e-target-e-currenttarget","children":[]},{"level":3,"title":"📌 return false","slug":"📌-return-false","link":"#📌-return-false","children":[]}]},{"level":2,"title":"相关链接","slug":"相关链接","link":"#相关链接","children":[]}],"relativePath":"article/一文读懂事件冒泡与事件捕获.md","lastUpdated":1676737739000}'),l={name:"article/一文读懂事件冒泡与事件捕获.md"},p=e(`

一文读懂事件冒泡与事件捕获

💡 从例子入手

这是一个简单的 Demo,点击的 Display video 按钮后,将视频展示出来。

其中的视频 <video> 标签被 <div> 包裹,<div><video> 上都绑定了自己的 click 事件。

代码片段

我们的预期是:点击 <video> 时播放视频,点击 <div> 时隐藏视频,然而实际上你会发现,点击视频后,不仅视频虽然正常播放,但同时也被隐藏了。

点击子元素,父元素的事件也被触发,导致这种现象的原因正是:浏览器的事件冒泡机制

🤔 什么是事件冒泡机制?事件捕获又是什么?

现代浏览器提供了两种事件处理阶段:捕获阶段与冒泡阶段

bubbling-capturing.png

在捕获阶段:

  • 浏览器检查元素的最外层祖先 <html> ,是否在捕获阶段中注册了一个 onclick 事件处理程序,如果是,则运行它。
  • 然后,它移动到 <html> 中单击元素的下一个祖先元素,执行相同的操作,然后是单击元素再下一个祖先元素,依此类推,直到到达实际点击的元素。

在冒泡阶段,与上述顺序相反:

  • 浏览器检查实际点击的元素是否在冒泡阶段中注册了一个 onclick 事件处理程序,如果是,则运行它
  • 然后它移动到下一个直接的祖先元素,并做同样的事情,然后是下一个,等等,直到它到达 <html> 元素。

当一个事件被触发时,浏览器先运行捕获阶段,后运行冒泡阶段,并且在默认情况下,所有事件处理程序都在冒泡阶段进行注册

针对上面提到的问题,我们可以知道:当 <video> 点击事件触发后,虽然我们没有主动触发 <div> 上绑定的点击事件,但由于冒泡机制,点击事件冒泡到了 <div> 上,并触发了绑定在其上的监听回调函数,将 <video> 标签隐藏。

📌 用例子验证结论

下面是一个用于验证上述结论的Demo:

页面中包括由外向内的三个类名不同的div标签: div1 div2 div3,并为他们在捕获阶段/冒泡阶段分别绑定了不同的事件函数 clickdblclick

代码片段

当点击最内部的 div3 后,浏览器控制台输出:

> 捕获 click div1
+import{_ as s,o as n,c as a,a as e}from"./app.33820b61.js";const u=JSON.parse('{"title":"一文读懂事件冒泡与事件捕获","description":"","frontmatter":{},"headers":[{"level":2,"title":"💡 从例子入手","slug":"💡-从例子入手","link":"#💡-从例子入手","children":[]},{"level":2,"title":"🤔 什么是事件冒泡机制?事件捕获又是什么?","slug":"🤔-什么是事件冒泡机制-事件捕获又是什么","link":"#🤔-什么是事件冒泡机制-事件捕获又是什么","children":[{"level":3,"title":"📌 用例子验证结论","slug":"📌-用例子验证结论","link":"#📌-用例子验证结论","children":[]}]},{"level":2,"title":"🧐 为什么有两个阶段?它们有什么用?","slug":"🧐-为什么有两个阶段-它们有什么用","link":"#🧐-为什么有两个阶段-它们有什么用","children":[{"level":3,"title":"📌 历史渊源","slug":"📌-历史渊源","link":"#📌-历史渊源","children":[]},{"level":3,"title":"📌 事件代理 (Event delegation)","slug":"📌-事件代理-event-delegation","link":"#📌-事件代理-event-delegation","children":[]},{"level":3,"title":"📌 事件对象中的target与currentTarget","slug":"📌-事件对象中的target与currenttarget","link":"#📌-事件对象中的target与currenttarget","children":[]}]},{"level":2,"title":"🥳 如何阻止事件冒泡?","slug":"🥳-如何阻止事件冒泡","link":"#🥳-如何阻止事件冒泡","children":[{"level":3,"title":"📌 .stopPropagation()","slug":"📌-stoppropagation","link":"#📌-stoppropagation","children":[]},{"level":3,"title":"📌 e.target == e.currentTarget","slug":"📌-e-target-e-currenttarget","link":"#📌-e-target-e-currenttarget","children":[]},{"level":3,"title":"📌 return false","slug":"📌-return-false","link":"#📌-return-false","children":[]}]},{"level":2,"title":"相关链接","slug":"相关链接","link":"#相关链接","children":[]}],"relativePath":"article/一文读懂事件冒泡与事件捕获.md","lastUpdated":1676979063000}'),l={name:"article/一文读懂事件冒泡与事件捕获.md"},p=e(`

一文读懂事件冒泡与事件捕获

💡 从例子入手

这是一个简单的 Demo,点击的 Display video 按钮后,将视频展示出来。

其中的视频 <video> 标签被 <div> 包裹,<div><video> 上都绑定了自己的 click 事件。

代码片段

我们的预期是:点击 <video> 时播放视频,点击 <div> 时隐藏视频,然而实际上你会发现,点击视频后,不仅视频虽然正常播放,但同时也被隐藏了。

点击子元素,父元素的事件也被触发,导致这种现象的原因正是:浏览器的事件冒泡机制

🤔 什么是事件冒泡机制?事件捕获又是什么?

现代浏览器提供了两种事件处理阶段:捕获阶段与冒泡阶段

bubbling-capturing.png

在捕获阶段:

  • 浏览器检查元素的最外层祖先 <html> ,是否在捕获阶段中注册了一个 onclick 事件处理程序,如果是,则运行它。
  • 然后,它移动到 <html> 中单击元素的下一个祖先元素,执行相同的操作,然后是单击元素再下一个祖先元素,依此类推,直到到达实际点击的元素。

在冒泡阶段,与上述顺序相反:

  • 浏览器检查实际点击的元素是否在冒泡阶段中注册了一个 onclick 事件处理程序,如果是,则运行它
  • 然后它移动到下一个直接的祖先元素,并做同样的事情,然后是下一个,等等,直到它到达 <html> 元素。

当一个事件被触发时,浏览器先运行捕获阶段,后运行冒泡阶段,并且在默认情况下,所有事件处理程序都在冒泡阶段进行注册

针对上面提到的问题,我们可以知道:当 <video> 点击事件触发后,虽然我们没有主动触发 <div> 上绑定的点击事件,但由于冒泡机制,点击事件冒泡到了 <div> 上,并触发了绑定在其上的监听回调函数,将 <video> 标签隐藏。

📌 用例子验证结论

下面是一个用于验证上述结论的Demo:

页面中包括由外向内的三个类名不同的div标签: div1 div2 div3,并为他们在捕获阶段/冒泡阶段分别绑定了不同的事件函数 clickdblclick

代码片段

当点击最内部的 div3 后,浏览器控制台输出:

> 捕获 click div1
 > 捕获 click div2
 > 捕获 click div3
 > 冒泡 click div3
diff --git a/assets/article_一文读懂事件冒泡与事件捕获.md.a9dedb6d.lean.js b/assets/article_一文读懂事件冒泡与事件捕获.md.c2d9cd1b.lean.js
similarity index 97%
rename from assets/article_一文读懂事件冒泡与事件捕获.md.a9dedb6d.lean.js
rename to assets/article_一文读懂事件冒泡与事件捕获.md.c2d9cd1b.lean.js
index 4b31d01a..6d00fac4 100644
--- a/assets/article_一文读懂事件冒泡与事件捕获.md.a9dedb6d.lean.js
+++ b/assets/article_一文读懂事件冒泡与事件捕获.md.c2d9cd1b.lean.js
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as e}from"./app.33820b61.js";const u=JSON.parse('{"title":"一文读懂事件冒泡与事件捕获","description":"","frontmatter":{},"headers":[{"level":2,"title":"💡 从例子入手","slug":"💡-从例子入手","link":"#💡-从例子入手","children":[]},{"level":2,"title":"🤔 什么是事件冒泡机制?事件捕获又是什么?","slug":"🤔-什么是事件冒泡机制-事件捕获又是什么","link":"#🤔-什么是事件冒泡机制-事件捕获又是什么","children":[{"level":3,"title":"📌 用例子验证结论","slug":"📌-用例子验证结论","link":"#📌-用例子验证结论","children":[]}]},{"level":2,"title":"🧐 为什么有两个阶段?它们有什么用?","slug":"🧐-为什么有两个阶段-它们有什么用","link":"#🧐-为什么有两个阶段-它们有什么用","children":[{"level":3,"title":"📌 历史渊源","slug":"📌-历史渊源","link":"#📌-历史渊源","children":[]},{"level":3,"title":"📌 事件代理 (Event delegation)","slug":"📌-事件代理-event-delegation","link":"#📌-事件代理-event-delegation","children":[]},{"level":3,"title":"📌 事件对象中的target与currentTarget","slug":"📌-事件对象中的target与currenttarget","link":"#📌-事件对象中的target与currenttarget","children":[]}]},{"level":2,"title":"🥳 如何阻止事件冒泡?","slug":"🥳-如何阻止事件冒泡","link":"#🥳-如何阻止事件冒泡","children":[{"level":3,"title":"📌 .stopPropagation()","slug":"📌-stoppropagation","link":"#📌-stoppropagation","children":[]},{"level":3,"title":"📌 e.target == e.currentTarget","slug":"📌-e-target-e-currenttarget","link":"#📌-e-target-e-currenttarget","children":[]},{"level":3,"title":"📌 return false","slug":"📌-return-false","link":"#📌-return-false","children":[]}]},{"level":2,"title":"相关链接","slug":"相关链接","link":"#相关链接","children":[]}],"relativePath":"article/一文读懂事件冒泡与事件捕获.md","lastUpdated":1676737739000}'),l={name:"article/一文读懂事件冒泡与事件捕获.md"},p=e("",63),o=[p];function t(r,c,i,d,D,y){return n(),a("div",null,o)}const C=s(l,[["render",t]]);export{u as __pageData,C as default};
+import{_ as s,o as n,c as a,a as e}from"./app.33820b61.js";const u=JSON.parse('{"title":"一文读懂事件冒泡与事件捕获","description":"","frontmatter":{},"headers":[{"level":2,"title":"💡 从例子入手","slug":"💡-从例子入手","link":"#💡-从例子入手","children":[]},{"level":2,"title":"🤔 什么是事件冒泡机制?事件捕获又是什么?","slug":"🤔-什么是事件冒泡机制-事件捕获又是什么","link":"#🤔-什么是事件冒泡机制-事件捕获又是什么","children":[{"level":3,"title":"📌 用例子验证结论","slug":"📌-用例子验证结论","link":"#📌-用例子验证结论","children":[]}]},{"level":2,"title":"🧐 为什么有两个阶段?它们有什么用?","slug":"🧐-为什么有两个阶段-它们有什么用","link":"#🧐-为什么有两个阶段-它们有什么用","children":[{"level":3,"title":"📌 历史渊源","slug":"📌-历史渊源","link":"#📌-历史渊源","children":[]},{"level":3,"title":"📌 事件代理 (Event delegation)","slug":"📌-事件代理-event-delegation","link":"#📌-事件代理-event-delegation","children":[]},{"level":3,"title":"📌 事件对象中的target与currentTarget","slug":"📌-事件对象中的target与currenttarget","link":"#📌-事件对象中的target与currenttarget","children":[]}]},{"level":2,"title":"🥳 如何阻止事件冒泡?","slug":"🥳-如何阻止事件冒泡","link":"#🥳-如何阻止事件冒泡","children":[{"level":3,"title":"📌 .stopPropagation()","slug":"📌-stoppropagation","link":"#📌-stoppropagation","children":[]},{"level":3,"title":"📌 e.target == e.currentTarget","slug":"📌-e-target-e-currenttarget","link":"#📌-e-target-e-currenttarget","children":[]},{"level":3,"title":"📌 return false","slug":"📌-return-false","link":"#📌-return-false","children":[]}]},{"level":2,"title":"相关链接","slug":"相关链接","link":"#相关链接","children":[]}],"relativePath":"article/一文读懂事件冒泡与事件捕获.md","lastUpdated":1676979063000}'),l={name:"article/一文读懂事件冒泡与事件捕获.md"},p=e("",63),o=[p];function t(r,c,i,d,D,y){return n(),a("div",null,o)}const C=s(l,[["render",t]]);export{u as __pageData,C as default};
diff --git a/assets/article_一文读懂伪类与伪元素.md.18a4ea39.js b/assets/article_一文读懂伪类与伪元素.md.dd034dbf.js
similarity index 99%
rename from assets/article_一文读懂伪类与伪元素.md.18a4ea39.js
rename to assets/article_一文读懂伪类与伪元素.md.dd034dbf.js
index 35783714..bd77fde1 100644
--- a/assets/article_一文读懂伪类与伪元素.md.18a4ea39.js
+++ b/assets/article_一文读懂伪类与伪元素.md.dd034dbf.js
@@ -1,4 +1,4 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const d=JSON.parse('{"title":"一文读懂伪类与伪元素","description":"","frontmatter":{},"headers":[{"level":2,"title":"🔰 什么是伪类?","slug":"🔰-什么是伪类","link":"#🔰-什么是伪类","children":[{"level":3,"title":"典型的伪类关键字","slug":"典型的伪类关键字","link":"#典型的伪类关键字","children":[]},{"level":3,"title":"单独使用的伪类关键字","slug":"单独使用的伪类关键字","link":"#单独使用的伪类关键字","children":[]}]},{"level":2,"title":"🔰 什么是伪元素?","slug":"🔰-什么是伪元素","link":"#🔰-什么是伪元素","children":[]},{"level":2,"title":"📌 伪类与伪元素共同使用","slug":"📌-伪类与伪元素共同使用","link":"#📌-伪类与伪元素共同使用","children":[{"level":3,"title":"题目解读","slug":"题目解读","link":"#题目解读","children":[]},{"level":3,"title":"实现代码","slug":"实现代码","link":"#实现代码","children":[]},{"level":3,"title":"相关链接","slug":"相关链接","link":"#相关链接","children":[]}]}],"relativePath":"article/一文读懂伪类与伪元素.md","lastUpdated":1676737739000}'),p={name:"article/一文读懂伪类与伪元素.md"},e=l(`

一文读懂伪类与伪元素

🔰 什么是伪类?

伪类是添加到选择器的 关键字 ,指定要选择的元素的特殊状态。

典型的伪类关键字

在大多数情况下,伪类都与基础选择器搭配使用,下述是伪类在一些典型场景下的应用。

:hover

指针在 <button> 上悬停,但没有激活它时,按钮颜色变为蓝色

css
button:hover {
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const d=JSON.parse('{"title":"一文读懂伪类与伪元素","description":"","frontmatter":{},"headers":[{"level":2,"title":"🔰 什么是伪类?","slug":"🔰-什么是伪类","link":"#🔰-什么是伪类","children":[{"level":3,"title":"典型的伪类关键字","slug":"典型的伪类关键字","link":"#典型的伪类关键字","children":[]},{"level":3,"title":"单独使用的伪类关键字","slug":"单独使用的伪类关键字","link":"#单独使用的伪类关键字","children":[]}]},{"level":2,"title":"🔰 什么是伪元素?","slug":"🔰-什么是伪元素","link":"#🔰-什么是伪元素","children":[]},{"level":2,"title":"📌 伪类与伪元素共同使用","slug":"📌-伪类与伪元素共同使用","link":"#📌-伪类与伪元素共同使用","children":[{"level":3,"title":"题目解读","slug":"题目解读","link":"#题目解读","children":[]},{"level":3,"title":"实现代码","slug":"实现代码","link":"#实现代码","children":[]},{"level":3,"title":"相关链接","slug":"相关链接","link":"#相关链接","children":[]}]}],"relativePath":"article/一文读懂伪类与伪元素.md","lastUpdated":1676979063000}'),p={name:"article/一文读懂伪类与伪元素.md"},e=l(`

一文读懂伪类与伪元素

🔰 什么是伪类?

伪类是添加到选择器的 关键字 ,指定要选择的元素的特殊状态。

典型的伪类关键字

在大多数情况下,伪类都与基础选择器搭配使用,下述是伪类在一些典型场景下的应用。

:hover

指针在 <button> 上悬停,但没有激活它时,按钮颜色变为蓝色

css
button:hover {
   color: blue;
 }
 

注意: 在触摸屏上 :hover 基本不可用。不同的浏览器上:hover 伪类表现不同。网页开发人员不要让任何内容只能通过悬停才能展示出来,不然这些内容对于触摸屏使用者来说是很难或者说不可能看到。

:not

:not() 用来匹配不符合一组选择器的元素。由于它的作用是防止特定的元素被选中,它也被称为反选伪类negation pseudo-class)。

将所有不是<p>的元素颜色改为蓝色:

css
body:not(p) {
diff --git a/assets/article_一文读懂伪类与伪元素.md.18a4ea39.lean.js b/assets/article_一文读懂伪类与伪元素.md.dd034dbf.lean.js
similarity index 95%
rename from assets/article_一文读懂伪类与伪元素.md.18a4ea39.lean.js
rename to assets/article_一文读懂伪类与伪元素.md.dd034dbf.lean.js
index eb64e840..26f13a25 100644
--- a/assets/article_一文读懂伪类与伪元素.md.18a4ea39.lean.js
+++ b/assets/article_一文读懂伪类与伪元素.md.dd034dbf.lean.js
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const d=JSON.parse('{"title":"一文读懂伪类与伪元素","description":"","frontmatter":{},"headers":[{"level":2,"title":"🔰 什么是伪类?","slug":"🔰-什么是伪类","link":"#🔰-什么是伪类","children":[{"level":3,"title":"典型的伪类关键字","slug":"典型的伪类关键字","link":"#典型的伪类关键字","children":[]},{"level":3,"title":"单独使用的伪类关键字","slug":"单独使用的伪类关键字","link":"#单独使用的伪类关键字","children":[]}]},{"level":2,"title":"🔰 什么是伪元素?","slug":"🔰-什么是伪元素","link":"#🔰-什么是伪元素","children":[]},{"level":2,"title":"📌 伪类与伪元素共同使用","slug":"📌-伪类与伪元素共同使用","link":"#📌-伪类与伪元素共同使用","children":[{"level":3,"title":"题目解读","slug":"题目解读","link":"#题目解读","children":[]},{"level":3,"title":"实现代码","slug":"实现代码","link":"#实现代码","children":[]},{"level":3,"title":"相关链接","slug":"相关链接","link":"#相关链接","children":[]}]}],"relativePath":"article/一文读懂伪类与伪元素.md","lastUpdated":1676737739000}'),p={name:"article/一文读懂伪类与伪元素.md"},e=l("",56),o=[e];function c(r,t,i,D,y,C){return n(),a("div",null,o)}const b=s(p,[["render",c]]);export{d as __pageData,b as default};
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const d=JSON.parse('{"title":"一文读懂伪类与伪元素","description":"","frontmatter":{},"headers":[{"level":2,"title":"🔰 什么是伪类?","slug":"🔰-什么是伪类","link":"#🔰-什么是伪类","children":[{"level":3,"title":"典型的伪类关键字","slug":"典型的伪类关键字","link":"#典型的伪类关键字","children":[]},{"level":3,"title":"单独使用的伪类关键字","slug":"单独使用的伪类关键字","link":"#单独使用的伪类关键字","children":[]}]},{"level":2,"title":"🔰 什么是伪元素?","slug":"🔰-什么是伪元素","link":"#🔰-什么是伪元素","children":[]},{"level":2,"title":"📌 伪类与伪元素共同使用","slug":"📌-伪类与伪元素共同使用","link":"#📌-伪类与伪元素共同使用","children":[{"level":3,"title":"题目解读","slug":"题目解读","link":"#题目解读","children":[]},{"level":3,"title":"实现代码","slug":"实现代码","link":"#实现代码","children":[]},{"level":3,"title":"相关链接","slug":"相关链接","link":"#相关链接","children":[]}]}],"relativePath":"article/一文读懂伪类与伪元素.md","lastUpdated":1676979063000}'),p={name:"article/一文读懂伪类与伪元素.md"},e=l("",56),o=[e];function c(r,t,i,D,y,C){return n(),a("div",null,o)}const b=s(p,[["render",c]]);export{d as __pageData,b as default};
diff --git a/assets/article_一文读懂函数中this指向问题.md.d4e27bc7.js b/assets/article_一文读懂函数中this指向问题.md.3025c285.js
similarity index 99%
rename from assets/article_一文读懂函数中this指向问题.md.d4e27bc7.js
rename to assets/article_一文读懂函数中this指向问题.md.3025c285.js
index 9749747e..2167efe5 100644
--- a/assets/article_一文读懂函数中this指向问题.md.d4e27bc7.js
+++ b/assets/article_一文读懂函数中this指向问题.md.3025c285.js
@@ -1,4 +1,4 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const u=JSON.parse('{"title":"一文读懂函数中this指向问题","description":"","frontmatter":{},"headers":[{"level":2,"title":"函数中this指向","slug":"函数中this指向","link":"#函数中this指向","children":[]},{"level":2,"title":"如何改变this的指向","slug":"如何改变this的指向","link":"#如何改变this的指向","children":[{"level":3,"title":"new 实例化一个函数","slug":"new-实例化一个函数","link":"#new-实例化一个函数","children":[]},{"level":3,"title":"使用 call apply bind","slug":"使用-call-apply-bind","link":"#使用-call-apply-bind","children":[]}]},{"level":2,"title":"箭头函数","slug":"箭头函数","link":"#箭头函数","children":[{"level":3,"title":"箭头函数中的this","slug":"箭头函数中的this","link":"#箭头函数中的this","children":[]},{"level":3,"title":"箭头函数中this的查找规则","slug":"箭头函数中this的查找规则","link":"#箭头函数中this的查找规则","children":[]},{"level":3,"title":"严格模式","slug":"严格模式","link":"#严格模式","children":[]}]},{"level":2,"title":"this面试题","slug":"this面试题","link":"#this面试题","children":[]}],"relativePath":"article/一文读懂函数中this指向问题.md","lastUpdated":1676737739000}'),e={name:"article/一文读懂函数中this指向问题.md"},p=l(`

一文读懂函数中this指向问题

函数中this指向

函数在调用时, Javascript会默认为this绑定一个值

// 定义一个函数
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const u=JSON.parse('{"title":"一文读懂函数中this指向问题","description":"","frontmatter":{},"headers":[{"level":2,"title":"函数中this指向","slug":"函数中this指向","link":"#函数中this指向","children":[]},{"level":2,"title":"如何改变this的指向","slug":"如何改变this的指向","link":"#如何改变this的指向","children":[{"level":3,"title":"new 实例化一个函数","slug":"new-实例化一个函数","link":"#new-实例化一个函数","children":[]},{"level":3,"title":"使用 call apply bind","slug":"使用-call-apply-bind","link":"#使用-call-apply-bind","children":[]}]},{"level":2,"title":"箭头函数","slug":"箭头函数","link":"#箭头函数","children":[{"level":3,"title":"箭头函数中的this","slug":"箭头函数中的this","link":"#箭头函数中的this","children":[]},{"level":3,"title":"箭头函数中this的查找规则","slug":"箭头函数中this的查找规则","link":"#箭头函数中this的查找规则","children":[]},{"level":3,"title":"严格模式","slug":"严格模式","link":"#严格模式","children":[]}]},{"level":2,"title":"this面试题","slug":"this面试题","link":"#this面试题","children":[]}],"relativePath":"article/一文读懂函数中this指向问题.md","lastUpdated":1676979063000}'),e={name:"article/一文读懂函数中this指向问题.md"},p=l(`

一文读懂函数中this指向问题

函数中this指向

函数在调用时, Javascript会默认为this绑定一个值

// 定义一个函数
 function foo() {
   console.log(this)
 }
diff --git a/assets/article_一文读懂函数中this指向问题.md.d4e27bc7.lean.js b/assets/article_一文读懂函数中this指向问题.md.3025c285.lean.js
similarity index 95%
rename from assets/article_一文读懂函数中this指向问题.md.d4e27bc7.lean.js
rename to assets/article_一文读懂函数中this指向问题.md.3025c285.lean.js
index 289dcbbe..fe5a107f 100644
--- a/assets/article_一文读懂函数中this指向问题.md.d4e27bc7.lean.js
+++ b/assets/article_一文读懂函数中this指向问题.md.3025c285.lean.js
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const u=JSON.parse('{"title":"一文读懂函数中this指向问题","description":"","frontmatter":{},"headers":[{"level":2,"title":"函数中this指向","slug":"函数中this指向","link":"#函数中this指向","children":[]},{"level":2,"title":"如何改变this的指向","slug":"如何改变this的指向","link":"#如何改变this的指向","children":[{"level":3,"title":"new 实例化一个函数","slug":"new-实例化一个函数","link":"#new-实例化一个函数","children":[]},{"level":3,"title":"使用 call apply bind","slug":"使用-call-apply-bind","link":"#使用-call-apply-bind","children":[]}]},{"level":2,"title":"箭头函数","slug":"箭头函数","link":"#箭头函数","children":[{"level":3,"title":"箭头函数中的this","slug":"箭头函数中的this","link":"#箭头函数中的this","children":[]},{"level":3,"title":"箭头函数中this的查找规则","slug":"箭头函数中this的查找规则","link":"#箭头函数中this的查找规则","children":[]},{"level":3,"title":"严格模式","slug":"严格模式","link":"#严格模式","children":[]}]},{"level":2,"title":"this面试题","slug":"this面试题","link":"#this面试题","children":[]}],"relativePath":"article/一文读懂函数中this指向问题.md","lastUpdated":1676737739000}'),e={name:"article/一文读懂函数中this指向问题.md"},p=l("",59),o=[p];function c(i,r,t,b,C,d){return n(),a("div",null,o)}const m=s(e,[["render",c]]);export{u as __pageData,m as default};
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const u=JSON.parse('{"title":"一文读懂函数中this指向问题","description":"","frontmatter":{},"headers":[{"level":2,"title":"函数中this指向","slug":"函数中this指向","link":"#函数中this指向","children":[]},{"level":2,"title":"如何改变this的指向","slug":"如何改变this的指向","link":"#如何改变this的指向","children":[{"level":3,"title":"new 实例化一个函数","slug":"new-实例化一个函数","link":"#new-实例化一个函数","children":[]},{"level":3,"title":"使用 call apply bind","slug":"使用-call-apply-bind","link":"#使用-call-apply-bind","children":[]}]},{"level":2,"title":"箭头函数","slug":"箭头函数","link":"#箭头函数","children":[{"level":3,"title":"箭头函数中的this","slug":"箭头函数中的this","link":"#箭头函数中的this","children":[]},{"level":3,"title":"箭头函数中this的查找规则","slug":"箭头函数中this的查找规则","link":"#箭头函数中this的查找规则","children":[]},{"level":3,"title":"严格模式","slug":"严格模式","link":"#严格模式","children":[]}]},{"level":2,"title":"this面试题","slug":"this面试题","link":"#this面试题","children":[]}],"relativePath":"article/一文读懂函数中this指向问题.md","lastUpdated":1676979063000}'),e={name:"article/一文读懂函数中this指向问题.md"},p=l("",59),o=[p];function c(i,r,t,b,C,d){return n(),a("div",null,o)}const m=s(e,[["render",c]]);export{u as __pageData,m as default};
diff --git a/assets/article_从0实现一个年度报告.md.4e06b81d.js b/assets/article_从0实现一个年度报告.md.7ba24283.js
similarity index 99%
rename from assets/article_从0实现一个年度报告.md.4e06b81d.js
rename to assets/article_从0实现一个年度报告.md.7ba24283.js
index fe2bf338..3e774da8 100644
--- a/assets/article_从0实现一个年度报告.md.4e06b81d.js
+++ b/assets/article_从0实现一个年度报告.md.7ba24283.js
@@ -1,4 +1,4 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const u=JSON.parse('{"title":"从0实现一个年度报告","description":"","frontmatter":{},"headers":[{"level":2,"title":"实现难点","slug":"实现难点","link":"#实现难点","children":[{"level":3,"title":"1. 数据模拟","slug":"_1-数据模拟","link":"#_1-数据模拟","children":[]},{"level":3,"title":"2. 屏幕适配","slug":"_2-屏幕适配","link":"#_2-屏幕适配","children":[]},{"level":3,"title":"3. 动画效果","slug":"_3-动画效果","link":"#_3-动画效果","children":[]},{"level":3,"title":"4. 音乐播放","slug":"_4-音乐播放","link":"#_4-音乐播放","children":[]}]},{"level":2,"title":"用户数据","slug":"用户数据","link":"#用户数据","children":[{"level":3,"title":"用户数据内容","slug":"用户数据内容","link":"#用户数据内容","children":[]},{"level":3,"title":"数据模拟","slug":"数据模拟","link":"#数据模拟","children":[]}]},{"level":2,"title":"编码中遇到的问题","slug":"编码中遇到的问题","link":"#编码中遇到的问题","children":[{"level":3,"title":"音乐自动播放的问题","slug":"音乐自动播放的问题","link":"#音乐自动播放的问题","children":[]},{"level":3,"title":"VNode调整样式的问题","slug":"vnode调整样式的问题","link":"#vnode调整样式的问题","children":[]},{"level":3,"title":"监听Animation结束事件并更新响应式变量","slug":"监听animation结束事件并更新响应式变量","link":"#监听animation结束事件并更新响应式变量","children":[]},{"level":3,"title":"切换页面支持触控滑动滚轮键盘","slug":"切换页面支持触控滑动滚轮键盘","link":"#切换页面支持触控滑动滚轮键盘","children":[]},{"level":3,"title":"代码打包","slug":"代码打包","link":"#代码打包","children":[]}]},{"level":2,"title":"技术介绍","slug":"技术介绍","link":"#技术介绍","children":[]},{"level":2,"title":"功能介绍","slug":"功能介绍","link":"#功能介绍","children":[]},{"level":2,"title":"Demo展示","slug":"demo展示","link":"#demo展示","children":[]}],"relativePath":"article/从0实现一个年度报告.md","lastUpdated":1676737739000}'),p={name:"article/从0实现一个年度报告.md"},o=l(`

从0实现一个年度报告

每到年底各大应用都会推出自己的年终总结报告,统计出用户一年来在应用内的行为展示给用户,供用户记录、分享。

今年掘金社区推出了自己的2022掘友年度报告,这次我们仿照这个报告,从0开始自己实现一个年终总结报告页面

实现难点

1. 数据模拟

一般情况下是根据用户UID,到后端去请求相关接口获得统计数据。

例如掘金的接口为https://api.juejin.cn/event_api/v1/annual/annual_summary?aid=xxxxxx

本次后端使用NodeJS实现了一个爬虫,可以将用户数据统计完成后导出JSON格式的数据,将此数据粘贴到前端页面的输入框即可生成自己的报告

2. 屏幕适配

可以观察到,在PC端和在手机端访问年度报告展示的效果是不一样的。

本次考虑使用媒体查询来实现这个功能:

  • 宽屏则展示背景,页面切换也使用背景中的上下切换按钮
  • 小屏则隐藏背景,让内容填满屏幕,页面切换通过滑动事件监听

3. 动画效果

动画分为文本与背景元素的动画

  • 背景元素的动画使用了SVG动画
    • 动画中不动的部分直接使用.png图片
    • 运动的部分使用SVG动画绘制,如克里克的眼睛、尾巴
  • 文本的动画使用了CSS Animation渐显的效果
    • 不同段落之间通过animation-delay属性,彼此相差1000ms

背景动画容器的四个位置:左上角 右下角 中间部分 中间(悬浮气泡)。不同位置的动画容器都采用绝对定位position: absolute;,辅以z-index实现层叠

囿于工期,本次的背景动画直接采用静态图片+CSS Animation实现上下浮动的效果

4. 音乐播放

通过Audio接口访问网络音乐链接,控制音乐相关功能

  • 进入页面开始播放
  • 离开页面暂停播放
  • 支持点击按钮切换播放状态

用户数据

用户数据内容

- 用户名
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const u=JSON.parse('{"title":"从0实现一个年度报告","description":"","frontmatter":{},"headers":[{"level":2,"title":"实现难点","slug":"实现难点","link":"#实现难点","children":[{"level":3,"title":"1. 数据模拟","slug":"_1-数据模拟","link":"#_1-数据模拟","children":[]},{"level":3,"title":"2. 屏幕适配","slug":"_2-屏幕适配","link":"#_2-屏幕适配","children":[]},{"level":3,"title":"3. 动画效果","slug":"_3-动画效果","link":"#_3-动画效果","children":[]},{"level":3,"title":"4. 音乐播放","slug":"_4-音乐播放","link":"#_4-音乐播放","children":[]}]},{"level":2,"title":"用户数据","slug":"用户数据","link":"#用户数据","children":[{"level":3,"title":"用户数据内容","slug":"用户数据内容","link":"#用户数据内容","children":[]},{"level":3,"title":"数据模拟","slug":"数据模拟","link":"#数据模拟","children":[]}]},{"level":2,"title":"编码中遇到的问题","slug":"编码中遇到的问题","link":"#编码中遇到的问题","children":[{"level":3,"title":"音乐自动播放的问题","slug":"音乐自动播放的问题","link":"#音乐自动播放的问题","children":[]},{"level":3,"title":"VNode调整样式的问题","slug":"vnode调整样式的问题","link":"#vnode调整样式的问题","children":[]},{"level":3,"title":"监听Animation结束事件并更新响应式变量","slug":"监听animation结束事件并更新响应式变量","link":"#监听animation结束事件并更新响应式变量","children":[]},{"level":3,"title":"切换页面支持触控滑动滚轮键盘","slug":"切换页面支持触控滑动滚轮键盘","link":"#切换页面支持触控滑动滚轮键盘","children":[]},{"level":3,"title":"代码打包","slug":"代码打包","link":"#代码打包","children":[]}]},{"level":2,"title":"技术介绍","slug":"技术介绍","link":"#技术介绍","children":[]},{"level":2,"title":"功能介绍","slug":"功能介绍","link":"#功能介绍","children":[]},{"level":2,"title":"Demo展示","slug":"demo展示","link":"#demo展示","children":[]}],"relativePath":"article/从0实现一个年度报告.md","lastUpdated":1676979063000}'),p={name:"article/从0实现一个年度报告.md"},o=l(`

从0实现一个年度报告

每到年底各大应用都会推出自己的年终总结报告,统计出用户一年来在应用内的行为展示给用户,供用户记录、分享。

今年掘金社区推出了自己的2022掘友年度报告,这次我们仿照这个报告,从0开始自己实现一个年终总结报告页面

实现难点

1. 数据模拟

一般情况下是根据用户UID,到后端去请求相关接口获得统计数据。

例如掘金的接口为https://api.juejin.cn/event_api/v1/annual/annual_summary?aid=xxxxxx

本次后端使用NodeJS实现了一个爬虫,可以将用户数据统计完成后导出JSON格式的数据,将此数据粘贴到前端页面的输入框即可生成自己的报告

2. 屏幕适配

可以观察到,在PC端和在手机端访问年度报告展示的效果是不一样的。

本次考虑使用媒体查询来实现这个功能:

  • 宽屏则展示背景,页面切换也使用背景中的上下切换按钮
  • 小屏则隐藏背景,让内容填满屏幕,页面切换通过滑动事件监听

3. 动画效果

动画分为文本与背景元素的动画

  • 背景元素的动画使用了SVG动画
    • 动画中不动的部分直接使用.png图片
    • 运动的部分使用SVG动画绘制,如克里克的眼睛、尾巴
  • 文本的动画使用了CSS Animation渐显的效果
    • 不同段落之间通过animation-delay属性,彼此相差1000ms

背景动画容器的四个位置:左上角 右下角 中间部分 中间(悬浮气泡)。不同位置的动画容器都采用绝对定位position: absolute;,辅以z-index实现层叠

囿于工期,本次的背景动画直接采用静态图片+CSS Animation实现上下浮动的效果

4. 音乐播放

通过Audio接口访问网络音乐链接,控制音乐相关功能

  • 进入页面开始播放
  • 离开页面暂停播放
  • 支持点击按钮切换播放状态

用户数据

用户数据内容

- 用户名
 - 注册时间 距今天数
 - 创作相关
     - 发布文章数
diff --git a/assets/article_从0实现一个年度报告.md.4e06b81d.lean.js b/assets/article_从0实现一个年度报告.md.7ba24283.lean.js
similarity index 97%
rename from assets/article_从0实现一个年度报告.md.4e06b81d.lean.js
rename to assets/article_从0实现一个年度报告.md.7ba24283.lean.js
index 26f2fcbe..831c1fd5 100644
--- a/assets/article_从0实现一个年度报告.md.4e06b81d.lean.js
+++ b/assets/article_从0实现一个年度报告.md.7ba24283.lean.js
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const u=JSON.parse('{"title":"从0实现一个年度报告","description":"","frontmatter":{},"headers":[{"level":2,"title":"实现难点","slug":"实现难点","link":"#实现难点","children":[{"level":3,"title":"1. 数据模拟","slug":"_1-数据模拟","link":"#_1-数据模拟","children":[]},{"level":3,"title":"2. 屏幕适配","slug":"_2-屏幕适配","link":"#_2-屏幕适配","children":[]},{"level":3,"title":"3. 动画效果","slug":"_3-动画效果","link":"#_3-动画效果","children":[]},{"level":3,"title":"4. 音乐播放","slug":"_4-音乐播放","link":"#_4-音乐播放","children":[]}]},{"level":2,"title":"用户数据","slug":"用户数据","link":"#用户数据","children":[{"level":3,"title":"用户数据内容","slug":"用户数据内容","link":"#用户数据内容","children":[]},{"level":3,"title":"数据模拟","slug":"数据模拟","link":"#数据模拟","children":[]}]},{"level":2,"title":"编码中遇到的问题","slug":"编码中遇到的问题","link":"#编码中遇到的问题","children":[{"level":3,"title":"音乐自动播放的问题","slug":"音乐自动播放的问题","link":"#音乐自动播放的问题","children":[]},{"level":3,"title":"VNode调整样式的问题","slug":"vnode调整样式的问题","link":"#vnode调整样式的问题","children":[]},{"level":3,"title":"监听Animation结束事件并更新响应式变量","slug":"监听animation结束事件并更新响应式变量","link":"#监听animation结束事件并更新响应式变量","children":[]},{"level":3,"title":"切换页面支持触控滑动滚轮键盘","slug":"切换页面支持触控滑动滚轮键盘","link":"#切换页面支持触控滑动滚轮键盘","children":[]},{"level":3,"title":"代码打包","slug":"代码打包","link":"#代码打包","children":[]}]},{"level":2,"title":"技术介绍","slug":"技术介绍","link":"#技术介绍","children":[]},{"level":2,"title":"功能介绍","slug":"功能介绍","link":"#功能介绍","children":[]},{"level":2,"title":"Demo展示","slug":"demo展示","link":"#demo展示","children":[]}],"relativePath":"article/从0实现一个年度报告.md","lastUpdated":1676737739000}'),p={name:"article/从0实现一个年度报告.md"},o=l("",59),e=[o];function t(c,r,F,D,y,i){return n(),a("div",null,e)}const d=s(p,[["render",t]]);export{u as __pageData,d as default};
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const u=JSON.parse('{"title":"从0实现一个年度报告","description":"","frontmatter":{},"headers":[{"level":2,"title":"实现难点","slug":"实现难点","link":"#实现难点","children":[{"level":3,"title":"1. 数据模拟","slug":"_1-数据模拟","link":"#_1-数据模拟","children":[]},{"level":3,"title":"2. 屏幕适配","slug":"_2-屏幕适配","link":"#_2-屏幕适配","children":[]},{"level":3,"title":"3. 动画效果","slug":"_3-动画效果","link":"#_3-动画效果","children":[]},{"level":3,"title":"4. 音乐播放","slug":"_4-音乐播放","link":"#_4-音乐播放","children":[]}]},{"level":2,"title":"用户数据","slug":"用户数据","link":"#用户数据","children":[{"level":3,"title":"用户数据内容","slug":"用户数据内容","link":"#用户数据内容","children":[]},{"level":3,"title":"数据模拟","slug":"数据模拟","link":"#数据模拟","children":[]}]},{"level":2,"title":"编码中遇到的问题","slug":"编码中遇到的问题","link":"#编码中遇到的问题","children":[{"level":3,"title":"音乐自动播放的问题","slug":"音乐自动播放的问题","link":"#音乐自动播放的问题","children":[]},{"level":3,"title":"VNode调整样式的问题","slug":"vnode调整样式的问题","link":"#vnode调整样式的问题","children":[]},{"level":3,"title":"监听Animation结束事件并更新响应式变量","slug":"监听animation结束事件并更新响应式变量","link":"#监听animation结束事件并更新响应式变量","children":[]},{"level":3,"title":"切换页面支持触控滑动滚轮键盘","slug":"切换页面支持触控滑动滚轮键盘","link":"#切换页面支持触控滑动滚轮键盘","children":[]},{"level":3,"title":"代码打包","slug":"代码打包","link":"#代码打包","children":[]}]},{"level":2,"title":"技术介绍","slug":"技术介绍","link":"#技术介绍","children":[]},{"level":2,"title":"功能介绍","slug":"功能介绍","link":"#功能介绍","children":[]},{"level":2,"title":"Demo展示","slug":"demo展示","link":"#demo展示","children":[]}],"relativePath":"article/从0实现一个年度报告.md","lastUpdated":1676979063000}'),p={name:"article/从0实现一个年度报告.md"},o=l("",59),e=[o];function t(c,r,F,D,y,i){return n(),a("div",null,e)}const d=s(p,[["render",t]]);export{u as __pageData,d as default};
diff --git a/assets/article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.9865de7d.js b/assets/article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.b7a6c275.js
similarity index 99%
rename from assets/article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.9865de7d.js
rename to assets/article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.b7a6c275.js
index b93dc36b..d3f2b47c 100644
--- a/assets/article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.9865de7d.js
+++ b/assets/article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.b7a6c275.js
@@ -1,4 +1,4 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const C=JSON.parse('{"title":"彻底搞懂对象的数据属性描述符、存储属性描述符","description":"","frontmatter":{},"headers":[{"level":2,"title":"属性描述符","slug":"属性描述符","link":"#属性描述符","children":[{"level":3,"title":"数据属性描述符","slug":"数据属性描述符","link":"#数据属性描述符","children":[]},{"level":3,"title":"存储属性描述符","slug":"存储属性描述符","link":"#存储属性描述符","children":[]},{"level":3,"title":"应用场景","slug":"应用场景","link":"#应用场景","children":[]}]}],"relativePath":"article/彻底搞懂对象的数据属性描述符、存储属性描述符.md","lastUpdated":1676737739000}'),p={name:"article/彻底搞懂对象的数据属性描述符、存储属性描述符.md"},o=l(`

彻底搞懂对象的数据属性描述符、存储属性描述符

属性描述符

js
  let obj = {
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const C=JSON.parse('{"title":"彻底搞懂对象的数据属性描述符、存储属性描述符","description":"","frontmatter":{},"headers":[{"level":2,"title":"属性描述符","slug":"属性描述符","link":"#属性描述符","children":[{"level":3,"title":"数据属性描述符","slug":"数据属性描述符","link":"#数据属性描述符","children":[]},{"level":3,"title":"存储属性描述符","slug":"存储属性描述符","link":"#存储属性描述符","children":[]},{"level":3,"title":"应用场景","slug":"应用场景","link":"#应用场景","children":[]}]}],"relativePath":"article/彻底搞懂对象的数据属性描述符、存储属性描述符.md","lastUpdated":1676979063000}'),p={name:"article/彻底搞懂对象的数据属性描述符、存储属性描述符.md"},o=l(`

彻底搞懂对象的数据属性描述符、存储属性描述符

属性描述符

js
  let obj = {
     name: "ziu",
     age: 18
   }
diff --git a/assets/article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.9865de7d.lean.js b/assets/article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.b7a6c275.lean.js
similarity index 93%
rename from assets/article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.9865de7d.lean.js
rename to assets/article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.b7a6c275.lean.js
index b54c6e70..f485760e 100644
--- a/assets/article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.9865de7d.lean.js
+++ b/assets/article_彻底搞懂对象的数据属性描述符、存储属性描述符.md.b7a6c275.lean.js
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const C=JSON.parse('{"title":"彻底搞懂对象的数据属性描述符、存储属性描述符","description":"","frontmatter":{},"headers":[{"level":2,"title":"属性描述符","slug":"属性描述符","link":"#属性描述符","children":[{"level":3,"title":"数据属性描述符","slug":"数据属性描述符","link":"#数据属性描述符","children":[]},{"level":3,"title":"存储属性描述符","slug":"存储属性描述符","link":"#存储属性描述符","children":[]},{"level":3,"title":"应用场景","slug":"应用场景","link":"#应用场景","children":[]}]}],"relativePath":"article/彻底搞懂对象的数据属性描述符、存储属性描述符.md","lastUpdated":1676737739000}'),p={name:"article/彻底搞懂对象的数据属性描述符、存储属性描述符.md"},o=l("",18),e=[o];function c(t,r,D,y,F,i){return n(),a("div",null,e)}const d=s(p,[["render",c]]);export{C as __pageData,d as default};
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const C=JSON.parse('{"title":"彻底搞懂对象的数据属性描述符、存储属性描述符","description":"","frontmatter":{},"headers":[{"level":2,"title":"属性描述符","slug":"属性描述符","link":"#属性描述符","children":[{"level":3,"title":"数据属性描述符","slug":"数据属性描述符","link":"#数据属性描述符","children":[]},{"level":3,"title":"存储属性描述符","slug":"存储属性描述符","link":"#存储属性描述符","children":[]},{"level":3,"title":"应用场景","slug":"应用场景","link":"#应用场景","children":[]}]}],"relativePath":"article/彻底搞懂对象的数据属性描述符、存储属性描述符.md","lastUpdated":1676979063000}'),p={name:"article/彻底搞懂对象的数据属性描述符、存储属性描述符.md"},o=l("",18),e=[o];function c(t,r,D,y,F,i){return n(),a("div",null,e)}const d=s(p,[["render",c]]);export{C as __pageData,d as default};
diff --git a/assets/article_浅析defineProperty与Proxy实现的双向绑定.md.f2072102.js b/assets/article_浅析defineProperty与Proxy实现的双向绑定.md.02c8f56e.js
similarity index 99%
rename from assets/article_浅析defineProperty与Proxy实现的双向绑定.md.f2072102.js
rename to assets/article_浅析defineProperty与Proxy实现的双向绑定.md.02c8f56e.js
index a7bd0e50..afc8d439 100644
--- a/assets/article_浅析defineProperty与Proxy实现的双向绑定.md.f2072102.js
+++ b/assets/article_浅析defineProperty与Proxy实现的双向绑定.md.02c8f56e.js
@@ -1,4 +1,4 @@
-import{_ as s,o as n,c as a,a as e}from"./app.33820b61.js";const C=JSON.parse('{"title":"浅析defineProperty与Proxy实现的双向绑定","description":"","frontmatter":{},"headers":[{"level":2,"title":"🔰 Vue2的响应式原理","slug":"🔰-vue2的响应式原理","link":"#🔰-vue2的响应式原理","children":[]},{"level":2,"title":"🔰 Vue3的响应式原理","slug":"🔰-vue3的响应式原理","link":"#🔰-vue3的响应式原理","children":[]}],"relativePath":"article/浅析defineProperty与Proxy实现的双向绑定.md","lastUpdated":1676737739000}'),l={name:"article/浅析defineProperty与Proxy实现的双向绑定.md"},p=e(`

浅析defineProperty与Proxy实现的双向绑定

文章内容总结自Vue官网 深入响应式原理

🔰 Vue2的响应式原理

image.png

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

Vue2的响应式原理,利用的是 Object.defineProperty()setter 属性:

defineProperty() 方法用于精确定义一个对象的属性,能够指定属性的各种特征,其中的 set 属性能够为对象指定一个 setter 函数,每次该属性的值发生修改,就会调用此函数。

更多可以配置的属性请参看:什么是对象的数据属性描述符?存储属性描述符?

这也是Vue2实现响应式数据、数据双向绑定的原理。

可以使用此方法实现一个简单的数据双向绑定的Demo:

image.png

  • 输入框内的内容改变,.vBox 展示的文本会随之改变。
  • 点击按钮修改 vm.text,输入框内的值和 .vBox 的文本都会发生改变。
html
  <body>
+import{_ as s,o as n,c as a,a as e}from"./app.33820b61.js";const C=JSON.parse('{"title":"浅析defineProperty与Proxy实现的双向绑定","description":"","frontmatter":{},"headers":[{"level":2,"title":"🔰 Vue2的响应式原理","slug":"🔰-vue2的响应式原理","link":"#🔰-vue2的响应式原理","children":[]},{"level":2,"title":"🔰 Vue3的响应式原理","slug":"🔰-vue3的响应式原理","link":"#🔰-vue3的响应式原理","children":[]}],"relativePath":"article/浅析defineProperty与Proxy实现的双向绑定.md","lastUpdated":1676979063000}'),l={name:"article/浅析defineProperty与Proxy实现的双向绑定.md"},p=e(`

浅析defineProperty与Proxy实现的双向绑定

文章内容总结自Vue官网 深入响应式原理

🔰 Vue2的响应式原理

image.png

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

Vue2的响应式原理,利用的是 Object.defineProperty()setter 属性:

defineProperty() 方法用于精确定义一个对象的属性,能够指定属性的各种特征,其中的 set 属性能够为对象指定一个 setter 函数,每次该属性的值发生修改,就会调用此函数。

更多可以配置的属性请参看:什么是对象的数据属性描述符?存储属性描述符?

这也是Vue2实现响应式数据、数据双向绑定的原理。

可以使用此方法实现一个简单的数据双向绑定的Demo:

image.png

  • 输入框内的内容改变,.vBox 展示的文本会随之改变。
  • 点击按钮修改 vm.text,输入框内的值和 .vBox 的文本都会发生改变。
html
  <body>
     <input type="text" id="input" />
     <button onclick="vm.text='Hello, World.'">Modify vm.text</button>
     <div class="vBox"></div>
diff --git a/assets/article_浅析defineProperty与Proxy实现的双向绑定.md.f2072102.lean.js b/assets/article_浅析defineProperty与Proxy实现的双向绑定.md.02c8f56e.lean.js
similarity index 91%
rename from assets/article_浅析defineProperty与Proxy实现的双向绑定.md.f2072102.lean.js
rename to assets/article_浅析defineProperty与Proxy实现的双向绑定.md.02c8f56e.lean.js
index aa5bce8f..27612a0f 100644
--- a/assets/article_浅析defineProperty与Proxy实现的双向绑定.md.f2072102.lean.js
+++ b/assets/article_浅析defineProperty与Proxy实现的双向绑定.md.02c8f56e.lean.js
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as e}from"./app.33820b61.js";const C=JSON.parse('{"title":"浅析defineProperty与Proxy实现的双向绑定","description":"","frontmatter":{},"headers":[{"level":2,"title":"🔰 Vue2的响应式原理","slug":"🔰-vue2的响应式原理","link":"#🔰-vue2的响应式原理","children":[]},{"level":2,"title":"🔰 Vue3的响应式原理","slug":"🔰-vue3的响应式原理","link":"#🔰-vue3的响应式原理","children":[]}],"relativePath":"article/浅析defineProperty与Proxy实现的双向绑定.md","lastUpdated":1676737739000}'),l={name:"article/浅析defineProperty与Proxy实现的双向绑定.md"},p=e("",20),o=[p];function t(r,c,D,y,F,i){return n(),a("div",null,o)}const u=s(l,[["render",t]]);export{C as __pageData,u as default};
+import{_ as s,o as n,c as a,a as e}from"./app.33820b61.js";const C=JSON.parse('{"title":"浅析defineProperty与Proxy实现的双向绑定","description":"","frontmatter":{},"headers":[{"level":2,"title":"🔰 Vue2的响应式原理","slug":"🔰-vue2的响应式原理","link":"#🔰-vue2的响应式原理","children":[]},{"level":2,"title":"🔰 Vue3的响应式原理","slug":"🔰-vue3的响应式原理","link":"#🔰-vue3的响应式原理","children":[]}],"relativePath":"article/浅析defineProperty与Proxy实现的双向绑定.md","lastUpdated":1676979063000}'),l={name:"article/浅析defineProperty与Proxy实现的双向绑定.md"},p=e("",20),o=[p];function t(r,c,D,y,F,i){return n(),a("div",null,o)}const u=s(l,[["render",t]]);export{C as __pageData,u as default};
diff --git a/assets/article_深入JavaScript数据类型.md.ed246d99.js b/assets/article_深入JavaScript数据类型.md.80fd8af0.js
similarity index 99%
rename from assets/article_深入JavaScript数据类型.md.ed246d99.js
rename to assets/article_深入JavaScript数据类型.md.80fd8af0.js
index d561a82e..9111fd03 100644
--- a/assets/article_深入JavaScript数据类型.md.ed246d99.js
+++ b/assets/article_深入JavaScript数据类型.md.80fd8af0.js
@@ -1,4 +1,4 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const o="/assets/Object.prototype.toString.70e8308c.png",d=JSON.parse(`{"title":"","description":"","frontmatter":{},"headers":[{"level":2,"title":"深入JavaScript数据类型","slug":"深入javascript数据类型","link":"#深入javascript数据类型","children":[]},{"level":2,"title":"typeof运算符","slug":"typeof运算符","link":"#typeof运算符","children":[{"level":3,"title":"typeof null === 'object'","slug":"typeof-null-object","link":"#typeof-null-object","children":[]},{"level":3,"title":"关于new操作符","slug":"关于new操作符","link":"#关于new操作符","children":[]},{"level":3,"title":"字符串原始值和字符串对象","slug":"字符串原始值和字符串对象","link":"#字符串原始值和字符串对象","children":[]}]},{"level":2,"title":"包装类型","slug":"包装类型","link":"#包装类型","children":[]},{"level":2,"title":"使用toString检查对象类型","slug":"使用tostring检查对象类型","link":"#使用tostring检查对象类型","children":[{"level":3,"title":"核心原理","slug":"核心原理","link":"#核心原理","children":[]}]}],"relativePath":"article/深入JavaScript数据类型.md","lastUpdated":1676737739000}`),e={name:"article/深入JavaScript数据类型.md"},p=l(`

深入JavaScript数据类型

JavaScript包含以下几种数据类型:

  • Number 数字
  • String 字符串
  • Boolean 布尔值
  • Symbol 符号 (ES6新增)
  • Object 对象
    • Function 函数
    • Array 数组
    • Date 日期
    • RegExp 正则表达式
    • ...
  • null 空
  • undefined 未定义

从语言底层值的可变与不可变,可以将JS中的数据分为两种:不可变值(原始类型)和可变值(引用类型)

除了Object及继承自Object的特殊对象,其他的类型都为原始类型

typeof运算符

除了null,所有原始类型都可以通过typeof运算符得到不同的结果

而null与object通过typeof运算符得到的结果都为'object'

javascript
// 除了 null 其他原始类型的变量都可以通过 typeof 得到其类型
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const o="/assets/Object.prototype.toString.70e8308c.png",d=JSON.parse(`{"title":"","description":"","frontmatter":{},"headers":[{"level":2,"title":"深入JavaScript数据类型","slug":"深入javascript数据类型","link":"#深入javascript数据类型","children":[]},{"level":2,"title":"typeof运算符","slug":"typeof运算符","link":"#typeof运算符","children":[{"level":3,"title":"typeof null === 'object'","slug":"typeof-null-object","link":"#typeof-null-object","children":[]},{"level":3,"title":"关于new操作符","slug":"关于new操作符","link":"#关于new操作符","children":[]},{"level":3,"title":"字符串原始值和字符串对象","slug":"字符串原始值和字符串对象","link":"#字符串原始值和字符串对象","children":[]}]},{"level":2,"title":"包装类型","slug":"包装类型","link":"#包装类型","children":[]},{"level":2,"title":"使用toString检查对象类型","slug":"使用tostring检查对象类型","link":"#使用tostring检查对象类型","children":[{"level":3,"title":"核心原理","slug":"核心原理","link":"#核心原理","children":[]}]}],"relativePath":"article/深入JavaScript数据类型.md","lastUpdated":1676979063000}`),e={name:"article/深入JavaScript数据类型.md"},p=l(`

深入JavaScript数据类型

JavaScript包含以下几种数据类型:

  • Number 数字
  • String 字符串
  • Boolean 布尔值
  • Symbol 符号 (ES6新增)
  • Object 对象
    • Function 函数
    • Array 数组
    • Date 日期
    • RegExp 正则表达式
    • ...
  • null 空
  • undefined 未定义

从语言底层值的可变与不可变,可以将JS中的数据分为两种:不可变值(原始类型)和可变值(引用类型)

除了Object及继承自Object的特殊对象,其他的类型都为原始类型

typeof运算符

除了null,所有原始类型都可以通过typeof运算符得到不同的结果

而null与object通过typeof运算符得到的结果都为'object'

javascript
// 除了 null 其他原始类型的变量都可以通过 typeof 得到其类型
 // 而 null 与 object 通过 typeof 运算得到的都是 'object'
 const targets = [18, 'Ziu', true, Symbol(''), {}, null, undefined]
 
diff --git a/assets/article_深入JavaScript数据类型.md.ed246d99.lean.js b/assets/article_深入JavaScript数据类型.md.80fd8af0.lean.js
similarity index 95%
rename from assets/article_深入JavaScript数据类型.md.ed246d99.lean.js
rename to assets/article_深入JavaScript数据类型.md.80fd8af0.lean.js
index 9e6b8629..ec1da120 100644
--- a/assets/article_深入JavaScript数据类型.md.ed246d99.lean.js
+++ b/assets/article_深入JavaScript数据类型.md.80fd8af0.lean.js
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const o="/assets/Object.prototype.toString.70e8308c.png",d=JSON.parse(`{"title":"","description":"","frontmatter":{},"headers":[{"level":2,"title":"深入JavaScript数据类型","slug":"深入javascript数据类型","link":"#深入javascript数据类型","children":[]},{"level":2,"title":"typeof运算符","slug":"typeof运算符","link":"#typeof运算符","children":[{"level":3,"title":"typeof null === 'object'","slug":"typeof-null-object","link":"#typeof-null-object","children":[]},{"level":3,"title":"关于new操作符","slug":"关于new操作符","link":"#关于new操作符","children":[]},{"level":3,"title":"字符串原始值和字符串对象","slug":"字符串原始值和字符串对象","link":"#字符串原始值和字符串对象","children":[]}]},{"level":2,"title":"包装类型","slug":"包装类型","link":"#包装类型","children":[]},{"level":2,"title":"使用toString检查对象类型","slug":"使用tostring检查对象类型","link":"#使用tostring检查对象类型","children":[{"level":3,"title":"核心原理","slug":"核心原理","link":"#核心原理","children":[]}]}],"relativePath":"article/深入JavaScript数据类型.md","lastUpdated":1676737739000}`),e={name:"article/深入JavaScript数据类型.md"},p=l("",46),t=[p];function c(r,i,y,D,A,F){return n(),a("div",null,t)}const b=s(e,[["render",c]]);export{d as __pageData,b as default};
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const o="/assets/Object.prototype.toString.70e8308c.png",d=JSON.parse(`{"title":"","description":"","frontmatter":{},"headers":[{"level":2,"title":"深入JavaScript数据类型","slug":"深入javascript数据类型","link":"#深入javascript数据类型","children":[]},{"level":2,"title":"typeof运算符","slug":"typeof运算符","link":"#typeof运算符","children":[{"level":3,"title":"typeof null === 'object'","slug":"typeof-null-object","link":"#typeof-null-object","children":[]},{"level":3,"title":"关于new操作符","slug":"关于new操作符","link":"#关于new操作符","children":[]},{"level":3,"title":"字符串原始值和字符串对象","slug":"字符串原始值和字符串对象","link":"#字符串原始值和字符串对象","children":[]}]},{"level":2,"title":"包装类型","slug":"包装类型","link":"#包装类型","children":[]},{"level":2,"title":"使用toString检查对象类型","slug":"使用tostring检查对象类型","link":"#使用tostring检查对象类型","children":[{"level":3,"title":"核心原理","slug":"核心原理","link":"#核心原理","children":[]}]}],"relativePath":"article/深入JavaScript数据类型.md","lastUpdated":1676979063000}`),e={name:"article/深入JavaScript数据类型.md"},p=l("",46),t=[p];function c(r,i,y,D,A,F){return n(),a("div",null,t)}const b=s(e,[["render",c]]);export{d as __pageData,b as default};
diff --git a/assets/article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.e6b03974.js b/assets/article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.cd9b1cff.js
similarity index 99%
rename from assets/article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.e6b03974.js
rename to assets/article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.cd9b1cff.js
index fe797104..85e65724 100644
--- a/assets/article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.e6b03974.js
+++ b/assets/article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.cd9b1cff.js
@@ -1,4 +1,4 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const u=JSON.parse('{"title":"深入Vue3源码,看看Vue.use后究竟发生了什么?","description":"","frontmatter":{},"headers":[{"level":2,"title":"从全局注册组件库入手","slug":"从全局注册组件库入手","link":"#从全局注册组件库入手","children":[]},{"level":2,"title":"深入源码","slug":"深入源码","link":"#深入源码","children":[]},{"level":2,"title":"手动引入&注册组件","slug":"手动引入-注册组件","link":"#手动引入-注册组件","children":[]},{"level":2,"title":"参考阅读","slug":"参考阅读","link":"#参考阅读","children":[]}],"relativePath":"article/深入Vue3源码,看看Vue.use后究竟发生了什么?.md","lastUpdated":1676737739000}'),p={name:"article/深入Vue3源码,看看Vue.use后究竟发生了什么?.md"},e=l(`

深入Vue3源码,看看Vue.use后究竟发生了什么?

从全局注册组件库入手

如果我们自定义了几个自定义组件,当我们想在.vue文件中使用它们时,需要手动import导入组件并在component中注册:

html
<script>
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const u=JSON.parse('{"title":"深入Vue3源码,看看Vue.use后究竟发生了什么?","description":"","frontmatter":{},"headers":[{"level":2,"title":"从全局注册组件库入手","slug":"从全局注册组件库入手","link":"#从全局注册组件库入手","children":[]},{"level":2,"title":"深入源码","slug":"深入源码","link":"#深入源码","children":[]},{"level":2,"title":"手动引入&注册组件","slug":"手动引入-注册组件","link":"#手动引入-注册组件","children":[]},{"level":2,"title":"参考阅读","slug":"参考阅读","link":"#参考阅读","children":[]}],"relativePath":"article/深入Vue3源码,看看Vue.use后究竟发生了什么?.md","lastUpdated":1676979063000}'),p={name:"article/深入Vue3源码,看看Vue.use后究竟发生了什么?.md"},e=l(`

深入Vue3源码,看看Vue.use后究竟发生了什么?

从全局注册组件库入手

如果我们自定义了几个自定义组件,当我们想在.vue文件中使用它们时,需要手动import导入组件并在component中注册:

html
<script>
 import CustomInput from '@/component/CustomInput.vue'
 
 export default {
diff --git a/assets/article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.e6b03974.lean.js b/assets/article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.cd9b1cff.lean.js
similarity index 93%
rename from assets/article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.e6b03974.lean.js
rename to assets/article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.cd9b1cff.lean.js
index db64a994..c23dc834 100644
--- a/assets/article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.e6b03974.lean.js
+++ b/assets/article_深入Vue3源码,看看Vue.use后究竟发生了什么?.md.cd9b1cff.lean.js
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const u=JSON.parse('{"title":"深入Vue3源码,看看Vue.use后究竟发生了什么?","description":"","frontmatter":{},"headers":[{"level":2,"title":"从全局注册组件库入手","slug":"从全局注册组件库入手","link":"#从全局注册组件库入手","children":[]},{"level":2,"title":"深入源码","slug":"深入源码","link":"#深入源码","children":[]},{"level":2,"title":"手动引入&注册组件","slug":"手动引入-注册组件","link":"#手动引入-注册组件","children":[]},{"level":2,"title":"参考阅读","slug":"参考阅读","link":"#参考阅读","children":[]}],"relativePath":"article/深入Vue3源码,看看Vue.use后究竟发生了什么?.md","lastUpdated":1676737739000}'),p={name:"article/深入Vue3源码,看看Vue.use后究竟发生了什么?.md"},e=l("",26),o=[e];function t(c,r,i,y,F,D){return n(),a("div",null,o)}const C=s(p,[["render",t]]);export{u as __pageData,C as default};
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const u=JSON.parse('{"title":"深入Vue3源码,看看Vue.use后究竟发生了什么?","description":"","frontmatter":{},"headers":[{"level":2,"title":"从全局注册组件库入手","slug":"从全局注册组件库入手","link":"#从全局注册组件库入手","children":[]},{"level":2,"title":"深入源码","slug":"深入源码","link":"#深入源码","children":[]},{"level":2,"title":"手动引入&注册组件","slug":"手动引入-注册组件","link":"#手动引入-注册组件","children":[]},{"level":2,"title":"参考阅读","slug":"参考阅读","link":"#参考阅读","children":[]}],"relativePath":"article/深入Vue3源码,看看Vue.use后究竟发生了什么?.md","lastUpdated":1676979063000}'),p={name:"article/深入Vue3源码,看看Vue.use后究竟发生了什么?.md"},e=l("",26),o=[e];function t(c,r,i,y,F,D){return n(),a("div",null,o)}const C=s(p,[["render",t]]);export{u as __pageData,C as default};
diff --git a/assets/article_深入理解Proxy与Reflect.md.368d9aed.js b/assets/article_深入理解Proxy与Reflect.md.9c5a6cd1.js
similarity index 99%
rename from assets/article_深入理解Proxy与Reflect.md.368d9aed.js
rename to assets/article_深入理解Proxy与Reflect.md.9c5a6cd1.js
index 31513b79..b17ff630 100644
--- a/assets/article_深入理解Proxy与Reflect.md.368d9aed.js
+++ b/assets/article_深入理解Proxy与Reflect.md.9c5a6cd1.js
@@ -1,4 +1,4 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const i=JSON.parse('{"title":"深入理解Proxy与Reflect","description":"","frontmatter":{},"headers":[{"level":3,"title":"监听对象的操作","slug":"监听对象的操作","link":"#监听对象的操作","children":[]},{"level":3,"title":"Proxy类基本使用","slug":"proxy类基本使用","link":"#proxy类基本使用","children":[]},{"level":3,"title":"捕获器","slug":"捕获器","link":"#捕获器","children":[]},{"level":3,"title":"Reflect","slug":"reflect","link":"#reflect","children":[]},{"level":3,"title":"与Object的区别","slug":"与object的区别","link":"#与object的区别","children":[]},{"level":3,"title":"Reflect常见方法","slug":"reflect常见方法","link":"#reflect常见方法","children":[]},{"level":3,"title":"Reflect.construct方法","slug":"reflect-construct方法","link":"#reflect-construct方法","children":[]}],"relativePath":"article/深入理解Proxy与Reflect.md","lastUpdated":1676737739000}'),p={name:"article/深入理解Proxy与Reflect.md"},o=l(`

深入理解Proxy与Reflect

监听对象的操作

可以使用Proxy对象将原对象包裹,此后的操作都对proxy进行,每次getset被触发时都会自动执行相应代码

js
const obj = {
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const i=JSON.parse('{"title":"深入理解Proxy与Reflect","description":"","frontmatter":{},"headers":[{"level":3,"title":"监听对象的操作","slug":"监听对象的操作","link":"#监听对象的操作","children":[]},{"level":3,"title":"Proxy类基本使用","slug":"proxy类基本使用","link":"#proxy类基本使用","children":[]},{"level":3,"title":"捕获器","slug":"捕获器","link":"#捕获器","children":[]},{"level":3,"title":"Reflect","slug":"reflect","link":"#reflect","children":[]},{"level":3,"title":"与Object的区别","slug":"与object的区别","link":"#与object的区别","children":[]},{"level":3,"title":"Reflect常见方法","slug":"reflect常见方法","link":"#reflect常见方法","children":[]},{"level":3,"title":"Reflect.construct方法","slug":"reflect-construct方法","link":"#reflect-construct方法","children":[]}],"relativePath":"article/深入理解Proxy与Reflect.md","lastUpdated":1676979063000}'),p={name:"article/深入理解Proxy与Reflect.md"},o=l(`

深入理解Proxy与Reflect

监听对象的操作

可以使用Proxy对象将原对象包裹,此后的操作都对proxy进行,每次getset被触发时都会自动执行相应代码

js
const obj = {
   name: 'ziu',
   age: 18,
   height: 1.88
diff --git a/assets/article_深入理解Proxy与Reflect.md.368d9aed.lean.js b/assets/article_深入理解Proxy与Reflect.md.9c5a6cd1.lean.js
similarity index 94%
rename from assets/article_深入理解Proxy与Reflect.md.368d9aed.lean.js
rename to assets/article_深入理解Proxy与Reflect.md.9c5a6cd1.lean.js
index ca496002..2b5ee0f0 100644
--- a/assets/article_深入理解Proxy与Reflect.md.368d9aed.lean.js
+++ b/assets/article_深入理解Proxy与Reflect.md.9c5a6cd1.lean.js
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const i=JSON.parse('{"title":"深入理解Proxy与Reflect","description":"","frontmatter":{},"headers":[{"level":3,"title":"监听对象的操作","slug":"监听对象的操作","link":"#监听对象的操作","children":[]},{"level":3,"title":"Proxy类基本使用","slug":"proxy类基本使用","link":"#proxy类基本使用","children":[]},{"level":3,"title":"捕获器","slug":"捕获器","link":"#捕获器","children":[]},{"level":3,"title":"Reflect","slug":"reflect","link":"#reflect","children":[]},{"level":3,"title":"与Object的区别","slug":"与object的区别","link":"#与object的区别","children":[]},{"level":3,"title":"Reflect常见方法","slug":"reflect常见方法","link":"#reflect常见方法","children":[]},{"level":3,"title":"Reflect.construct方法","slug":"reflect-construct方法","link":"#reflect-construct方法","children":[]}],"relativePath":"article/深入理解Proxy与Reflect.md","lastUpdated":1676737739000}'),p={name:"article/深入理解Proxy与Reflect.md"},o=l("",44),e=[o];function c(t,r,y,D,F,A){return n(),a("div",null,e)}const b=s(p,[["render",c]]);export{i as __pageData,b as default};
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const i=JSON.parse('{"title":"深入理解Proxy与Reflect","description":"","frontmatter":{},"headers":[{"level":3,"title":"监听对象的操作","slug":"监听对象的操作","link":"#监听对象的操作","children":[]},{"level":3,"title":"Proxy类基本使用","slug":"proxy类基本使用","link":"#proxy类基本使用","children":[]},{"level":3,"title":"捕获器","slug":"捕获器","link":"#捕获器","children":[]},{"level":3,"title":"Reflect","slug":"reflect","link":"#reflect","children":[]},{"level":3,"title":"与Object的区别","slug":"与object的区别","link":"#与object的区别","children":[]},{"level":3,"title":"Reflect常见方法","slug":"reflect常见方法","link":"#reflect常见方法","children":[]},{"level":3,"title":"Reflect.construct方法","slug":"reflect-construct方法","link":"#reflect-construct方法","children":[]}],"relativePath":"article/深入理解Proxy与Reflect.md","lastUpdated":1676979063000}'),p={name:"article/深入理解Proxy与Reflect.md"},o=l("",44),e=[o];function c(t,r,y,D,F,A){return n(),a("div",null,e)}const b=s(p,[["render",c]]);export{i as __pageData,b as default};
diff --git a/assets/article_深入理解浏览器缓存机制.md.be15491a.js b/assets/article_深入理解浏览器缓存机制.md.e7e22bb1.js
similarity index 99%
rename from assets/article_深入理解浏览器缓存机制.md.be15491a.js
rename to assets/article_深入理解浏览器缓存机制.md.e7e22bb1.js
index b5f8a28b..3ee80ed8 100644
--- a/assets/article_深入理解浏览器缓存机制.md.be15491a.js
+++ b/assets/article_深入理解浏览器缓存机制.md.e7e22bb1.js
@@ -1,4 +1,4 @@
-import{_ as e,o as a,c as s,a as l}from"./app.33820b61.js";const f=JSON.parse('{"title":"深入理解浏览器缓存机制","description":"","frontmatter":{},"headers":[{"level":2,"title":"强制缓存","slug":"强制缓存","link":"#强制缓存","children":[{"level":3,"title":"什么是强制缓存","slug":"什么是强制缓存","link":"#什么是强制缓存","children":[]},{"level":3,"title":"强制缓存的规则","slug":"强制缓存的规则","link":"#强制缓存的规则","children":[]},{"level":3,"title":"Expires与Cache-Control","slug":"expires与cache-control","link":"#expires与cache-control","children":[]}]},{"level":2,"title":"协商缓存","slug":"协商缓存","link":"#协商缓存","children":[{"level":3,"title":"协商缓存的规则","slug":"协商缓存的规则","link":"#协商缓存的规则","children":[]}]},{"level":2,"title":"内存缓存与硬盘缓存","slug":"内存缓存与硬盘缓存","link":"#内存缓存与硬盘缓存","children":[]},{"level":2,"title":"用户对浏览器缓存的控制","slug":"用户对浏览器缓存的控制","link":"#用户对浏览器缓存的控制","children":[]},{"level":2,"title":"参考资料","slug":"参考资料","link":"#参考资料","children":[]}],"relativePath":"article/深入理解浏览器缓存机制.md","lastUpdated":1676737739000}'),n={name:"article/深入理解浏览器缓存机制.md"},o=l(`

深入理解浏览器缓存机制

浏览器有两种缓存规则:强制缓存与协商缓存

  1. 强制缓存:不会向服务器发送请求,直接从缓存中读取资源
  2. 协商缓存:向服务器发送请求,服务器会根据这个请求的request header的一些参数来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的response header通知浏览器从缓存中读取资源
  • 共同点:都是从客户端缓存中读取资源
  • 不同点:强制缓存不会发请求,协商缓存会发请求

强制缓存

什么是强制缓存

浏览器在服务器发起真正请求前,先检查浏览器缓存:

  • 如果命中缓存,且缓存未过期,那么直接使用缓存资源
  • 如果未命中缓存,或缓存已过期失效,那么向服务器发出请求

强制缓存的规则

服务器通过向响应头添加ExpiresCache-Control字段来标识强制缓存的状态,浏览器会将这两个信息缓存到本地,后续有相同请求时,优先到浏览器缓存中检查资源是否到期。

其中Cache-Control优先级比Expires高,即:二者同时存在时,浏览器以Cache-Control为标准,检查缓存资源是否过期

Expires与Cache-Control

Expires

Expires表示当前资源的失效时间,它的值是一个HTTP-日期时间戳,例如:Expires: Thu, 01 Dec 1994 16:00:00 GMT

使用Expires存在一些弊端:

  • 代表的是绝对时间,如果浏览器和服务器的时间不同步,会导致缓存目标时间存在偏差
  • 如果服务端设置的日期格式不规范,那么等同于无缓存
  • ExpiresHTTP/1.0的字段,但是现在浏览器默认使用的是HTTP/1.1

在某些不支持HTTP1.1的环境下,Expires就会发挥用处

所以Expires其实是过时的产物,现阶段它的存在只是一种兼容性的写法

Cache-Control

如果在Cache-Control响应头设置了"max-age"或者"s-max-age"指令,那么Expires头会被忽略

设置Cache-Control的值有以下规则:

  • 不区分大小写,但建议使用小写
  • 多个指令以逗号分隔
  • 具有可选参数,可以用令牌或者带引号的字符串语法

常用的指令:

  • public:所有内容都将被缓存,即使是通常不可缓存的内容(如POST请求)。
  • private:所有内容只有客户端可以缓存,不能作为共享缓存(即代理服务器不能缓存它),这也是Cache-Control的默认取值
  • no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
  • no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存,即不使用任何缓存。
  • max-age=xxx (xxx is numeric):缓存内容将在xxx秒后失效

举几个例子:

此次请求之后的600秒内,如果浏览器再次发起请求,那么直接使用缓存中的资源:

Cache-Control: max-age=600
+import{_ as e,o as a,c as s,a as l}from"./app.33820b61.js";const f=JSON.parse('{"title":"深入理解浏览器缓存机制","description":"","frontmatter":{},"headers":[{"level":2,"title":"强制缓存","slug":"强制缓存","link":"#强制缓存","children":[{"level":3,"title":"什么是强制缓存","slug":"什么是强制缓存","link":"#什么是强制缓存","children":[]},{"level":3,"title":"强制缓存的规则","slug":"强制缓存的规则","link":"#强制缓存的规则","children":[]},{"level":3,"title":"Expires与Cache-Control","slug":"expires与cache-control","link":"#expires与cache-control","children":[]}]},{"level":2,"title":"协商缓存","slug":"协商缓存","link":"#协商缓存","children":[{"level":3,"title":"协商缓存的规则","slug":"协商缓存的规则","link":"#协商缓存的规则","children":[]}]},{"level":2,"title":"内存缓存与硬盘缓存","slug":"内存缓存与硬盘缓存","link":"#内存缓存与硬盘缓存","children":[]},{"level":2,"title":"用户对浏览器缓存的控制","slug":"用户对浏览器缓存的控制","link":"#用户对浏览器缓存的控制","children":[]},{"level":2,"title":"参考资料","slug":"参考资料","link":"#参考资料","children":[]}],"relativePath":"article/深入理解浏览器缓存机制.md","lastUpdated":1676979063000}'),n={name:"article/深入理解浏览器缓存机制.md"},o=l(`

深入理解浏览器缓存机制

浏览器有两种缓存规则:强制缓存与协商缓存

  1. 强制缓存:不会向服务器发送请求,直接从缓存中读取资源
  2. 协商缓存:向服务器发送请求,服务器会根据这个请求的request header的一些参数来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的response header通知浏览器从缓存中读取资源
  • 共同点:都是从客户端缓存中读取资源
  • 不同点:强制缓存不会发请求,协商缓存会发请求

强制缓存

什么是强制缓存

浏览器在服务器发起真正请求前,先检查浏览器缓存:

  • 如果命中缓存,且缓存未过期,那么直接使用缓存资源
  • 如果未命中缓存,或缓存已过期失效,那么向服务器发出请求

强制缓存的规则

服务器通过向响应头添加ExpiresCache-Control字段来标识强制缓存的状态,浏览器会将这两个信息缓存到本地,后续有相同请求时,优先到浏览器缓存中检查资源是否到期。

其中Cache-Control优先级比Expires高,即:二者同时存在时,浏览器以Cache-Control为标准,检查缓存资源是否过期

Expires与Cache-Control

Expires

Expires表示当前资源的失效时间,它的值是一个HTTP-日期时间戳,例如:Expires: Thu, 01 Dec 1994 16:00:00 GMT

使用Expires存在一些弊端:

  • 代表的是绝对时间,如果浏览器和服务器的时间不同步,会导致缓存目标时间存在偏差
  • 如果服务端设置的日期格式不规范,那么等同于无缓存
  • ExpiresHTTP/1.0的字段,但是现在浏览器默认使用的是HTTP/1.1

在某些不支持HTTP1.1的环境下,Expires就会发挥用处

所以Expires其实是过时的产物,现阶段它的存在只是一种兼容性的写法

Cache-Control

如果在Cache-Control响应头设置了"max-age"或者"s-max-age"指令,那么Expires头会被忽略

设置Cache-Control的值有以下规则:

  • 不区分大小写,但建议使用小写
  • 多个指令以逗号分隔
  • 具有可选参数,可以用令牌或者带引号的字符串语法

常用的指令:

  • public:所有内容都将被缓存,即使是通常不可缓存的内容(如POST请求)。
  • private:所有内容只有客户端可以缓存,不能作为共享缓存(即代理服务器不能缓存它),这也是Cache-Control的默认取值
  • no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
  • no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存,即不使用任何缓存。
  • max-age=xxx (xxx is numeric):缓存内容将在xxx秒后失效

举几个例子:

此次请求之后的600秒内,如果浏览器再次发起请求,那么直接使用缓存中的资源:

Cache-Control: max-age=600
 

浏览器可以缓存资源,但每次使用缓存资源前都必须重新验证其有效性:

Cache-Control: no-cache
 
Cache-Control: max-age=0, must-revalidate
 

这意味着每次都会发起 HTTP 请求,但当缓存内容仍有效时可以跳过 HTTP 响应体的下载

协商缓存

当浏览器检查本地的强制缓存已经失效后,浏览器携带该资源的协商缓存标识向服务器发起请求,由服务器根据缓存标识决定是否继续使用本地缓存。

  • 协商缓存生效,服务器返回304,通知浏览器继续使用本地缓存
  • 协商缓存失效,服务器返回200,与最新的请求资源

协商缓存的规则

服务器与浏览器通过两两成对的请求头来控制协商缓存:

  • Etag If-None-Match
  • Last-Modified If-Modified-Since

其中,EtagLast-Modified是由服务器设置的响应头的字段,If-None-MatchIf-Modified-Since则是浏览器向服务器发送的请求头的字段

Etag与Last-Modified

Etag是上一次加载资源时,服务器返回的ResponseHeader,是对该资源的一种唯一标识,只要资源有变化,Etag就会重新生成。浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到RequestHeader里的If-None-Match里,服务器接受到If-None-Match的值后,会拿来跟该资源文件的Etag值做比较,如果相同,则表示资源文件没有发生改变,命中协商缓存。

  • Etag由服务器生成,标志当前资源的唯一标识,一般包含大小、修改时间等信息
  • If-None-Match浏览器缓存到本地的Etag

HTTP协议并未规定Etag的内容是如何生成的,但一般包含大小、修改时间等信息

Node.js下生成Etag的示例:

js
// 根据文件的fs.Stats信息计算出etag
diff --git a/assets/article_深入理解浏览器缓存机制.md.be15491a.lean.js b/assets/article_深入理解浏览器缓存机制.md.e7e22bb1.lean.js
similarity index 95%
rename from assets/article_深入理解浏览器缓存机制.md.be15491a.lean.js
rename to assets/article_深入理解浏览器缓存机制.md.e7e22bb1.lean.js
index 4cb8f338..e4ddadd6 100644
--- a/assets/article_深入理解浏览器缓存机制.md.be15491a.lean.js
+++ b/assets/article_深入理解浏览器缓存机制.md.e7e22bb1.lean.js
@@ -1 +1 @@
-import{_ as e,o as a,c as s,a as l}from"./app.33820b61.js";const f=JSON.parse('{"title":"深入理解浏览器缓存机制","description":"","frontmatter":{},"headers":[{"level":2,"title":"强制缓存","slug":"强制缓存","link":"#强制缓存","children":[{"level":3,"title":"什么是强制缓存","slug":"什么是强制缓存","link":"#什么是强制缓存","children":[]},{"level":3,"title":"强制缓存的规则","slug":"强制缓存的规则","link":"#强制缓存的规则","children":[]},{"level":3,"title":"Expires与Cache-Control","slug":"expires与cache-control","link":"#expires与cache-control","children":[]}]},{"level":2,"title":"协商缓存","slug":"协商缓存","link":"#协商缓存","children":[{"level":3,"title":"协商缓存的规则","slug":"协商缓存的规则","link":"#协商缓存的规则","children":[]}]},{"level":2,"title":"内存缓存与硬盘缓存","slug":"内存缓存与硬盘缓存","link":"#内存缓存与硬盘缓存","children":[]},{"level":2,"title":"用户对浏览器缓存的控制","slug":"用户对浏览器缓存的控制","link":"#用户对浏览器缓存的控制","children":[]},{"level":2,"title":"参考资料","slug":"参考资料","link":"#参考资料","children":[]}],"relativePath":"article/深入理解浏览器缓存机制.md","lastUpdated":1676737739000}'),n={name:"article/深入理解浏览器缓存机制.md"},o=l("",66),c=[o];function i(r,p,t,d,h,u){return a(),s("div",null,c)}const b=e(n,[["render",i]]);export{f as __pageData,b as default};
+import{_ as e,o as a,c as s,a as l}from"./app.33820b61.js";const f=JSON.parse('{"title":"深入理解浏览器缓存机制","description":"","frontmatter":{},"headers":[{"level":2,"title":"强制缓存","slug":"强制缓存","link":"#强制缓存","children":[{"level":3,"title":"什么是强制缓存","slug":"什么是强制缓存","link":"#什么是强制缓存","children":[]},{"level":3,"title":"强制缓存的规则","slug":"强制缓存的规则","link":"#强制缓存的规则","children":[]},{"level":3,"title":"Expires与Cache-Control","slug":"expires与cache-control","link":"#expires与cache-control","children":[]}]},{"level":2,"title":"协商缓存","slug":"协商缓存","link":"#协商缓存","children":[{"level":3,"title":"协商缓存的规则","slug":"协商缓存的规则","link":"#协商缓存的规则","children":[]}]},{"level":2,"title":"内存缓存与硬盘缓存","slug":"内存缓存与硬盘缓存","link":"#内存缓存与硬盘缓存","children":[]},{"level":2,"title":"用户对浏览器缓存的控制","slug":"用户对浏览器缓存的控制","link":"#用户对浏览器缓存的控制","children":[]},{"level":2,"title":"参考资料","slug":"参考资料","link":"#参考资料","children":[]}],"relativePath":"article/深入理解浏览器缓存机制.md","lastUpdated":1676979063000}'),n={name:"article/深入理解浏览器缓存机制.md"},o=l("",66),c=[o];function i(r,p,t,d,h,u){return a(),s("div",null,c)}const b=e(n,[["render",i]]);export{f as __pageData,b as default};
diff --git a/assets/article_深入理解浏览器运行原理.md.4b1c1d16.js b/assets/article_深入理解浏览器运行原理.md.f13b2b23.js
similarity index 99%
rename from assets/article_深入理解浏览器运行原理.md.4b1c1d16.js
rename to assets/article_深入理解浏览器运行原理.md.f13b2b23.js
index 8dacc7bb..243da0bc 100644
--- a/assets/article_深入理解浏览器运行原理.md.4b1c1d16.js
+++ b/assets/article_深入理解浏览器运行原理.md.f13b2b23.js
@@ -1,4 +1,4 @@
-import{_ as s,o as n,c as a,a as e}from"./app.33820b61.js";const m=JSON.parse('{"title":"深入理解浏览器运行原理","description":"","frontmatter":{},"headers":[{"level":2,"title":"网页解析过程","slug":"网页解析过程","link":"#网页解析过程","children":[]},{"level":2,"title":"HTML解析过程","slug":"html解析过程","link":"#html解析过程","children":[]},{"level":2,"title":"生成CSS规则","slug":"生成css规则","link":"#生成css规则","children":[]},{"level":2,"title":"构建Render Tree","slug":"构建render-tree","link":"#构建render-tree","children":[]},{"level":2,"title":"布局和绘制(Layout & Paint)","slug":"布局和绘制-layout-paint","link":"#布局和绘制-layout-paint","children":[]},{"level":2,"title":"回流和重绘(Reflow & )","slug":"回流和重绘-reflow","link":"#回流和重绘-reflow","children":[]},{"level":2,"title":"特殊解析: composite合成","slug":"特殊解析-composite合成","link":"#特殊解析-composite合成","children":[{"level":3,"title":"案例1:同一层渲染","slug":"案例1-同一层渲染","link":"#案例1-同一层渲染","children":[]},{"level":3,"title":"案例2:分层渲染","slug":"案例2-分层渲染","link":"#案例2-分层渲染","children":[]},{"level":3,"title":"案例3:transform 3D","slug":"案例3-transform-3d","link":"#案例3-transform-3d","children":[]},{"level":3,"title":"案例4:transition+transform","slug":"案例4-transition-transform","link":"#案例4-transition-transform","children":[]},{"level":3,"title":"案例5:transition+opacity","slug":"案例5-transition-opacity","link":"#案例5-transition-opacity","children":[]},{"level":3,"title":"总结","slug":"总结","link":"#总结","children":[]}]},{"level":2,"title":"浏览器对script元素的处理","slug":"浏览器对script元素的处理","link":"#浏览器对script元素的处理","children":[]},{"level":2,"title":"defer属性","slug":"defer属性","link":"#defer属性","children":[]},{"level":2,"title":"async属性","slug":"async属性","link":"#async属性","children":[]}],"relativePath":"article/深入理解浏览器运行原理.md","lastUpdated":1676737739000}'),l={name:"article/深入理解浏览器运行原理.md"},p=e(`

深入理解浏览器运行原理

网页解析过程

输入域名 => DNS解析为IP => 目标服务器返回index.html

DNS:Domain Name System

HTML解析过程

  • 浏览器开始解析index.html文件,当遇到<link>则向服务器请求下载.css文件
  • 遇到<script>标签则向服务器请求下载.js文件
浏览器解析HTML过程浏览器是和如何工作的

How browsers work

生成CSS规则

在解析的过程中,如果遇到<link>元素,那么会由浏览器负责下载对应的CSS文件

  • 注意:下载CSS文件不会影响到DOM解析
  • 有单独一个线程对CSS文件进行下载与解析

浏览器下载完CSS文件后,就会对CSS文件进行解析,解析出对应的规则树:

  • 我们可以称之为CSSOM(CSS Object Model,CSS对象模型)

构建Render Tree

有了DOM Tree和CSSOM Tree之后,就可以将二者结合,构建Render Tree了

此时,如果有某些元素的CSS属性display: none;那么这个元素就不会出现在Render Tree中

  • 下载和解析CSS文件时,不会阻塞DOM Tree的构建过程
  • 但会阻塞Render Tree的构建过程:因为需要对应的CSSOM Tree

布局和绘制(Layout & Paint)

第四步是在渲染树(Render Tree)上运行布局(Layout),以计算每个节点的几何体

  • 渲染树会表示显示哪些节点以及其他的样式,但是不表示每个节点的尺寸、位置等信息
  • 布局是确定呈现树中所有节点的宽度、高度和位置信息

第五步是将每个节点绘制(Paint)到屏幕上

  • 在绘制阶段,浏览器布局阶段计算的每个frame转为屏幕上实际的像素点
  • 包括将元素的可见部分进行绘制,比如文本、颜色、边框、阴影、替换元素

回流和重绘(Reflow & )

回流也可称为重排

理解回流(Reflow):

  • 第一次确定节点的大小和位置,称之为布局(layout)
  • 之后对节点的大小、位置修改重新计算,称之为回流

什么情况下会引起回流?

  • DOM 结构发生改变(添加新的节点或者移除节点)
  • 改变了布局(修改了width height padding font-size等值)
  • 窗口resize(修改了窗口的尺寸等)
  • 调用getComputedStyle方法获取尺寸、位置信息

理解重绘(Repaint):

  • 第一次渲染内容称之为绘制(paint)
  • 之后的重新渲染称之为重绘

什么情况下会引起重绘?

  • 修改背景色、文字颜色、边框颜色、样式等

回流一定会引起重绘,所以回流是一件很消耗性能的事情

  • 开发中要尽量避免发生回流

  • 修改样式尽量一次性修改完毕

    • 例如通过cssText一次性设置样式,或通过修改class的方式修改样式
  • 尽量避免频繁的操作DOM

    • 可以在一个DocumentFragment或者父元素中,将要操作的DOM操作完成,再一次性插入到DOM树中
  • 尽量避免通过getComputedStyle获取元素尺寸、位置等信息

  • 对某些元素使用position的absolute或fixed属性

    • 并不是不会引起回流,而是开销相对较小,不会对其他元素产生影响

特殊解析: composite合成

在绘制的过程中,可以将布局后的元素绘制到多个合成图层中

  • 这是浏览器的一种优化手段
  • 将不同流生成的不同Layer进行合并
标准流 => LayouTree => RenderLayer
+import{_ as s,o as n,c as a,a as e}from"./app.33820b61.js";const m=JSON.parse('{"title":"深入理解浏览器运行原理","description":"","frontmatter":{},"headers":[{"level":2,"title":"网页解析过程","slug":"网页解析过程","link":"#网页解析过程","children":[]},{"level":2,"title":"HTML解析过程","slug":"html解析过程","link":"#html解析过程","children":[]},{"level":2,"title":"生成CSS规则","slug":"生成css规则","link":"#生成css规则","children":[]},{"level":2,"title":"构建Render Tree","slug":"构建render-tree","link":"#构建render-tree","children":[]},{"level":2,"title":"布局和绘制(Layout & Paint)","slug":"布局和绘制-layout-paint","link":"#布局和绘制-layout-paint","children":[]},{"level":2,"title":"回流和重绘(Reflow & )","slug":"回流和重绘-reflow","link":"#回流和重绘-reflow","children":[]},{"level":2,"title":"特殊解析: composite合成","slug":"特殊解析-composite合成","link":"#特殊解析-composite合成","children":[{"level":3,"title":"案例1:同一层渲染","slug":"案例1-同一层渲染","link":"#案例1-同一层渲染","children":[]},{"level":3,"title":"案例2:分层渲染","slug":"案例2-分层渲染","link":"#案例2-分层渲染","children":[]},{"level":3,"title":"案例3:transform 3D","slug":"案例3-transform-3d","link":"#案例3-transform-3d","children":[]},{"level":3,"title":"案例4:transition+transform","slug":"案例4-transition-transform","link":"#案例4-transition-transform","children":[]},{"level":3,"title":"案例5:transition+opacity","slug":"案例5-transition-opacity","link":"#案例5-transition-opacity","children":[]},{"level":3,"title":"总结","slug":"总结","link":"#总结","children":[]}]},{"level":2,"title":"浏览器对script元素的处理","slug":"浏览器对script元素的处理","link":"#浏览器对script元素的处理","children":[]},{"level":2,"title":"defer属性","slug":"defer属性","link":"#defer属性","children":[]},{"level":2,"title":"async属性","slug":"async属性","link":"#async属性","children":[]}],"relativePath":"article/深入理解浏览器运行原理.md","lastUpdated":1676979063000}'),l={name:"article/深入理解浏览器运行原理.md"},p=e(`

深入理解浏览器运行原理

网页解析过程

输入域名 => DNS解析为IP => 目标服务器返回index.html

DNS:Domain Name System

HTML解析过程

  • 浏览器开始解析index.html文件,当遇到<link>则向服务器请求下载.css文件
  • 遇到<script>标签则向服务器请求下载.js文件
浏览器解析HTML过程浏览器是和如何工作的

How browsers work

生成CSS规则

在解析的过程中,如果遇到<link>元素,那么会由浏览器负责下载对应的CSS文件

  • 注意:下载CSS文件不会影响到DOM解析
  • 有单独一个线程对CSS文件进行下载与解析

浏览器下载完CSS文件后,就会对CSS文件进行解析,解析出对应的规则树:

  • 我们可以称之为CSSOM(CSS Object Model,CSS对象模型)

构建Render Tree

有了DOM Tree和CSSOM Tree之后,就可以将二者结合,构建Render Tree了

此时,如果有某些元素的CSS属性display: none;那么这个元素就不会出现在Render Tree中

  • 下载和解析CSS文件时,不会阻塞DOM Tree的构建过程
  • 但会阻塞Render Tree的构建过程:因为需要对应的CSSOM Tree

布局和绘制(Layout & Paint)

第四步是在渲染树(Render Tree)上运行布局(Layout),以计算每个节点的几何体

  • 渲染树会表示显示哪些节点以及其他的样式,但是不表示每个节点的尺寸、位置等信息
  • 布局是确定呈现树中所有节点的宽度、高度和位置信息

第五步是将每个节点绘制(Paint)到屏幕上

  • 在绘制阶段,浏览器布局阶段计算的每个frame转为屏幕上实际的像素点
  • 包括将元素的可见部分进行绘制,比如文本、颜色、边框、阴影、替换元素

回流和重绘(Reflow & )

回流也可称为重排

理解回流(Reflow):

  • 第一次确定节点的大小和位置,称之为布局(layout)
  • 之后对节点的大小、位置修改重新计算,称之为回流

什么情况下会引起回流?

  • DOM 结构发生改变(添加新的节点或者移除节点)
  • 改变了布局(修改了width height padding font-size等值)
  • 窗口resize(修改了窗口的尺寸等)
  • 调用getComputedStyle方法获取尺寸、位置信息

理解重绘(Repaint):

  • 第一次渲染内容称之为绘制(paint)
  • 之后的重新渲染称之为重绘

什么情况下会引起重绘?

  • 修改背景色、文字颜色、边框颜色、样式等

回流一定会引起重绘,所以回流是一件很消耗性能的事情

  • 开发中要尽量避免发生回流

  • 修改样式尽量一次性修改完毕

    • 例如通过cssText一次性设置样式,或通过修改class的方式修改样式
  • 尽量避免频繁的操作DOM

    • 可以在一个DocumentFragment或者父元素中,将要操作的DOM操作完成,再一次性插入到DOM树中
  • 尽量避免通过getComputedStyle获取元素尺寸、位置等信息

  • 对某些元素使用position的absolute或fixed属性

    • 并不是不会引起回流,而是开销相对较小,不会对其他元素产生影响

特殊解析: composite合成

在绘制的过程中,可以将布局后的元素绘制到多个合成图层中

  • 这是浏览器的一种优化手段
  • 将不同流生成的不同Layer进行合并
标准流 => LayouTree => RenderLayer
 \`position:fixed;\` => RenderLayer
 

默认情况,标准流中的内容都是被绘制在同一个图层(Layer)中的

而一些特殊的属性,浏览器会创建一个新的合成层(CompositingLayer),并且新的图层可以利用GPU来加速绘制

  • 每个合成层都是单独渲染的
  • 单独渲染可以避免所有的动画都在同一层中渲染导致性能问题
  • 在各自的层中渲染完成后,只需要将渲染结果更新回合成层即可

当元素具有哪些属性时,浏览器会为其创建新的合成层呢?

  • 3D Transforms
  • video canvas iframe
  • opacity 动画转换时
  • position: fixed
  • will-change: 一个实验性的属性,提前告诉浏览器此元素可能发生哪些变化
  • animation 或 transition设置了opacity、transform

案例1:同一层渲染

.box1 {
   width: 100px;
diff --git a/assets/article_深入理解浏览器运行原理.md.4b1c1d16.lean.js b/assets/article_深入理解浏览器运行原理.md.f13b2b23.lean.js
similarity index 97%
rename from assets/article_深入理解浏览器运行原理.md.4b1c1d16.lean.js
rename to assets/article_深入理解浏览器运行原理.md.f13b2b23.lean.js
index 6752f389..aa023abf 100644
--- a/assets/article_深入理解浏览器运行原理.md.4b1c1d16.lean.js
+++ b/assets/article_深入理解浏览器运行原理.md.f13b2b23.lean.js
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as e}from"./app.33820b61.js";const m=JSON.parse('{"title":"深入理解浏览器运行原理","description":"","frontmatter":{},"headers":[{"level":2,"title":"网页解析过程","slug":"网页解析过程","link":"#网页解析过程","children":[]},{"level":2,"title":"HTML解析过程","slug":"html解析过程","link":"#html解析过程","children":[]},{"level":2,"title":"生成CSS规则","slug":"生成css规则","link":"#生成css规则","children":[]},{"level":2,"title":"构建Render Tree","slug":"构建render-tree","link":"#构建render-tree","children":[]},{"level":2,"title":"布局和绘制(Layout & Paint)","slug":"布局和绘制-layout-paint","link":"#布局和绘制-layout-paint","children":[]},{"level":2,"title":"回流和重绘(Reflow & )","slug":"回流和重绘-reflow","link":"#回流和重绘-reflow","children":[]},{"level":2,"title":"特殊解析: composite合成","slug":"特殊解析-composite合成","link":"#特殊解析-composite合成","children":[{"level":3,"title":"案例1:同一层渲染","slug":"案例1-同一层渲染","link":"#案例1-同一层渲染","children":[]},{"level":3,"title":"案例2:分层渲染","slug":"案例2-分层渲染","link":"#案例2-分层渲染","children":[]},{"level":3,"title":"案例3:transform 3D","slug":"案例3-transform-3d","link":"#案例3-transform-3d","children":[]},{"level":3,"title":"案例4:transition+transform","slug":"案例4-transition-transform","link":"#案例4-transition-transform","children":[]},{"level":3,"title":"案例5:transition+opacity","slug":"案例5-transition-opacity","link":"#案例5-transition-opacity","children":[]},{"level":3,"title":"总结","slug":"总结","link":"#总结","children":[]}]},{"level":2,"title":"浏览器对script元素的处理","slug":"浏览器对script元素的处理","link":"#浏览器对script元素的处理","children":[]},{"level":2,"title":"defer属性","slug":"defer属性","link":"#defer属性","children":[]},{"level":2,"title":"async属性","slug":"async属性","link":"#async属性","children":[]}],"relativePath":"article/深入理解浏览器运行原理.md","lastUpdated":1676737739000}'),l={name:"article/深入理解浏览器运行原理.md"},p=e("",87),i=[p];function r(c,t,o,d,u,b){return n(),a("div",null,i)}const C=s(l,[["render",r]]);export{m as __pageData,C as default};
+import{_ as s,o as n,c as a,a as e}from"./app.33820b61.js";const m=JSON.parse('{"title":"深入理解浏览器运行原理","description":"","frontmatter":{},"headers":[{"level":2,"title":"网页解析过程","slug":"网页解析过程","link":"#网页解析过程","children":[]},{"level":2,"title":"HTML解析过程","slug":"html解析过程","link":"#html解析过程","children":[]},{"level":2,"title":"生成CSS规则","slug":"生成css规则","link":"#生成css规则","children":[]},{"level":2,"title":"构建Render Tree","slug":"构建render-tree","link":"#构建render-tree","children":[]},{"level":2,"title":"布局和绘制(Layout & Paint)","slug":"布局和绘制-layout-paint","link":"#布局和绘制-layout-paint","children":[]},{"level":2,"title":"回流和重绘(Reflow & )","slug":"回流和重绘-reflow","link":"#回流和重绘-reflow","children":[]},{"level":2,"title":"特殊解析: composite合成","slug":"特殊解析-composite合成","link":"#特殊解析-composite合成","children":[{"level":3,"title":"案例1:同一层渲染","slug":"案例1-同一层渲染","link":"#案例1-同一层渲染","children":[]},{"level":3,"title":"案例2:分层渲染","slug":"案例2-分层渲染","link":"#案例2-分层渲染","children":[]},{"level":3,"title":"案例3:transform 3D","slug":"案例3-transform-3d","link":"#案例3-transform-3d","children":[]},{"level":3,"title":"案例4:transition+transform","slug":"案例4-transition-transform","link":"#案例4-transition-transform","children":[]},{"level":3,"title":"案例5:transition+opacity","slug":"案例5-transition-opacity","link":"#案例5-transition-opacity","children":[]},{"level":3,"title":"总结","slug":"总结","link":"#总结","children":[]}]},{"level":2,"title":"浏览器对script元素的处理","slug":"浏览器对script元素的处理","link":"#浏览器对script元素的处理","children":[]},{"level":2,"title":"defer属性","slug":"defer属性","link":"#defer属性","children":[]},{"level":2,"title":"async属性","slug":"async属性","link":"#async属性","children":[]}],"relativePath":"article/深入理解浏览器运行原理.md","lastUpdated":1676979063000}'),l={name:"article/深入理解浏览器运行原理.md"},p=e("",87),i=[p];function r(c,t,o,d,u,b){return n(),a("div",null,i)}const C=s(l,[["render",r]]);export{m as __pageData,C as default};
diff --git a/assets/index.md.e391bcbf.js b/assets/index.md.00c51c0e.js
similarity index 92%
rename from assets/index.md.e391bcbf.js
rename to assets/index.md.00c51c0e.js
index 35ba0b5e..34a678f1 100644
--- a/assets/index.md.e391bcbf.js
+++ b/assets/index.md.00c51c0e.js
@@ -1 +1 @@
-import{_ as t,o as e,c as i}from"./app.33820b61.js";const p=JSON.parse('{"title":"主页","description":"","frontmatter":{"layout":"home","title":"主页","hero":{"name":"ZiuChen","text":"无限进步.","tagline":"Infinite Progress...","actions":[{"theme":"brand","text":"Get Started","link":"/self/"},{"theme":"alt","text":"View on GitHub","link":"https://github.com/ZiuChen"}]},"features":[{"icon":"🎓","title":"Electronic Information Major","details":"电子信息工程"},{"icon":"🎯","title":"JavaScript & TypeScript","details":"自学前端 热爱技术"},{"icon":"👆","title":"See more information","details":"访问导航栏查看更多信息"}]},"headers":[],"relativePath":"index.md","lastUpdated":1676737739000}'),a={name:"index.md"};function n(o,r,s,c,l,d){return e(),i("div")}const f=t(a,[["render",n]]);export{p as __pageData,f as default};
+import{_ as t,o as e,c as i}from"./app.33820b61.js";const p=JSON.parse('{"title":"主页","description":"","frontmatter":{"layout":"home","title":"主页","hero":{"name":"ZiuChen","text":"无限进步.","tagline":"Infinite Progress...","actions":[{"theme":"brand","text":"Get Started","link":"/self/"},{"theme":"alt","text":"View on GitHub","link":"https://github.com/ZiuChen"}]},"features":[{"icon":"🎓","title":"Electronic Information Major","details":"电子信息工程"},{"icon":"🎯","title":"JavaScript & TypeScript","details":"自学前端 热爱技术"},{"icon":"👆","title":"See more information","details":"访问导航栏查看更多信息"}]},"headers":[],"relativePath":"index.md","lastUpdated":1676979063000}'),a={name:"index.md"};function n(o,r,s,c,l,d){return e(),i("div")}const f=t(a,[["render",n]]);export{p as __pageData,f as default};
diff --git a/assets/index.md.e391bcbf.lean.js b/assets/index.md.00c51c0e.lean.js
similarity index 92%
rename from assets/index.md.e391bcbf.lean.js
rename to assets/index.md.00c51c0e.lean.js
index 35ba0b5e..34a678f1 100644
--- a/assets/index.md.e391bcbf.lean.js
+++ b/assets/index.md.00c51c0e.lean.js
@@ -1 +1 @@
-import{_ as t,o as e,c as i}from"./app.33820b61.js";const p=JSON.parse('{"title":"主页","description":"","frontmatter":{"layout":"home","title":"主页","hero":{"name":"ZiuChen","text":"无限进步.","tagline":"Infinite Progress...","actions":[{"theme":"brand","text":"Get Started","link":"/self/"},{"theme":"alt","text":"View on GitHub","link":"https://github.com/ZiuChen"}]},"features":[{"icon":"🎓","title":"Electronic Information Major","details":"电子信息工程"},{"icon":"🎯","title":"JavaScript & TypeScript","details":"自学前端 热爱技术"},{"icon":"👆","title":"See more information","details":"访问导航栏查看更多信息"}]},"headers":[],"relativePath":"index.md","lastUpdated":1676737739000}'),a={name:"index.md"};function n(o,r,s,c,l,d){return e(),i("div")}const f=t(a,[["render",n]]);export{p as __pageData,f as default};
+import{_ as t,o as e,c as i}from"./app.33820b61.js";const p=JSON.parse('{"title":"主页","description":"","frontmatter":{"layout":"home","title":"主页","hero":{"name":"ZiuChen","text":"无限进步.","tagline":"Infinite Progress...","actions":[{"theme":"brand","text":"Get Started","link":"/self/"},{"theme":"alt","text":"View on GitHub","link":"https://github.com/ZiuChen"}]},"features":[{"icon":"🎓","title":"Electronic Information Major","details":"电子信息工程"},{"icon":"🎯","title":"JavaScript & TypeScript","details":"自学前端 热爱技术"},{"icon":"👆","title":"See more information","details":"访问导航栏查看更多信息"}]},"headers":[],"relativePath":"index.md","lastUpdated":1676979063000}'),a={name:"index.md"};function n(o,r,s,c,l,d){return e(),i("div")}const f=t(a,[["render",n]]);export{p as __pageData,f as default};
diff --git a/assets/note_CSS.md.2c88cba1.js b/assets/note_CSS.md.a4f3e631.js
similarity index 99%
rename from assets/note_CSS.md.2c88cba1.js
rename to assets/note_CSS.md.a4f3e631.js
index 764b3df6..528a6ddb 100644
--- a/assets/note_CSS.md.2c88cba1.js
+++ b/assets/note_CSS.md.a4f3e631.js
@@ -1,4 +1,4 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const e="/assets/BFC-1.ed3fcfd0.jpg",p="/assets/BFC-2.3c4a8bbc.jpg",o="/assets/BFC-3.7daed619.jpg",c="/assets/BFC-4.b58515a7.jpg",A=JSON.parse('{"title":"CSS基础","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"文本样式(text)","slug":"文本样式-text","link":"#文本样式-text","children":[{"level":3,"title":"text-align(重要)","slug":"text-align-重要","link":"#text-align-重要","children":[]},{"level":3,"title":"letter-spacing word-spacing(了解)","slug":"letter-spacing-word-spacing-了解","link":"#letter-spacing-word-spacing-了解","children":[]}]},{"level":2,"title":"字体样式(font)","slug":"字体样式-font","link":"#字体样式-font","children":[{"level":3,"title":"font-size","slug":"font-size","link":"#font-size","children":[]},{"level":3,"title":"font-family(了解)","slug":"font-family-了解","link":"#font-family-了解","children":[]},{"level":3,"title":"font-weight(重要)","slug":"font-weight-重要","link":"#font-weight-重要","children":[]},{"level":3,"title":"font-style(了解)","slug":"font-style-了解","link":"#font-style-了解","children":[]},{"level":3,"title":"font-variant(了解)","slug":"font-variant-了解","link":"#font-variant-了解","children":[]},{"level":3,"title":"line-height(重要)","slug":"line-height-重要","link":"#line-height-重要","children":[]},{"level":3,"title":"font 缩写属性","slug":"font-缩写属性","link":"#font-缩写属性","children":[]}]},{"level":2,"title":"CSS选择器","slug":"css选择器","link":"#css选择器","children":[{"level":3,"title":"后代选择器","slug":"后代选择器","link":"#后代选择器","children":[]},{"level":3,"title":"直接子代选择器","slug":"直接子代选择器","link":"#直接子代选择器","children":[]},{"level":3,"title":"兄弟选择器","slug":"兄弟选择器","link":"#兄弟选择器","children":[]},{"level":3,"title":"选择器组","slug":"选择器组","link":"#选择器组","children":[]},{"level":3,"title":"伪类","slug":"伪类","link":"#伪类","children":[]},{"level":3,"title":"结构伪类","slug":"结构伪类","link":"#结构伪类","children":[]},{"level":3,"title":"伪元素","slug":"伪元素","link":"#伪元素","children":[]}]},{"level":2,"title":"CSS特性(重要)","slug":"css特性-重要","link":"#css特性-重要","children":[{"level":3,"title":"属性的继承","slug":"属性的继承","link":"#属性的继承","children":[]},{"level":3,"title":"属性的层叠","slug":"属性的层叠","link":"#属性的层叠","children":[]},{"level":3,"title":"HTML元素的类型","slug":"html元素的类型","link":"#html元素的类型","children":[]}]},{"level":2,"title":"CSS技巧","slug":"css技巧","link":"#css技巧","children":[{"level":3,"title":"元素隐藏方法","slug":"元素隐藏方法","link":"#元素隐藏方法","children":[]},{"level":3,"title":"样式不生效","slug":"样式不生效","link":"#样式不生效","children":[]}]},{"level":2,"title":"CSS盒子模型","slug":"css盒子模型","link":"#css盒子模型","children":[{"level":3,"title":"内容 width / height","slug":"内容-width-height","link":"#内容-width-height","children":[]},{"level":3,"title":"内边距 padding","slug":"内边距-padding","link":"#内边距-padding","children":[]},{"level":3,"title":"边框 border","slug":"边框-border","link":"#边框-border","children":[]},{"level":3,"title":"外边距 margin","slug":"外边距-margin","link":"#外边距-margin","children":[]},{"level":3,"title":"额外知识点","slug":"额外知识点","link":"#额外知识点","children":[]},{"level":3,"title":"外轮廓 outline","slug":"外轮廓-outline","link":"#外轮廓-outline","children":[]},{"level":3,"title":"盒子阴影 box-shadow","slug":"盒子阴影-box-shadow","link":"#盒子阴影-box-shadow","children":[]},{"level":3,"title":"行内非替换元素的注意事项","slug":"行内非替换元素的注意事项","link":"#行内非替换元素的注意事项","children":[]}]},{"level":2,"title":"CSS元素定位","slug":"css元素定位","link":"#css元素定位","children":[{"level":3,"title":"标准流","slug":"标准流","link":"#标准流","children":[]},{"level":3,"title":"认识元素的定位","slug":"认识元素的定位","link":"#认识元素的定位","children":[]},{"level":3,"title":"position属性取值","slug":"position属性取值","link":"#position属性取值","children":[]},{"level":3,"title":"绝对定位元素的特点","slug":"绝对定位元素的特点","link":"#绝对定位元素的特点","children":[]},{"level":3,"title":"z-index解析","slug":"z-index解析","link":"#z-index解析","children":[]}]},{"level":2,"title":"浮动布局","slug":"浮动布局","link":"#浮动布局","children":[{"level":3,"title":"认识浮动布局","slug":"认识浮动布局","link":"#认识浮动布局","children":[]},{"level":3,"title":"浮动案例","slug":"浮动案例","link":"#浮动案例","children":[]},{"level":3,"title":"浮动规则","slug":"浮动规则","link":"#浮动规则","children":[]},{"level":3,"title":"通过清除浮动实现布局(TODO)","slug":"通过清除浮动实现布局-todo","link":"#通过清除浮动实现布局-todo","children":[]}]},{"level":2,"title":"Flex布局","slug":"flex布局","link":"#flex布局","children":[{"level":3,"title":"认识Flex布局","slug":"认识flex布局","link":"#认识flex布局","children":[]},{"level":3,"title":"flex布局的重要概念","slug":"flex布局的重要概念","link":"#flex布局的重要概念","children":[]},{"level":3,"title":"flex相关的属性","slug":"flex相关的属性","link":"#flex相关的属性","children":[]},{"level":3,"title":"案例:解决布局问题","slug":"案例-解决布局问题","link":"#案例-解决布局问题","children":[]}]},{"level":2,"title":"CSS中的函数","slug":"css中的函数","link":"#css中的函数","children":[{"level":3,"title":"var  变量","slug":"var-变量","link":"#var-变量","children":[]},{"level":3,"title":"calc 计算","slug":"calc-计算","link":"#calc-计算","children":[]},{"level":3,"title":"blur 高斯模糊","slug":"blur-高斯模糊","link":"#blur-高斯模糊","children":[]},{"level":3,"title":"gradient 颜色渐变","slug":"gradient-颜色渐变","link":"#gradient-颜色渐变","children":[]}]},{"level":2,"title":"CSS求值过程","slug":"css求值过程","link":"#css求值过程","children":[]},{"level":2,"title":"移动端开发","slug":"移动端开发","link":"#移动端开发","children":[]},{"level":2,"title":"额外知识补充","slug":"额外知识补充","link":"#额外知识补充","children":[{"level":3,"title":"浏览器前缀","slug":"浏览器前缀","link":"#浏览器前缀","children":[]},{"level":3,"title":"深入理解BFC(重点)","slug":"深入理解bfc-重点","link":"#深入理解bfc-重点","children":[]},{"level":3,"title":"媒体查询","slug":"媒体查询","link":"#媒体查询","children":[]},{"level":3,"title":"link元素的使用","slug":"link元素的使用","link":"#link元素的使用","children":[]},{"level":3,"title":"CSS颜色的表示方式","slug":"css颜色的表示方式","link":"#css颜色的表示方式","children":[]},{"level":3,"title":"网络字体","slug":"网络字体","link":"#网络字体","children":[]},{"level":3,"title":"字体图标","slug":"字体图标","link":"#字体图标","children":[]},{"level":3,"title":"精灵图 雪碧图","slug":"精灵图-雪碧图","link":"#精灵图-雪碧图","children":[]},{"level":3,"title":"white-space","slug":"white-space","link":"#white-space","children":[]},{"level":3,"title":"text-overflow","slug":"text-overflow","link":"#text-overflow","children":[]},{"level":3,"title":"水平垂直居中方案","slug":"水平垂直居中方案","link":"#水平垂直居中方案","children":[]},{"level":3,"title":"内联元素居中布局","slug":"内联元素居中布局","link":"#内联元素居中布局","children":[]},{"level":3,"title":"块级元素居中布局","slug":"块级元素居中布局","link":"#块级元素居中布局","children":[]}]},{"level":2,"title":"HTML5新增内容","slug":"html5新增内容","link":"#html5新增内容","children":[{"level":3,"title":"语义化元素","slug":"语义化元素","link":"#语义化元素","children":[]},{"level":3,"title":"video标签","slug":"video标签","link":"#video标签","children":[]},{"level":3,"title":"audio标签","slug":"audio标签","link":"#audio标签","children":[]},{"level":3,"title":"input元素","slug":"input元素","link":"#input元素","children":[]},{"level":3,"title":"全局新增属性 data-*","slug":"全局新增属性-data","link":"#全局新增属性-data","children":[]}]}],"relativePath":"note/CSS.md","lastUpdated":1676737739000}'),t={name:"note/CSS.md"},r=l(`

CSS基础

CSS提供了三种方法,可以将CSS样式应用到元素上:

  • 内联样式
    • 直接将样式写到元素的style属性上
  • 内部样式表
    • 将样式通过<style>标签写在<head>标签中,通过选择器应用到元素上
  • 外部样式表
    • 将样式写在外部文件如style.css中,再通过<link>标签引入

文本样式(text)

  • text-decoration 框线样式
    • line-through 删除线
    • overline 上划线
    • underline 下划线
    • none 不设置装饰线
  • text-transform
    • text-transform 属性指定如何将元素的文本大写。
    • 它可以用于使文本显示为全大写或全小写,也可单独对每一个单词进行操作。
  • text-indent
    • text-indent 属性能定义一个块元素首行文本内容之前的缩进量。
  • text-align
  • word/letter-spacing

text-align(重要)

行内内容(例如文字)如何相对它的块父元素对齐,left靠左 center居中 right靠右 justify两端对齐

默认值为left

需要注意的是,当子元素是div时,对父元素设置text-align是不生效的:

css
.box {
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const e="/assets/BFC-1.ed3fcfd0.jpg",p="/assets/BFC-2.3c4a8bbc.jpg",o="/assets/BFC-3.7daed619.jpg",c="/assets/BFC-4.b58515a7.jpg",A=JSON.parse('{"title":"CSS基础","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"文本样式(text)","slug":"文本样式-text","link":"#文本样式-text","children":[{"level":3,"title":"text-align(重要)","slug":"text-align-重要","link":"#text-align-重要","children":[]},{"level":3,"title":"letter-spacing word-spacing(了解)","slug":"letter-spacing-word-spacing-了解","link":"#letter-spacing-word-spacing-了解","children":[]}]},{"level":2,"title":"字体样式(font)","slug":"字体样式-font","link":"#字体样式-font","children":[{"level":3,"title":"font-size","slug":"font-size","link":"#font-size","children":[]},{"level":3,"title":"font-family(了解)","slug":"font-family-了解","link":"#font-family-了解","children":[]},{"level":3,"title":"font-weight(重要)","slug":"font-weight-重要","link":"#font-weight-重要","children":[]},{"level":3,"title":"font-style(了解)","slug":"font-style-了解","link":"#font-style-了解","children":[]},{"level":3,"title":"font-variant(了解)","slug":"font-variant-了解","link":"#font-variant-了解","children":[]},{"level":3,"title":"line-height(重要)","slug":"line-height-重要","link":"#line-height-重要","children":[]},{"level":3,"title":"font 缩写属性","slug":"font-缩写属性","link":"#font-缩写属性","children":[]}]},{"level":2,"title":"CSS选择器","slug":"css选择器","link":"#css选择器","children":[{"level":3,"title":"后代选择器","slug":"后代选择器","link":"#后代选择器","children":[]},{"level":3,"title":"直接子代选择器","slug":"直接子代选择器","link":"#直接子代选择器","children":[]},{"level":3,"title":"兄弟选择器","slug":"兄弟选择器","link":"#兄弟选择器","children":[]},{"level":3,"title":"选择器组","slug":"选择器组","link":"#选择器组","children":[]},{"level":3,"title":"伪类","slug":"伪类","link":"#伪类","children":[]},{"level":3,"title":"结构伪类","slug":"结构伪类","link":"#结构伪类","children":[]},{"level":3,"title":"伪元素","slug":"伪元素","link":"#伪元素","children":[]}]},{"level":2,"title":"CSS特性(重要)","slug":"css特性-重要","link":"#css特性-重要","children":[{"level":3,"title":"属性的继承","slug":"属性的继承","link":"#属性的继承","children":[]},{"level":3,"title":"属性的层叠","slug":"属性的层叠","link":"#属性的层叠","children":[]},{"level":3,"title":"HTML元素的类型","slug":"html元素的类型","link":"#html元素的类型","children":[]}]},{"level":2,"title":"CSS技巧","slug":"css技巧","link":"#css技巧","children":[{"level":3,"title":"元素隐藏方法","slug":"元素隐藏方法","link":"#元素隐藏方法","children":[]},{"level":3,"title":"样式不生效","slug":"样式不生效","link":"#样式不生效","children":[]}]},{"level":2,"title":"CSS盒子模型","slug":"css盒子模型","link":"#css盒子模型","children":[{"level":3,"title":"内容 width / height","slug":"内容-width-height","link":"#内容-width-height","children":[]},{"level":3,"title":"内边距 padding","slug":"内边距-padding","link":"#内边距-padding","children":[]},{"level":3,"title":"边框 border","slug":"边框-border","link":"#边框-border","children":[]},{"level":3,"title":"外边距 margin","slug":"外边距-margin","link":"#外边距-margin","children":[]},{"level":3,"title":"额外知识点","slug":"额外知识点","link":"#额外知识点","children":[]},{"level":3,"title":"外轮廓 outline","slug":"外轮廓-outline","link":"#外轮廓-outline","children":[]},{"level":3,"title":"盒子阴影 box-shadow","slug":"盒子阴影-box-shadow","link":"#盒子阴影-box-shadow","children":[]},{"level":3,"title":"行内非替换元素的注意事项","slug":"行内非替换元素的注意事项","link":"#行内非替换元素的注意事项","children":[]}]},{"level":2,"title":"CSS元素定位","slug":"css元素定位","link":"#css元素定位","children":[{"level":3,"title":"标准流","slug":"标准流","link":"#标准流","children":[]},{"level":3,"title":"认识元素的定位","slug":"认识元素的定位","link":"#认识元素的定位","children":[]},{"level":3,"title":"position属性取值","slug":"position属性取值","link":"#position属性取值","children":[]},{"level":3,"title":"绝对定位元素的特点","slug":"绝对定位元素的特点","link":"#绝对定位元素的特点","children":[]},{"level":3,"title":"z-index解析","slug":"z-index解析","link":"#z-index解析","children":[]}]},{"level":2,"title":"浮动布局","slug":"浮动布局","link":"#浮动布局","children":[{"level":3,"title":"认识浮动布局","slug":"认识浮动布局","link":"#认识浮动布局","children":[]},{"level":3,"title":"浮动案例","slug":"浮动案例","link":"#浮动案例","children":[]},{"level":3,"title":"浮动规则","slug":"浮动规则","link":"#浮动规则","children":[]},{"level":3,"title":"通过清除浮动实现布局(TODO)","slug":"通过清除浮动实现布局-todo","link":"#通过清除浮动实现布局-todo","children":[]}]},{"level":2,"title":"Flex布局","slug":"flex布局","link":"#flex布局","children":[{"level":3,"title":"认识Flex布局","slug":"认识flex布局","link":"#认识flex布局","children":[]},{"level":3,"title":"flex布局的重要概念","slug":"flex布局的重要概念","link":"#flex布局的重要概念","children":[]},{"level":3,"title":"flex相关的属性","slug":"flex相关的属性","link":"#flex相关的属性","children":[]},{"level":3,"title":"案例:解决布局问题","slug":"案例-解决布局问题","link":"#案例-解决布局问题","children":[]}]},{"level":2,"title":"CSS中的函数","slug":"css中的函数","link":"#css中的函数","children":[{"level":3,"title":"var  变量","slug":"var-变量","link":"#var-变量","children":[]},{"level":3,"title":"calc 计算","slug":"calc-计算","link":"#calc-计算","children":[]},{"level":3,"title":"blur 高斯模糊","slug":"blur-高斯模糊","link":"#blur-高斯模糊","children":[]},{"level":3,"title":"gradient 颜色渐变","slug":"gradient-颜色渐变","link":"#gradient-颜色渐变","children":[]}]},{"level":2,"title":"CSS求值过程","slug":"css求值过程","link":"#css求值过程","children":[]},{"level":2,"title":"移动端开发","slug":"移动端开发","link":"#移动端开发","children":[]},{"level":2,"title":"额外知识补充","slug":"额外知识补充","link":"#额外知识补充","children":[{"level":3,"title":"浏览器前缀","slug":"浏览器前缀","link":"#浏览器前缀","children":[]},{"level":3,"title":"深入理解BFC(重点)","slug":"深入理解bfc-重点","link":"#深入理解bfc-重点","children":[]},{"level":3,"title":"媒体查询","slug":"媒体查询","link":"#媒体查询","children":[]},{"level":3,"title":"link元素的使用","slug":"link元素的使用","link":"#link元素的使用","children":[]},{"level":3,"title":"CSS颜色的表示方式","slug":"css颜色的表示方式","link":"#css颜色的表示方式","children":[]},{"level":3,"title":"网络字体","slug":"网络字体","link":"#网络字体","children":[]},{"level":3,"title":"字体图标","slug":"字体图标","link":"#字体图标","children":[]},{"level":3,"title":"精灵图 雪碧图","slug":"精灵图-雪碧图","link":"#精灵图-雪碧图","children":[]},{"level":3,"title":"white-space","slug":"white-space","link":"#white-space","children":[]},{"level":3,"title":"text-overflow","slug":"text-overflow","link":"#text-overflow","children":[]},{"level":3,"title":"水平垂直居中方案","slug":"水平垂直居中方案","link":"#水平垂直居中方案","children":[]},{"level":3,"title":"内联元素居中布局","slug":"内联元素居中布局","link":"#内联元素居中布局","children":[]},{"level":3,"title":"块级元素居中布局","slug":"块级元素居中布局","link":"#块级元素居中布局","children":[]}]},{"level":2,"title":"HTML5新增内容","slug":"html5新增内容","link":"#html5新增内容","children":[{"level":3,"title":"语义化元素","slug":"语义化元素","link":"#语义化元素","children":[]},{"level":3,"title":"video标签","slug":"video标签","link":"#video标签","children":[]},{"level":3,"title":"audio标签","slug":"audio标签","link":"#audio标签","children":[]},{"level":3,"title":"input元素","slug":"input元素","link":"#input元素","children":[]},{"level":3,"title":"全局新增属性 data-*","slug":"全局新增属性-data","link":"#全局新增属性-data","children":[]}]}],"relativePath":"note/CSS.md","lastUpdated":1676979063000}'),t={name:"note/CSS.md"},r=l(`

CSS基础

CSS提供了三种方法,可以将CSS样式应用到元素上:

  • 内联样式
    • 直接将样式写到元素的style属性上
  • 内部样式表
    • 将样式通过<style>标签写在<head>标签中,通过选择器应用到元素上
  • 外部样式表
    • 将样式写在外部文件如style.css中,再通过<link>标签引入

文本样式(text)

  • text-decoration 框线样式
    • line-through 删除线
    • overline 上划线
    • underline 下划线
    • none 不设置装饰线
  • text-transform
    • text-transform 属性指定如何将元素的文本大写。
    • 它可以用于使文本显示为全大写或全小写,也可单独对每一个单词进行操作。
  • text-indent
    • text-indent 属性能定义一个块元素首行文本内容之前的缩进量。
  • text-align
  • word/letter-spacing

text-align(重要)

行内内容(例如文字)如何相对它的块父元素对齐,left靠左 center居中 right靠右 justify两端对齐

默认值为left

需要注意的是,当子元素是div时,对父元素设置text-align是不生效的:

css
.box {
   height: 500px;
   text-align: center;
   background-color: red;
diff --git a/assets/note_CSS.md.2c88cba1.lean.js b/assets/note_CSS.md.a4f3e631.lean.js
similarity index 99%
rename from assets/note_CSS.md.2c88cba1.lean.js
rename to assets/note_CSS.md.a4f3e631.lean.js
index 266f575e..7293dfe4 100644
--- a/assets/note_CSS.md.2c88cba1.lean.js
+++ b/assets/note_CSS.md.a4f3e631.lean.js
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const e="/assets/BFC-1.ed3fcfd0.jpg",p="/assets/BFC-2.3c4a8bbc.jpg",o="/assets/BFC-3.7daed619.jpg",c="/assets/BFC-4.b58515a7.jpg",A=JSON.parse('{"title":"CSS基础","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"文本样式(text)","slug":"文本样式-text","link":"#文本样式-text","children":[{"level":3,"title":"text-align(重要)","slug":"text-align-重要","link":"#text-align-重要","children":[]},{"level":3,"title":"letter-spacing word-spacing(了解)","slug":"letter-spacing-word-spacing-了解","link":"#letter-spacing-word-spacing-了解","children":[]}]},{"level":2,"title":"字体样式(font)","slug":"字体样式-font","link":"#字体样式-font","children":[{"level":3,"title":"font-size","slug":"font-size","link":"#font-size","children":[]},{"level":3,"title":"font-family(了解)","slug":"font-family-了解","link":"#font-family-了解","children":[]},{"level":3,"title":"font-weight(重要)","slug":"font-weight-重要","link":"#font-weight-重要","children":[]},{"level":3,"title":"font-style(了解)","slug":"font-style-了解","link":"#font-style-了解","children":[]},{"level":3,"title":"font-variant(了解)","slug":"font-variant-了解","link":"#font-variant-了解","children":[]},{"level":3,"title":"line-height(重要)","slug":"line-height-重要","link":"#line-height-重要","children":[]},{"level":3,"title":"font 缩写属性","slug":"font-缩写属性","link":"#font-缩写属性","children":[]}]},{"level":2,"title":"CSS选择器","slug":"css选择器","link":"#css选择器","children":[{"level":3,"title":"后代选择器","slug":"后代选择器","link":"#后代选择器","children":[]},{"level":3,"title":"直接子代选择器","slug":"直接子代选择器","link":"#直接子代选择器","children":[]},{"level":3,"title":"兄弟选择器","slug":"兄弟选择器","link":"#兄弟选择器","children":[]},{"level":3,"title":"选择器组","slug":"选择器组","link":"#选择器组","children":[]},{"level":3,"title":"伪类","slug":"伪类","link":"#伪类","children":[]},{"level":3,"title":"结构伪类","slug":"结构伪类","link":"#结构伪类","children":[]},{"level":3,"title":"伪元素","slug":"伪元素","link":"#伪元素","children":[]}]},{"level":2,"title":"CSS特性(重要)","slug":"css特性-重要","link":"#css特性-重要","children":[{"level":3,"title":"属性的继承","slug":"属性的继承","link":"#属性的继承","children":[]},{"level":3,"title":"属性的层叠","slug":"属性的层叠","link":"#属性的层叠","children":[]},{"level":3,"title":"HTML元素的类型","slug":"html元素的类型","link":"#html元素的类型","children":[]}]},{"level":2,"title":"CSS技巧","slug":"css技巧","link":"#css技巧","children":[{"level":3,"title":"元素隐藏方法","slug":"元素隐藏方法","link":"#元素隐藏方法","children":[]},{"level":3,"title":"样式不生效","slug":"样式不生效","link":"#样式不生效","children":[]}]},{"level":2,"title":"CSS盒子模型","slug":"css盒子模型","link":"#css盒子模型","children":[{"level":3,"title":"内容 width / height","slug":"内容-width-height","link":"#内容-width-height","children":[]},{"level":3,"title":"内边距 padding","slug":"内边距-padding","link":"#内边距-padding","children":[]},{"level":3,"title":"边框 border","slug":"边框-border","link":"#边框-border","children":[]},{"level":3,"title":"外边距 margin","slug":"外边距-margin","link":"#外边距-margin","children":[]},{"level":3,"title":"额外知识点","slug":"额外知识点","link":"#额外知识点","children":[]},{"level":3,"title":"外轮廓 outline","slug":"外轮廓-outline","link":"#外轮廓-outline","children":[]},{"level":3,"title":"盒子阴影 box-shadow","slug":"盒子阴影-box-shadow","link":"#盒子阴影-box-shadow","children":[]},{"level":3,"title":"行内非替换元素的注意事项","slug":"行内非替换元素的注意事项","link":"#行内非替换元素的注意事项","children":[]}]},{"level":2,"title":"CSS元素定位","slug":"css元素定位","link":"#css元素定位","children":[{"level":3,"title":"标准流","slug":"标准流","link":"#标准流","children":[]},{"level":3,"title":"认识元素的定位","slug":"认识元素的定位","link":"#认识元素的定位","children":[]},{"level":3,"title":"position属性取值","slug":"position属性取值","link":"#position属性取值","children":[]},{"level":3,"title":"绝对定位元素的特点","slug":"绝对定位元素的特点","link":"#绝对定位元素的特点","children":[]},{"level":3,"title":"z-index解析","slug":"z-index解析","link":"#z-index解析","children":[]}]},{"level":2,"title":"浮动布局","slug":"浮动布局","link":"#浮动布局","children":[{"level":3,"title":"认识浮动布局","slug":"认识浮动布局","link":"#认识浮动布局","children":[]},{"level":3,"title":"浮动案例","slug":"浮动案例","link":"#浮动案例","children":[]},{"level":3,"title":"浮动规则","slug":"浮动规则","link":"#浮动规则","children":[]},{"level":3,"title":"通过清除浮动实现布局(TODO)","slug":"通过清除浮动实现布局-todo","link":"#通过清除浮动实现布局-todo","children":[]}]},{"level":2,"title":"Flex布局","slug":"flex布局","link":"#flex布局","children":[{"level":3,"title":"认识Flex布局","slug":"认识flex布局","link":"#认识flex布局","children":[]},{"level":3,"title":"flex布局的重要概念","slug":"flex布局的重要概念","link":"#flex布局的重要概念","children":[]},{"level":3,"title":"flex相关的属性","slug":"flex相关的属性","link":"#flex相关的属性","children":[]},{"level":3,"title":"案例:解决布局问题","slug":"案例-解决布局问题","link":"#案例-解决布局问题","children":[]}]},{"level":2,"title":"CSS中的函数","slug":"css中的函数","link":"#css中的函数","children":[{"level":3,"title":"var  变量","slug":"var-变量","link":"#var-变量","children":[]},{"level":3,"title":"calc 计算","slug":"calc-计算","link":"#calc-计算","children":[]},{"level":3,"title":"blur 高斯模糊","slug":"blur-高斯模糊","link":"#blur-高斯模糊","children":[]},{"level":3,"title":"gradient 颜色渐变","slug":"gradient-颜色渐变","link":"#gradient-颜色渐变","children":[]}]},{"level":2,"title":"CSS求值过程","slug":"css求值过程","link":"#css求值过程","children":[]},{"level":2,"title":"移动端开发","slug":"移动端开发","link":"#移动端开发","children":[]},{"level":2,"title":"额外知识补充","slug":"额外知识补充","link":"#额外知识补充","children":[{"level":3,"title":"浏览器前缀","slug":"浏览器前缀","link":"#浏览器前缀","children":[]},{"level":3,"title":"深入理解BFC(重点)","slug":"深入理解bfc-重点","link":"#深入理解bfc-重点","children":[]},{"level":3,"title":"媒体查询","slug":"媒体查询","link":"#媒体查询","children":[]},{"level":3,"title":"link元素的使用","slug":"link元素的使用","link":"#link元素的使用","children":[]},{"level":3,"title":"CSS颜色的表示方式","slug":"css颜色的表示方式","link":"#css颜色的表示方式","children":[]},{"level":3,"title":"网络字体","slug":"网络字体","link":"#网络字体","children":[]},{"level":3,"title":"字体图标","slug":"字体图标","link":"#字体图标","children":[]},{"level":3,"title":"精灵图 雪碧图","slug":"精灵图-雪碧图","link":"#精灵图-雪碧图","children":[]},{"level":3,"title":"white-space","slug":"white-space","link":"#white-space","children":[]},{"level":3,"title":"text-overflow","slug":"text-overflow","link":"#text-overflow","children":[]},{"level":3,"title":"水平垂直居中方案","slug":"水平垂直居中方案","link":"#水平垂直居中方案","children":[]},{"level":3,"title":"内联元素居中布局","slug":"内联元素居中布局","link":"#内联元素居中布局","children":[]},{"level":3,"title":"块级元素居中布局","slug":"块级元素居中布局","link":"#块级元素居中布局","children":[]}]},{"level":2,"title":"HTML5新增内容","slug":"html5新增内容","link":"#html5新增内容","children":[{"level":3,"title":"语义化元素","slug":"语义化元素","link":"#语义化元素","children":[]},{"level":3,"title":"video标签","slug":"video标签","link":"#video标签","children":[]},{"level":3,"title":"audio标签","slug":"audio标签","link":"#audio标签","children":[]},{"level":3,"title":"input元素","slug":"input元素","link":"#input元素","children":[]},{"level":3,"title":"全局新增属性 data-*","slug":"全局新增属性-data","link":"#全局新增属性-data","children":[]}]}],"relativePath":"note/CSS.md","lastUpdated":1676737739000}'),t={name:"note/CSS.md"},r=l("",533),i=[r];function d(D,y,F,C,u,b){return n(),a("div",null,i)}const m=s(t,[["render",d]]);export{A as __pageData,m as default};
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const e="/assets/BFC-1.ed3fcfd0.jpg",p="/assets/BFC-2.3c4a8bbc.jpg",o="/assets/BFC-3.7daed619.jpg",c="/assets/BFC-4.b58515a7.jpg",A=JSON.parse('{"title":"CSS基础","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"文本样式(text)","slug":"文本样式-text","link":"#文本样式-text","children":[{"level":3,"title":"text-align(重要)","slug":"text-align-重要","link":"#text-align-重要","children":[]},{"level":3,"title":"letter-spacing word-spacing(了解)","slug":"letter-spacing-word-spacing-了解","link":"#letter-spacing-word-spacing-了解","children":[]}]},{"level":2,"title":"字体样式(font)","slug":"字体样式-font","link":"#字体样式-font","children":[{"level":3,"title":"font-size","slug":"font-size","link":"#font-size","children":[]},{"level":3,"title":"font-family(了解)","slug":"font-family-了解","link":"#font-family-了解","children":[]},{"level":3,"title":"font-weight(重要)","slug":"font-weight-重要","link":"#font-weight-重要","children":[]},{"level":3,"title":"font-style(了解)","slug":"font-style-了解","link":"#font-style-了解","children":[]},{"level":3,"title":"font-variant(了解)","slug":"font-variant-了解","link":"#font-variant-了解","children":[]},{"level":3,"title":"line-height(重要)","slug":"line-height-重要","link":"#line-height-重要","children":[]},{"level":3,"title":"font 缩写属性","slug":"font-缩写属性","link":"#font-缩写属性","children":[]}]},{"level":2,"title":"CSS选择器","slug":"css选择器","link":"#css选择器","children":[{"level":3,"title":"后代选择器","slug":"后代选择器","link":"#后代选择器","children":[]},{"level":3,"title":"直接子代选择器","slug":"直接子代选择器","link":"#直接子代选择器","children":[]},{"level":3,"title":"兄弟选择器","slug":"兄弟选择器","link":"#兄弟选择器","children":[]},{"level":3,"title":"选择器组","slug":"选择器组","link":"#选择器组","children":[]},{"level":3,"title":"伪类","slug":"伪类","link":"#伪类","children":[]},{"level":3,"title":"结构伪类","slug":"结构伪类","link":"#结构伪类","children":[]},{"level":3,"title":"伪元素","slug":"伪元素","link":"#伪元素","children":[]}]},{"level":2,"title":"CSS特性(重要)","slug":"css特性-重要","link":"#css特性-重要","children":[{"level":3,"title":"属性的继承","slug":"属性的继承","link":"#属性的继承","children":[]},{"level":3,"title":"属性的层叠","slug":"属性的层叠","link":"#属性的层叠","children":[]},{"level":3,"title":"HTML元素的类型","slug":"html元素的类型","link":"#html元素的类型","children":[]}]},{"level":2,"title":"CSS技巧","slug":"css技巧","link":"#css技巧","children":[{"level":3,"title":"元素隐藏方法","slug":"元素隐藏方法","link":"#元素隐藏方法","children":[]},{"level":3,"title":"样式不生效","slug":"样式不生效","link":"#样式不生效","children":[]}]},{"level":2,"title":"CSS盒子模型","slug":"css盒子模型","link":"#css盒子模型","children":[{"level":3,"title":"内容 width / height","slug":"内容-width-height","link":"#内容-width-height","children":[]},{"level":3,"title":"内边距 padding","slug":"内边距-padding","link":"#内边距-padding","children":[]},{"level":3,"title":"边框 border","slug":"边框-border","link":"#边框-border","children":[]},{"level":3,"title":"外边距 margin","slug":"外边距-margin","link":"#外边距-margin","children":[]},{"level":3,"title":"额外知识点","slug":"额外知识点","link":"#额外知识点","children":[]},{"level":3,"title":"外轮廓 outline","slug":"外轮廓-outline","link":"#外轮廓-outline","children":[]},{"level":3,"title":"盒子阴影 box-shadow","slug":"盒子阴影-box-shadow","link":"#盒子阴影-box-shadow","children":[]},{"level":3,"title":"行内非替换元素的注意事项","slug":"行内非替换元素的注意事项","link":"#行内非替换元素的注意事项","children":[]}]},{"level":2,"title":"CSS元素定位","slug":"css元素定位","link":"#css元素定位","children":[{"level":3,"title":"标准流","slug":"标准流","link":"#标准流","children":[]},{"level":3,"title":"认识元素的定位","slug":"认识元素的定位","link":"#认识元素的定位","children":[]},{"level":3,"title":"position属性取值","slug":"position属性取值","link":"#position属性取值","children":[]},{"level":3,"title":"绝对定位元素的特点","slug":"绝对定位元素的特点","link":"#绝对定位元素的特点","children":[]},{"level":3,"title":"z-index解析","slug":"z-index解析","link":"#z-index解析","children":[]}]},{"level":2,"title":"浮动布局","slug":"浮动布局","link":"#浮动布局","children":[{"level":3,"title":"认识浮动布局","slug":"认识浮动布局","link":"#认识浮动布局","children":[]},{"level":3,"title":"浮动案例","slug":"浮动案例","link":"#浮动案例","children":[]},{"level":3,"title":"浮动规则","slug":"浮动规则","link":"#浮动规则","children":[]},{"level":3,"title":"通过清除浮动实现布局(TODO)","slug":"通过清除浮动实现布局-todo","link":"#通过清除浮动实现布局-todo","children":[]}]},{"level":2,"title":"Flex布局","slug":"flex布局","link":"#flex布局","children":[{"level":3,"title":"认识Flex布局","slug":"认识flex布局","link":"#认识flex布局","children":[]},{"level":3,"title":"flex布局的重要概念","slug":"flex布局的重要概念","link":"#flex布局的重要概念","children":[]},{"level":3,"title":"flex相关的属性","slug":"flex相关的属性","link":"#flex相关的属性","children":[]},{"level":3,"title":"案例:解决布局问题","slug":"案例-解决布局问题","link":"#案例-解决布局问题","children":[]}]},{"level":2,"title":"CSS中的函数","slug":"css中的函数","link":"#css中的函数","children":[{"level":3,"title":"var  变量","slug":"var-变量","link":"#var-变量","children":[]},{"level":3,"title":"calc 计算","slug":"calc-计算","link":"#calc-计算","children":[]},{"level":3,"title":"blur 高斯模糊","slug":"blur-高斯模糊","link":"#blur-高斯模糊","children":[]},{"level":3,"title":"gradient 颜色渐变","slug":"gradient-颜色渐变","link":"#gradient-颜色渐变","children":[]}]},{"level":2,"title":"CSS求值过程","slug":"css求值过程","link":"#css求值过程","children":[]},{"level":2,"title":"移动端开发","slug":"移动端开发","link":"#移动端开发","children":[]},{"level":2,"title":"额外知识补充","slug":"额外知识补充","link":"#额外知识补充","children":[{"level":3,"title":"浏览器前缀","slug":"浏览器前缀","link":"#浏览器前缀","children":[]},{"level":3,"title":"深入理解BFC(重点)","slug":"深入理解bfc-重点","link":"#深入理解bfc-重点","children":[]},{"level":3,"title":"媒体查询","slug":"媒体查询","link":"#媒体查询","children":[]},{"level":3,"title":"link元素的使用","slug":"link元素的使用","link":"#link元素的使用","children":[]},{"level":3,"title":"CSS颜色的表示方式","slug":"css颜色的表示方式","link":"#css颜色的表示方式","children":[]},{"level":3,"title":"网络字体","slug":"网络字体","link":"#网络字体","children":[]},{"level":3,"title":"字体图标","slug":"字体图标","link":"#字体图标","children":[]},{"level":3,"title":"精灵图 雪碧图","slug":"精灵图-雪碧图","link":"#精灵图-雪碧图","children":[]},{"level":3,"title":"white-space","slug":"white-space","link":"#white-space","children":[]},{"level":3,"title":"text-overflow","slug":"text-overflow","link":"#text-overflow","children":[]},{"level":3,"title":"水平垂直居中方案","slug":"水平垂直居中方案","link":"#水平垂直居中方案","children":[]},{"level":3,"title":"内联元素居中布局","slug":"内联元素居中布局","link":"#内联元素居中布局","children":[]},{"level":3,"title":"块级元素居中布局","slug":"块级元素居中布局","link":"#块级元素居中布局","children":[]}]},{"level":2,"title":"HTML5新增内容","slug":"html5新增内容","link":"#html5新增内容","children":[{"level":3,"title":"语义化元素","slug":"语义化元素","link":"#语义化元素","children":[]},{"level":3,"title":"video标签","slug":"video标签","link":"#video标签","children":[]},{"level":3,"title":"audio标签","slug":"audio标签","link":"#audio标签","children":[]},{"level":3,"title":"input元素","slug":"input元素","link":"#input元素","children":[]},{"level":3,"title":"全局新增属性 data-*","slug":"全局新增属性-data","link":"#全局新增属性-data","children":[]}]}],"relativePath":"note/CSS.md","lastUpdated":1676979063000}'),t={name:"note/CSS.md"},r=l("",533),i=[r];function d(D,y,F,C,u,b){return n(),a("div",null,i)}const m=s(t,[["render",d]]);export{A as __pageData,m as default};
diff --git a/assets/note_Front-end Engineering.md.e321faed.js b/assets/note_Front-end Engineering.md.939c2eef.js
similarity index 98%
rename from assets/note_Front-end Engineering.md.e321faed.js
rename to assets/note_Front-end Engineering.md.939c2eef.js
index 3ffdb18d..8b525d73 100644
--- a/assets/note_Front-end Engineering.md.e321faed.js	
+++ b/assets/note_Front-end Engineering.md.939c2eef.js	
@@ -1,4 +1,4 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const F=JSON.parse('{"title":"前端工程化","description":"","frontmatter":{},"headers":[{"level":2,"title":"Node.js","slug":"node-js","link":"#node-js","children":[{"level":3,"title":"什么是Node.js","slug":"什么是node-js","link":"#什么是node-js","children":[]},{"level":3,"title":"Node.js的应用场景","slug":"node-js的应用场景","link":"#node-js的应用场景","children":[]},{"level":3,"title":"Node.js的参数传递","slug":"node-js的参数传递","link":"#node-js的参数传递","children":[]},{"level":3,"title":"Node中的全局对象","slug":"node中的全局对象","link":"#node中的全局对象","children":[]}]},{"level":2,"title":"模块化开发","slug":"模块化开发","link":"#模块化开发","children":[{"level":3,"title":"模块化的初衷","slug":"模块化的初衷","link":"#模块化的初衷","children":[]},{"level":3,"title":"CommonJS","slug":"commonjs","link":"#commonjs","children":[]},{"level":3,"title":"ESModule","slug":"esmodule","link":"#esmodule","children":[]},{"level":3,"title":"深入理解模块加载","slug":"深入理解模块加载","link":"#深入理解模块加载","children":[]},{"level":3,"title":"拓展内容","slug":"拓展内容","link":"#拓展内容","children":[]}]},{"level":2,"title":"包管理工具","slug":"包管理工具","link":"#包管理工具","children":[{"level":3,"title":"npm","slug":"npm","link":"#npm","children":[]},{"level":3,"title":"package.json","slug":"package-json","link":"#package-json","children":[]},{"level":3,"title":"npx","slug":"npx","link":"#npx","children":[]},{"level":3,"title":"npm包的发布","slug":"npm包的发布","link":"#npm包的发布","children":[]},{"level":3,"title":"npm包的开发调试","slug":"npm包的开发调试","link":"#npm包的开发调试","children":[]},{"level":3,"title":"PNPM","slug":"pnpm","link":"#pnpm","children":[]}]},{"level":2,"title":"系统学习Webpack","slug":"系统学习webpack","link":"#系统学习webpack","children":[{"level":3,"title":"Node内置模块 path","slug":"node内置模块-path","link":"#node内置模块-path","children":[]},{"level":3,"title":"初识Webpack","slug":"初识webpack","link":"#初识webpack","children":[]}]}],"relativePath":"note/Front-end Engineering.md","lastUpdated":1676737739000}'),e={name:"note/Front-end Engineering.md"},o=l(`

前端工程化

Node.js

  • 什么是Node.JS Node的应用场景
  • JS代码执行
  • Node的输入和输出
  • Node的全局对象

什么是Node.js

Node.js是一个基于V8 JavaScript引擎JavaScript运行时环境

  • V8可以嵌入到任何C++应用程序中,无论是Chrome还是Node.js,事实上都嵌入了V8引擎来执行JavaScript代码
  • 在Chrome浏览器中,还需要解析、渲染HTML、CSS等相关渲染引擎,另外还需要支持浏览器操作的API、浏览器自己的事件循环
  • 在Node.js中我们也需要进行一些额外操作:文件系统读写、网络IO、加密、压缩解压文件等

可以简单总结出Node.js和浏览器的区别

  • Chrome浏览器

    • Blink负责解析HTML文档,遇到JavaScript标签时将内容交给V8引擎

    • Blink 是 Google Chrome 浏览器的渲染引擎,V8 是 Blink 内置的 JavaScript 引擎

      • 预分析:检查语法错误但不生成AST树
      • 生成AST:语法分析、词法分析后,生成抽象语法树(AST)
        • AST 为每一行代码定义键值对。初始类型标识符定义 AST 属于一个程序,然后所有代码行将定义在主体内部,主体是一个对象数组。
      • 生成字节码:基线编译器(Ignition)将 AST 转换为字节码
      • 生成机器代码:优化编译器 (Turbofan) 将字节码转换为优化的机器代码。另外,在逐行执行字节码的过程中,如果一段代码经常被执行,V8会直接将这段代码转换并保存为机器码,下次执行不需要经过字节码,优化了执行速度
  • Node.js

    • 只处理JavaScript代码 内部V8引擎负责JS代码的执行
    • JavaScript代码 -> V8 -> Node.js Bindings -> LibUV
    • LibUV是使用C语言编写的库,提供了事件循环、文件系统读写、网络IO、线程池等等内容

![The Node.js System](Front-end Engineering.assets/The Node.js System.jpeg)

Node.js的应用场景

  • 前端开发的库都是以node包形式管理的
  • npm yarn pnpm成为前端开发使用最多的工具
  • 使用Node.js作为Web服务器开发、中间件、代理服务器
  • 借助Node.js完成前后端渲染的同构应用
  • 编写脚本工具 构建项目 打包代码等
  • Electron桌面应用程序

Node.js的参数传递

process.argv

process.argv返回一个数组

  • 在代码中通过process.argv[2]读取来自命令行的额外参数
  • process.argv[0] process.argv[1]分别为node.exe的绝对路径和目标文件的绝对路径
js
// sum.js
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const F=JSON.parse('{"title":"前端工程化","description":"","frontmatter":{},"headers":[{"level":2,"title":"Node.js","slug":"node-js","link":"#node-js","children":[{"level":3,"title":"什么是Node.js","slug":"什么是node-js","link":"#什么是node-js","children":[]},{"level":3,"title":"Node.js的应用场景","slug":"node-js的应用场景","link":"#node-js的应用场景","children":[]},{"level":3,"title":"Node.js的参数传递","slug":"node-js的参数传递","link":"#node-js的参数传递","children":[]},{"level":3,"title":"Node中的全局对象","slug":"node中的全局对象","link":"#node中的全局对象","children":[]}]},{"level":2,"title":"模块化开发","slug":"模块化开发","link":"#模块化开发","children":[{"level":3,"title":"模块化的初衷","slug":"模块化的初衷","link":"#模块化的初衷","children":[]},{"level":3,"title":"CommonJS","slug":"commonjs","link":"#commonjs","children":[]},{"level":3,"title":"ESModule","slug":"esmodule","link":"#esmodule","children":[]},{"level":3,"title":"深入理解模块加载","slug":"深入理解模块加载","link":"#深入理解模块加载","children":[]},{"level":3,"title":"拓展内容","slug":"拓展内容","link":"#拓展内容","children":[]}]},{"level":2,"title":"包管理工具","slug":"包管理工具","link":"#包管理工具","children":[{"level":3,"title":"npm","slug":"npm","link":"#npm","children":[]},{"level":3,"title":"package.json","slug":"package-json","link":"#package-json","children":[]},{"level":3,"title":"npx","slug":"npx","link":"#npx","children":[]},{"level":3,"title":"npm包的发布","slug":"npm包的发布","link":"#npm包的发布","children":[]},{"level":3,"title":"npm包的开发调试","slug":"npm包的开发调试","link":"#npm包的开发调试","children":[]},{"level":3,"title":"PNPM","slug":"pnpm","link":"#pnpm","children":[]}]},{"level":2,"title":"系统学习Webpack","slug":"系统学习webpack","link":"#系统学习webpack","children":[{"level":3,"title":"Node内置模块 path","slug":"node内置模块-path","link":"#node内置模块-path","children":[]},{"level":3,"title":"初识Webpack","slug":"初识webpack","link":"#初识webpack","children":[]}]}],"relativePath":"note/Front-end Engineering.md","lastUpdated":1676979063000}'),e={name:"note/Front-end Engineering.md"},o=l(`

前端工程化

Node.js

  • 什么是Node.JS Node的应用场景
  • JS代码执行
  • Node的输入和输出
  • Node的全局对象

什么是Node.js

Node.js是一个基于V8 JavaScript引擎JavaScript运行时环境

  • V8可以嵌入到任何C++应用程序中,无论是Chrome还是Node.js,事实上都嵌入了V8引擎来执行JavaScript代码
  • 在Chrome浏览器中,还需要解析、渲染HTML、CSS等相关渲染引擎,另外还需要支持浏览器操作的API、浏览器自己的事件循环
  • 在Node.js中我们也需要进行一些额外操作:文件系统读写、网络IO、加密、压缩解压文件等

可以简单总结出Node.js和浏览器的区别

  • Chrome浏览器

    • Blink负责解析HTML文档,遇到JavaScript标签时将内容交给V8引擎

    • Blink 是 Google Chrome 浏览器的渲染引擎,V8 是 Blink 内置的 JavaScript 引擎

      • 预分析:检查语法错误但不生成AST树
      • 生成AST:语法分析、词法分析后,生成抽象语法树(AST)
        • AST 为每一行代码定义键值对。初始类型标识符定义 AST 属于一个程序,然后所有代码行将定义在主体内部,主体是一个对象数组。
      • 生成字节码:基线编译器(Ignition)将 AST 转换为字节码
      • 生成机器代码:优化编译器 (Turbofan) 将字节码转换为优化的机器代码。另外,在逐行执行字节码的过程中,如果一段代码经常被执行,V8会直接将这段代码转换并保存为机器码,下次执行不需要经过字节码,优化了执行速度
  • Node.js

    • 只处理JavaScript代码 内部V8引擎负责JS代码的执行
    • JavaScript代码 -> V8 -> Node.js Bindings -> LibUV
    • LibUV是使用C语言编写的库,提供了事件循环、文件系统读写、网络IO、线程池等等内容

![The Node.js System](Front-end Engineering.assets/The Node.js System.jpeg)

Node.js的应用场景

  • 前端开发的库都是以node包形式管理的
  • npm yarn pnpm成为前端开发使用最多的工具
  • 使用Node.js作为Web服务器开发、中间件、代理服务器
  • 借助Node.js完成前后端渲染的同构应用
  • 编写脚本工具 构建项目 打包代码等
  • Electron桌面应用程序

Node.js的参数传递

process.argv

process.argv返回一个数组

  • 在代码中通过process.argv[2]读取来自命令行的额外参数
  • process.argv[0] process.argv[1]分别为node.exe的绝对路径和目标文件的绝对路径
js
// sum.js
 const x = process.argv[2]
 const y = process.argv[3]
 console.log(x + y)
@@ -51,7 +51,7 @@ import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const F=JSON.parse('{
 
 // moduleB.js
 console.log(moduleA.name) // 在其他模块中调用
-

CommonJS

CommonJS是一种规范,当初命名为ServerJS,旨在浏览器以外的地方使用,后为体现其广泛性,改名为CommonJS,简称CJS

规范 是用来指导 实现的

  • Node 是CommonJS在服务端的代表实现
  • Browserify 是CommonJS在浏览器中的一种实现 (正在被淘汰)
  • WebPack 打包工具具备支持CommonJS的支持和转换

所以,Node.js对CommonJS进行了支持和实现,让JavaScript在Node上运行时可以实现模块化开发

  • 每个.js文件都是一个单独的模块
  • 每个模块中都包含变量exports module.exports require
js
// env.js
+

CommonJS

CommonJS是一种规范,当初命名为ServerJS,旨在浏览器以外的地方使用,后为体现其广泛性,改名为CommonJS,简称CJS

规范 是用来指导 实现的

  • Node 是CommonJS在服务端的代表实现
  • Browserify 是CommonJS在浏览器中的一种实现 (正在被淘汰)
  • WebPack 打包工具具备支持CommonJS的支持和转换

所以,Node.js对CommonJS进行了支持和实现,让JavaScript在Node上运行时可以实现模块化开发

  • 每个.js文件都是一个单独的模块
  • 每个模块中都包含变量exports module.exports require
js
// env.js
 exports.name = 'Ziu'
 exports.age = 18
 
js
// utils.js
@@ -69,7 +69,7 @@ import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const F=JSON.parse('{
 
 const { name, age } = require('env.js')
 console.log(name, age) // Ziu 18
-

exports的本质

exportsrequire在Node中的本质

  • exports是一个对象,我们可以在这个对象中添加很多属性,添加的属性则会被导出
    • 在没有向该对象添加任何属性之前,它是一个空对象
  • 当通过require导入时:const env = require('env.js')
    • env这个变量等于env.js中的exports对象
    • 本质上是envexports对象的引用赋值
    • { id: '...', exports: { ... }, loaded: true, ... }
  • 后续即使再次执行require导入模块,模块中的代码也不会重新执行(module.loaded属性)
    • 当从模块中取值时,会从已经加载的exports对象缓存上取值
js
// utils.js
+

exports的本质

exportsrequire在Node中的本质

  • exports是一个对象,我们可以在这个对象中添加很多属性,添加的属性则会被导出
    • 在没有向该对象添加任何属性之前,它是一个空对象
  • 当通过require导入时:const env = require('env.js')
    • env这个变量等于env.js中的exports对象
    • 本质上是envexports对象的引用赋值
    • { id: '...', exports: { ... }, loaded: true, ... }
  • 后续即使再次执行require导入模块,模块中的代码也不会重新执行(module.loaded属性)
    • 当从模块中取值时,会从已经加载的exports对象缓存上取值
js
// utils.js
 exports.a = 0
 
 // 1s后修改a值
@@ -97,7 +97,7 @@ import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const F=JSON.parse('{
   name,
   run
 }
-

二者的区别

既然如此,为什么还要存在exports这个概念呢?

  • 在CommonJS中是没有module.exports的概念的
  • 为了实现模块的导出,Node.js使用的是Module类,每一个模块都是Module的实例,也就是module
  • 所以在Node.js中真正用于导出的并不是exports,而是module.exports
  • module对象中的exports属性是exports对象的一个引用
    • module.exports === exports === utils

如果module.exports不再引用exports对象了,修改exports对象也就没有意义了

js
// utils.js
+

二者的区别

既然如此,为什么还要存在exports这个概念呢?

  • 在CommonJS中是没有module.exports的概念的
  • 为了实现模块的导出,Node.js使用的是Module类,每一个模块都是Module的实例,也就是module
  • 所以在Node.js中真正用于导出的并不是exports,而是module.exports
  • module对象中的exports属性是exports对象的一个引用
    • module.exports === exports === utils

如果module.exports不再引用exports对象了,修改exports对象也就没有意义了

js
// utils.js
 module.exports = {
   name: 'Ziu'
 }
@@ -106,7 +106,7 @@ import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const F=JSON.parse('{
 const utils = require('utils.js')
 console.log(utils.name) // Ziu
 console.log(utils.age) // undefined
-

当使用module.exports = { ... }后,模块中原有的exports不再被导入识别,导入的内容将变为module.exports指定的对象内容

require的本质

require是一个函数,可以帮助我们导入一个文件(模块)中导出的对象

  • 为什么可以省略掉.js后缀,直接使用require('./utils')
  • 为什么可以省略掉index.js,直接使用require('./tools')导入tools/index.js

这涉及到require在匹配路径后的查找规则:

分为三种情况:内置模块、自定义路径、包名

  • 导入Node.js内置的模块,如const path = require('path')
    • 直接返回该内置模块 并停止后续的查找
  • 根据路径导入自定义的模块,如const utils = require('./{filename}')
    • 按照路径寻找该模块./ ../ /
    • 如果指定了后缀名,则按照后缀名查找
    • 如果未指定后缀名,则:
      1. 直接查找该文件
      2. 查找{filename}.js文件
      3. 查找{filename}.json文件
      4. 查找{filename}.node文件
    • 如果按照上述方式没找到文件,则{filename}作为路径继续查找
    • 查找目录下的index文件 {filename}/index
      1. 查找{filename}/index.js文件
      2. ··· ···
    • 没找到:报错Cannot find module 'xxx'
  • 包名,如const lodash = require('lodash')
    • 到项目根目录的node_modules中查找
    • node_modules/{package_name}/index.js
    • 当前项目目录的node_modules找不到则继续向上查找,直到查找到根目录的node_modules

模块的加载过程

  • 模块在被第一次引入时,模块中的JS代码会被运行一次
    • 代码执行顺序与require的位置相关
  • 模块如果被多次引入,会被缓存,最终只加载一次
    • 这是因为每个模块对象module上都有一个属性loaded
    • loaded === false表示该模块尚未被加载
    • 第二次被require引入时会检查该属性是否为true
  • 如果有循环引用,加载顺序如何?
    • 数据结构:图结构(graph)遍历时有深度优先搜索(DFS)、广度优先搜索(BFS)两种算法
    • Node采用的是深度优先算法

CommonJS的缺点

  • 加载模块是同步加载的
    • 只有等到对应的模块加载完毕,当前模块中的内容才能被执行
    • 当然,在服务器中加载JS文件都是本地文件,加载速度非常快,不会受影响
  • 但是在浏览器中使用CommonJS
    • 需要先从服务器下载JS文件,后加载运行
    • 阻塞JS执行 阻塞页面加载
  • 在WebPack中使用CommonJS
    • CommonJS会被WebPack解析
    • 将CommonJS代码转化为bundle 浏览器可以直接运行

ESModule

  • ES6 模块采用编译时加载,使得编译时就能确定模块的依赖关系,有助于静态优化
  • CommonJS模块在运行时加载,且必须借助对象加载模块内容

exportimport用法概览

ESModule借助exportimport导入导出内容,需要注意的是导入导出的并不是对象

export定义的是当前模块导出的接口import可以导入来自其他不同模块的接口

  • export default可以设置默认导出对象
  • export { ... }可以统一导出多个内容
  • exportimport都可以使用as关键字重命名导出/导入的接口
  • import * from 'xxx' export * from 'xxx'批量导入/导出
js
// utils.js
+

当使用module.exports = { ... }后,模块中原有的exports不再被导入识别,导入的内容将变为module.exports指定的对象内容

require的本质

require是一个函数,可以帮助我们导入一个文件(模块)中导出的对象

  • 为什么可以省略掉.js后缀,直接使用require('./utils')
  • 为什么可以省略掉index.js,直接使用require('./tools')导入tools/index.js

这涉及到require在匹配路径后的查找规则:

分为三种情况:内置模块、自定义路径、包名

  • 导入Node.js内置的模块,如const path = require('path')
    • 直接返回该内置模块 并停止后续的查找
  • 根据路径导入自定义的模块,如const utils = require('./{filename}')
    • 按照路径寻找该模块./ ../ /
    • 如果指定了后缀名,则按照后缀名查找
    • 如果未指定后缀名,则:
      1. 直接查找该文件
      2. 查找{filename}.js文件
      3. 查找{filename}.json文件
      4. 查找{filename}.node文件
    • 如果按照上述方式没找到文件,则{filename}作为路径继续查找
    • 查找目录下的index文件 {filename}/index
      1. 查找{filename}/index.js文件
      2. ··· ···
    • 没找到:报错Cannot find module 'xxx'
  • 包名,如const lodash = require('lodash')
    • 到项目根目录的node_modules中查找
    • node_modules/{package_name}/index.js
    • 当前项目目录的node_modules找不到则继续向上查找,直到查找到根目录的node_modules

模块的加载过程

  • 模块在被第一次引入时,模块中的JS代码会被运行一次
    • 代码执行顺序与require的位置相关
  • 模块如果被多次引入,会被缓存,最终只加载一次
    • 这是因为每个模块对象module上都有一个属性loaded
    • loaded === false表示该模块尚未被加载
    • 第二次被require引入时会检查该属性是否为true
  • 如果有循环引用,加载顺序如何?
    • 数据结构:图结构(graph)遍历时有深度优先搜索(DFS)、广度优先搜索(BFS)两种算法
    • Node采用的是深度优先算法

CommonJS的缺点

  • 加载模块是同步加载的
    • 只有等到对应的模块加载完毕,当前模块中的内容才能被执行
    • 当然,在服务器中加载JS文件都是本地文件,加载速度非常快,不会受影响
  • 但是在浏览器中使用CommonJS
    • 需要先从服务器下载JS文件,后加载运行
    • 阻塞JS执行 阻塞页面加载
  • 在WebPack中使用CommonJS
    • CommonJS会被WebPack解析
    • 将CommonJS代码转化为bundle 浏览器可以直接运行

ESModule

  • ES6 模块采用编译时加载,使得编译时就能确定模块的依赖关系,有助于静态优化
  • CommonJS模块在运行时加载,且必须借助对象加载模块内容

exportimport用法概览

ESModule借助exportimport导入导出内容,需要注意的是导入导出的并不是对象

export定义的是当前模块导出的接口import可以导入来自其他不同模块的接口

  • export default可以设置默认导出对象
  • export { ... }可以统一导出多个内容
  • exportimport都可以使用as关键字重命名导出/导入的接口
  • import * from 'xxx' export * from 'xxx'批量导入/导出
js
// utils.js
 export function sum(a, b) {
   return a + b
 }
@@ -128,7 +128,7 @@ import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const F=JSON.parse('{
 sum(1, 2) // 3
 sub(2, 3) // -1
 log(name, age, ENV_VARIABLE) // 'Ziu' 18 'Hello, World!'
-

需要注意的是,在浏览器中要使用ESModule,需要为<script>标签添加module标记:

<script src="index.js" type="module"></script>

  • 当浏览器解析到type="module"的JS代码后,会分析模块中导入的ESModule模块
  • 每导入一个ESModule模块,浏览器都会发起一个HTTP请求去加载它
  • 在本地运行时加载不同协议头的文件会遇到跨域问题,需要开启本地Web服务器

另外,exportimport必须位于模块的顶层,如果位于作用域内会报错,因为这就无法对代码进行静态分析优化了

export详解

export有两种导出方式:

  • 命名导出 export const name = 'Ziu' export { v1, v2 } export * from 'xxx'
    • 导出时需要指定名字
    • 导入时也需要知道对应的名字
  • 默认导出 export default AGE = 18
    • 在从其他位置导入时需要为此默认导出指定新的名字
    • 给用户方便:不必阅读文档就可以加载模块

值的动态绑定

  • ESModule模块通过export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值
  • CommonJS模块输出的是值的缓存,不存在动态更新

我们援引之前介绍CJS时的案例,将后缀名改为mjs即可在Node中运行ESModule模块代码

初始获得的a值为0,经过1s后,在utils.mjs中修改了a的值,这时导入utils.mjs模块的其他模块可以获取到a最新的值

js
// utils.mjs
+

需要注意的是,在浏览器中要使用ESModule,需要为<script>标签添加module标记:

<script src="index.js" type="module"></script>

  • 当浏览器解析到type="module"的JS代码后,会分析模块中导入的ESModule模块
  • 每导入一个ESModule模块,浏览器都会发起一个HTTP请求去加载它
  • 在本地运行时加载不同协议头的文件会遇到跨域问题,需要开启本地Web服务器

另外,exportimport必须位于模块的顶层,如果位于作用域内会报错,因为这就无法对代码进行静态分析优化了

export详解

export有两种导出方式:

  • 命名导出 export const name = 'Ziu' export { v1, v2 } export * from 'xxx'
    • 导出时需要指定名字
    • 导入时也需要知道对应的名字
  • 默认导出 export default AGE = 18
    • 在从其他位置导入时需要为此默认导出指定新的名字
    • 给用户方便:不必阅读文档就可以加载模块

值的动态绑定

  • ESModule模块通过export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值
  • CommonJS模块输出的是值的缓存,不存在动态更新

我们援引之前介绍CJS时的案例,将后缀名改为mjs即可在Node中运行ESModule模块代码

初始获得的a值为0,经过1s后,在utils.mjs中修改了a的值,这时导入utils.mjs模块的其他模块可以获取到a最新的值

js
// utils.mjs
 export let a = 0
 
 // 1s后修改a值
@@ -175,7 +175,7 @@ import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const F=JSON.parse('{
 }
 

传入动态值

js
let moduleName = () => ['Home', 'History', 'User'][0]
 import(\`./\${moduleName()}.js\`)
-

import.meta

ES2020引入了import.meta,它仅能在模块内部使用,包含一些模块自身的信息,即模块元信息

  • import.meta.url 返回当前模块的URL路径
    • 浏览器加载ESModule都是通过HTTP发起请求
      • 例如当前模块为fetchData.js,要在模块内引入一个名为data.json的数据:
      • import( new URL('data.json', import.meta.url) )
    • Node.js环境下,该值都是file://协议的链接
  • import.meta.scriptElement
    • 浏览器特有的属性
    • 返回加载模块的<script>标签,相当于document.currentScript

规范中并未规定import.meta中包含哪些属性,一般包括上面两个属性

深入理解模块加载

ESModule的解析过程

ESModule的解析过程可以分为三个阶段:

  • 构建 Construction
    • 根据地址查找JS文件,并发起HTTP请求下载,将其解析为模块记录 Module Record
  • 实例化 Instatiation
    • 对模块记录进行实例化,并为其分配内存空间
    • 解析ESModule模块的导入和导出语句,将模块指向对应的内存地址
    • 例如export const name = 'Ziu',会将变量name添加到模块环境记录中 Module Enviroment Record
  • 运行 Evaluation
    • 运行代码,计算值,并且将值填充到内存地址中
    • 将导入导出的赋给对应的变量name = 'Ziu'

![ESModule解析过程](Front-end Engineering.assets/esmodule-phases.png)

文章推荐:ES modules: A cartoon deep-dive

MJS和CJS的区别

  • CommonJS模块输出的是值的拷贝,而ESModule模块输出的是值的引用
    • CJS导出的变量,其值如果在模块内发生变化,外部导入是不会同步更新的,除非导出的是一个取值函数
    • MJS导出变量,外部模块每次访问时都会得到该变量最新的值,即使变量在模块内被修改了
  • CommonJS模块是运行时加载,而ESModule是编译时输出接口
    • CJS是通过对象实现的导入导出,它在运行时才被确定依赖关系和其值
    • MJS则是通过静态定义,在代码运行之前的静态解析阶段即可确定模块的导入导出内容
  • CommonJS模块的require()是同步加载模块,而ESModule模块的import命令是异步加载模块
    • import命令拥有一个独立的模块依赖的解析阶段

CJS中的循环加载

设想有以下两文件 a.jsb.js

js
// a.js
+

import.meta

ES2020引入了import.meta,它仅能在模块内部使用,包含一些模块自身的信息,即模块元信息

  • import.meta.url 返回当前模块的URL路径
    • 浏览器加载ESModule都是通过HTTP发起请求
      • 例如当前模块为fetchData.js,要在模块内引入一个名为data.json的数据:
      • import( new URL('data.json', import.meta.url) )
    • Node.js环境下,该值都是file://协议的链接
  • import.meta.scriptElement
    • 浏览器特有的属性
    • 返回加载模块的<script>标签,相当于document.currentScript

规范中并未规定import.meta中包含哪些属性,一般包括上面两个属性

深入理解模块加载

ESModule的解析过程

ESModule的解析过程可以分为三个阶段:

  • 构建 Construction
    • 根据地址查找JS文件,并发起HTTP请求下载,将其解析为模块记录 Module Record
  • 实例化 Instatiation
    • 对模块记录进行实例化,并为其分配内存空间
    • 解析ESModule模块的导入和导出语句,将模块指向对应的内存地址
    • 例如export const name = 'Ziu',会将变量name添加到模块环境记录中 Module Enviroment Record
  • 运行 Evaluation
    • 运行代码,计算值,并且将值填充到内存地址中
    • 将导入导出的赋给对应的变量name = 'Ziu'

![ESModule解析过程](Front-end Engineering.assets/esmodule-phases.png)

文章推荐:ES modules: A cartoon deep-dive

MJS和CJS的区别

  • CommonJS模块输出的是值的拷贝,而ESModule模块输出的是值的引用
    • CJS导出的变量,其值如果在模块内发生变化,外部导入是不会同步更新的,除非导出的是一个取值函数
    • MJS导出变量,外部模块每次访问时都会得到该变量最新的值,即使变量在模块内被修改了
  • CommonJS模块是运行时加载,而ESModule是编译时输出接口
    • CJS是通过对象实现的导入导出,它在运行时才被确定依赖关系和其值
    • MJS则是通过静态定义,在代码运行之前的静态解析阶段即可确定模块的导入导出内容
  • CommonJS模块的require()是同步加载模块,而ESModule模块的import命令是异步加载模块
    • import命令拥有一个独立的模块依赖的解析阶段

CJS中的循环加载

设想有以下两文件 a.jsb.js

js
// a.js
 exports.done = false
 const b = require('./b.js')
 console.log('在 a.js 之中,b.done = %j', b.done)
@@ -196,7 +196,7 @@ import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const F=JSON.parse('{
  a.js 之中,b.done = true
 a.js 执行完毕
  main.js 之中, a.done=true, b.done=true
-

总结:

  • CJS的模块导出是输出值的拷贝,而不是引用,值的变化不是动态的,而是会被缓存的
  • 循环加载时,CJS模块导出的值是当前已经执行部分代码产生的结果的值,而不是模块代码完全执行完后的最终值

MJS中的循环加载

ESModule的导入和导出与CommonJS有本质不同:

js
// a.mjs
+

总结:

  • CJS的模块导出是输出值的拷贝,而不是引用,值的变化不是动态的,而是会被缓存的
  • 循环加载时,CJS模块导出的值是当前已经执行部分代码产生的结果的值,而不是模块代码完全执行完后的最终值

MJS中的循环加载

ESModule的导入和导出与CommonJS有本质不同:

js
// a.mjs
 import { bar } from './b.mjs'
 console.log('a.mjs')
 console.log(bar)
@@ -206,7 +206,7 @@ import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const F=JSON.parse('{
 console.log('b.mjs')
 console.log(foo)
 export let bar = 'bar'
-

执行a.mjs后发现报错了:ReferenceError: Cannot access 'foo' before initialization,变量foo未定义

  • MJS模块在代码执行前会进行静态分析
  • 分析a.mjs的依赖关系时,发现其依赖了b.mjs
  • 于是加载b.mjs并解析它的依赖关系
  • 解析b.mjs的过程中,发现它又依赖了a.mjs
  • 这时引擎不会再去加载a.mjs 而是认为a.mjs这个模块的Module Record已经存在了
  • 继续向下执行,执行到console.log(foo)时发现foo未定义 抛出错误

要实现预期效果,可以将foobar改写为取值函数,这时执行就不会报错了:

js
// a.mjs
+

执行a.mjs后发现报错了:ReferenceError: Cannot access 'foo' before initialization,变量foo未定义

  • MJS模块在代码执行前会进行静态分析
  • 分析a.mjs的依赖关系时,发现其依赖了b.mjs
  • 于是加载b.mjs并解析它的依赖关系
  • 解析b.mjs的过程中,发现它又依赖了a.mjs
  • 这时引擎不会再去加载a.mjs 而是认为a.mjs这个模块的Module Record已经存在了
  • 继续向下执行,执行到console.log(foo)时发现foo未定义 抛出错误

要实现预期效果,可以将foobar改写为取值函数,这时执行就不会报错了:

js
// a.mjs
 import { bar } from './b.mjs'
 console.log('a.mjs')
 console.log(bar())
diff --git a/assets/note_Front-end Engineering.md.e321faed.lean.js b/assets/note_Front-end Engineering.md.939c2eef.lean.js
similarity index 97%
rename from assets/note_Front-end Engineering.md.e321faed.lean.js
rename to assets/note_Front-end Engineering.md.939c2eef.lean.js
index 629a81b0..e6638e2b 100644
--- a/assets/note_Front-end Engineering.md.e321faed.lean.js	
+++ b/assets/note_Front-end Engineering.md.939c2eef.lean.js	
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const F=JSON.parse('{"title":"前端工程化","description":"","frontmatter":{},"headers":[{"level":2,"title":"Node.js","slug":"node-js","link":"#node-js","children":[{"level":3,"title":"什么是Node.js","slug":"什么是node-js","link":"#什么是node-js","children":[]},{"level":3,"title":"Node.js的应用场景","slug":"node-js的应用场景","link":"#node-js的应用场景","children":[]},{"level":3,"title":"Node.js的参数传递","slug":"node-js的参数传递","link":"#node-js的参数传递","children":[]},{"level":3,"title":"Node中的全局对象","slug":"node中的全局对象","link":"#node中的全局对象","children":[]}]},{"level":2,"title":"模块化开发","slug":"模块化开发","link":"#模块化开发","children":[{"level":3,"title":"模块化的初衷","slug":"模块化的初衷","link":"#模块化的初衷","children":[]},{"level":3,"title":"CommonJS","slug":"commonjs","link":"#commonjs","children":[]},{"level":3,"title":"ESModule","slug":"esmodule","link":"#esmodule","children":[]},{"level":3,"title":"深入理解模块加载","slug":"深入理解模块加载","link":"#深入理解模块加载","children":[]},{"level":3,"title":"拓展内容","slug":"拓展内容","link":"#拓展内容","children":[]}]},{"level":2,"title":"包管理工具","slug":"包管理工具","link":"#包管理工具","children":[{"level":3,"title":"npm","slug":"npm","link":"#npm","children":[]},{"level":3,"title":"package.json","slug":"package-json","link":"#package-json","children":[]},{"level":3,"title":"npx","slug":"npx","link":"#npx","children":[]},{"level":3,"title":"npm包的发布","slug":"npm包的发布","link":"#npm包的发布","children":[]},{"level":3,"title":"npm包的开发调试","slug":"npm包的开发调试","link":"#npm包的开发调试","children":[]},{"level":3,"title":"PNPM","slug":"pnpm","link":"#pnpm","children":[]}]},{"level":2,"title":"系统学习Webpack","slug":"系统学习webpack","link":"#系统学习webpack","children":[{"level":3,"title":"Node内置模块 path","slug":"node内置模块-path","link":"#node内置模块-path","children":[]},{"level":3,"title":"初识Webpack","slug":"初识webpack","link":"#初识webpack","children":[]}]}],"relativePath":"note/Front-end Engineering.md","lastUpdated":1676737739000}'),e={name:"note/Front-end Engineering.md"},o=l("",254),p=[o];function c(r,t,i,d,y,D){return n(),a("div",null,p)}const A=s(e,[["render",c]]);export{F as __pageData,A as default};
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const F=JSON.parse('{"title":"前端工程化","description":"","frontmatter":{},"headers":[{"level":2,"title":"Node.js","slug":"node-js","link":"#node-js","children":[{"level":3,"title":"什么是Node.js","slug":"什么是node-js","link":"#什么是node-js","children":[]},{"level":3,"title":"Node.js的应用场景","slug":"node-js的应用场景","link":"#node-js的应用场景","children":[]},{"level":3,"title":"Node.js的参数传递","slug":"node-js的参数传递","link":"#node-js的参数传递","children":[]},{"level":3,"title":"Node中的全局对象","slug":"node中的全局对象","link":"#node中的全局对象","children":[]}]},{"level":2,"title":"模块化开发","slug":"模块化开发","link":"#模块化开发","children":[{"level":3,"title":"模块化的初衷","slug":"模块化的初衷","link":"#模块化的初衷","children":[]},{"level":3,"title":"CommonJS","slug":"commonjs","link":"#commonjs","children":[]},{"level":3,"title":"ESModule","slug":"esmodule","link":"#esmodule","children":[]},{"level":3,"title":"深入理解模块加载","slug":"深入理解模块加载","link":"#深入理解模块加载","children":[]},{"level":3,"title":"拓展内容","slug":"拓展内容","link":"#拓展内容","children":[]}]},{"level":2,"title":"包管理工具","slug":"包管理工具","link":"#包管理工具","children":[{"level":3,"title":"npm","slug":"npm","link":"#npm","children":[]},{"level":3,"title":"package.json","slug":"package-json","link":"#package-json","children":[]},{"level":3,"title":"npx","slug":"npx","link":"#npx","children":[]},{"level":3,"title":"npm包的发布","slug":"npm包的发布","link":"#npm包的发布","children":[]},{"level":3,"title":"npm包的开发调试","slug":"npm包的开发调试","link":"#npm包的开发调试","children":[]},{"level":3,"title":"PNPM","slug":"pnpm","link":"#pnpm","children":[]}]},{"level":2,"title":"系统学习Webpack","slug":"系统学习webpack","link":"#系统学习webpack","children":[{"level":3,"title":"Node内置模块 path","slug":"node内置模块-path","link":"#node内置模块-path","children":[]},{"level":3,"title":"初识Webpack","slug":"初识webpack","link":"#初识webpack","children":[]}]}],"relativePath":"note/Front-end Engineering.md","lastUpdated":1676979063000}'),e={name:"note/Front-end Engineering.md"},o=l("",254),p=[o];function c(r,t,i,d,y,D){return n(),a("div",null,p)}const A=s(e,[["render",c]]);export{F as __pageData,A as default};
diff --git a/assets/note_JavaScript.md.6a2d95de.js b/assets/note_JavaScript.md.e58e866f.js
similarity index 91%
rename from assets/note_JavaScript.md.6a2d95de.js
rename to assets/note_JavaScript.md.e58e866f.js
index 9175d403..2250d3b5 100644
--- a/assets/note_JavaScript.md.6a2d95de.js
+++ b/assets/note_JavaScript.md.e58e866f.js
@@ -1 +1 @@
-import{_ as a,o as e,c as r,b as t,d as s}from"./app.33820b61.js";const S=JSON.parse('{"title":"JavaScript 基础","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"note/JavaScript.md","lastUpdated":1676737739000}'),c={name:"note/JavaScript.md"},i=t("h1",{id:"javascript-基础",tabindex:"-1"},[s("JavaScript 基础 "),t("a",{class:"header-anchor",href:"#javascript-基础","aria-hidden":"true"},"#")],-1),n=t("p",null,"JavaScript 组成",-1),o=t("ul",null,[t("li",null,"ECMAScript 定义语言规范"),t("li",null,"DOM 用于操作文档的API"),t("li",null,"BOM 用于操作浏览器的API")],-1),l=[i,n,o];function d(p,_,h,u,v,f){return e(),r("div",null,l)}const J=a(c,[["render",d]]);export{S as __pageData,J as default};
+import{_ as a,o as e,c as r,b as t,d as s}from"./app.33820b61.js";const S=JSON.parse('{"title":"JavaScript 基础","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"note/JavaScript.md","lastUpdated":1676979063000}'),c={name:"note/JavaScript.md"},i=t("h1",{id:"javascript-基础",tabindex:"-1"},[s("JavaScript 基础 "),t("a",{class:"header-anchor",href:"#javascript-基础","aria-hidden":"true"},"#")],-1),n=t("p",null,"JavaScript 组成",-1),o=t("ul",null,[t("li",null,"ECMAScript 定义语言规范"),t("li",null,"DOM 用于操作文档的API"),t("li",null,"BOM 用于操作浏览器的API")],-1),l=[i,n,o];function d(p,_,h,u,v,f){return e(),r("div",null,l)}const J=a(c,[["render",d]]);export{S as __pageData,J as default};
diff --git a/assets/note_JavaScript.md.6a2d95de.lean.js b/assets/note_JavaScript.md.e58e866f.lean.js
similarity index 91%
rename from assets/note_JavaScript.md.6a2d95de.lean.js
rename to assets/note_JavaScript.md.e58e866f.lean.js
index 9175d403..2250d3b5 100644
--- a/assets/note_JavaScript.md.6a2d95de.lean.js
+++ b/assets/note_JavaScript.md.e58e866f.lean.js
@@ -1 +1 @@
-import{_ as a,o as e,c as r,b as t,d as s}from"./app.33820b61.js";const S=JSON.parse('{"title":"JavaScript 基础","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"note/JavaScript.md","lastUpdated":1676737739000}'),c={name:"note/JavaScript.md"},i=t("h1",{id:"javascript-基础",tabindex:"-1"},[s("JavaScript 基础 "),t("a",{class:"header-anchor",href:"#javascript-基础","aria-hidden":"true"},"#")],-1),n=t("p",null,"JavaScript 组成",-1),o=t("ul",null,[t("li",null,"ECMAScript 定义语言规范"),t("li",null,"DOM 用于操作文档的API"),t("li",null,"BOM 用于操作浏览器的API")],-1),l=[i,n,o];function d(p,_,h,u,v,f){return e(),r("div",null,l)}const J=a(c,[["render",d]]);export{S as __pageData,J as default};
+import{_ as a,o as e,c as r,b as t,d as s}from"./app.33820b61.js";const S=JSON.parse('{"title":"JavaScript 基础","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"note/JavaScript.md","lastUpdated":1676979063000}'),c={name:"note/JavaScript.md"},i=t("h1",{id:"javascript-基础",tabindex:"-1"},[s("JavaScript 基础 "),t("a",{class:"header-anchor",href:"#javascript-基础","aria-hidden":"true"},"#")],-1),n=t("p",null,"JavaScript 组成",-1),o=t("ul",null,[t("li",null,"ECMAScript 定义语言规范"),t("li",null,"DOM 用于操作文档的API"),t("li",null,"BOM 用于操作浏览器的API")],-1),l=[i,n,o];function d(p,_,h,u,v,f){return e(),r("div",null,l)}const J=a(c,[["render",d]]);export{S as __pageData,J as default};
diff --git a/assets/note_JavaScriptEnhanced.md.209d0c05.js b/assets/note_JavaScriptEnhanced.md.b46ba179.js
similarity index 99%
rename from assets/note_JavaScriptEnhanced.md.209d0c05.js
rename to assets/note_JavaScriptEnhanced.md.b46ba179.js
index 21111a45..d7365d6a 100644
--- a/assets/note_JavaScriptEnhanced.md.209d0c05.js
+++ b/assets/note_JavaScriptEnhanced.md.b46ba179.js
@@ -1,4 +1,4 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const p="/assets/image-20221118222207332-16687813334481.64935e06.png",o="/assets/image-20221118222311200-16687813941873.8c07f79f.png",e="/assets/image-20221122103111654.29f48e34.png",c="/assets/image-20221122103256116.b7d76f81.png",r="/assets/image-20221122103715428.587185d1.png",t="/assets/image-20221125090752249.baeedc2b.png",y="/assets/image-20221125094148365.3adfbe2d.png",g=JSON.parse('{"title":"JavaScript 高级教程","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"函数中this指向","slug":"函数中this指向","link":"#函数中this指向","children":[{"level":3,"title":"如何改变this的指向","slug":"如何改变this的指向","link":"#如何改变this的指向","children":[]},{"level":3,"title":"new 实例化一个函数","slug":"new-实例化一个函数","link":"#new-实例化一个函数","children":[]},{"level":3,"title":"使用 call apply bind","slug":"使用-call-apply-bind","link":"#使用-call-apply-bind","children":[]},{"level":3,"title":"箭头函数","slug":"箭头函数","link":"#箭头函数","children":[]},{"level":3,"title":"严格模式","slug":"严格模式","link":"#严格模式","children":[]},{"level":3,"title":"this面试题","slug":"this面试题","link":"#this面试题","children":[]}]},{"level":2,"title":"原型与继承","slug":"原型与继承","link":"#原型与继承","children":[{"level":3,"title":"原型有什么作用?","slug":"原型有什么作用","link":"#原型有什么作用","children":[]},{"level":3,"title":"函数的显式原型","slug":"函数的显式原型","link":"#函数的显式原型","children":[]},{"level":3,"title":"Object的原型","slug":"object的原型","link":"#object的原型","children":[]},{"level":3,"title":"原型链实现继承","slug":"原型链实现继承","link":"#原型链实现继承","children":[]},{"level":3,"title":"创建原型对象的方法","slug":"创建原型对象的方法","link":"#创建原型对象的方法","children":[]},{"level":3,"title":"对象方法补充","slug":"对象方法补充","link":"#对象方法补充","children":[]},{"level":3,"title":"解读原型继承关系图","slug":"解读原型继承关系图","link":"#解读原型继承关系图","children":[]},{"level":3,"title":"构造函数的类方法","slug":"构造函数的类方法","link":"#构造函数的类方法","children":[]}]},{"level":2,"title":"ES6继承","slug":"es6继承","link":"#es6继承","children":[{"level":3,"title":"与function的异同","slug":"与function的异同","link":"#与function的异同","children":[]},{"level":3,"title":"定义访问器方法","slug":"定义访问器方法","link":"#定义访问器方法","children":[]},{"level":3,"title":"类的静态方法","slug":"类的静态方法","link":"#类的静态方法","children":[]},{"level":3,"title":"extends实现继承","slug":"extends实现继承","link":"#extends实现继承","children":[]},{"level":3,"title":"继承自默认类","slug":"继承自默认类","link":"#继承自默认类","children":[]},{"level":3,"title":"类的混入mixin","slug":"类的混入mixin","link":"#类的混入mixin","children":[]},{"level":3,"title":"Babel是如何转化ES6的","slug":"babel是如何转化es6的","link":"#babel是如何转化es6的","children":[]}]},{"level":2,"title":"浏览器运行原理","slug":"浏览器运行原理","link":"#浏览器运行原理","children":[{"level":3,"title":"网页解析过程","slug":"网页解析过程","link":"#网页解析过程","children":[]},{"level":3,"title":"浏览器对script元素的处理","slug":"浏览器对script元素的处理","link":"#浏览器对script元素的处理","children":[]}]},{"level":2,"title":"JavaScript 运行原理","slug":"javascript-运行原理","link":"#javascript-运行原理","children":[{"level":3,"title":"JS代码的执行","slug":"js代码的执行","link":"#js代码的执行","children":[]},{"level":3,"title":"JavaScript V8引擎","slug":"javascript-v8引擎","link":"#javascript-v8引擎","children":[]},{"level":3,"title":"JavaScript代码执行过程","slug":"javascript代码执行过程","link":"#javascript代码执行过程","children":[]}]},{"level":2,"title":"Proxy与Reflect","slug":"proxy与reflect","link":"#proxy与reflect","children":[{"level":3,"title":"监听对象方法","slug":"监听对象方法","link":"#监听对象方法","children":[]},{"level":3,"title":"Proxy","slug":"proxy","link":"#proxy","children":[]},{"level":3,"title":"Reflect","slug":"reflect","link":"#reflect","children":[]},{"level":3,"title":"理解Proxy与Reflect中的receiver参数","slug":"理解proxy与reflect中的receiver参数","link":"#理解proxy与reflect中的receiver参数","children":[]}]},{"level":2,"title":"Promise详解","slug":"promise详解","link":"#promise详解","children":[{"level":3,"title":"异步代码","slug":"异步代码","link":"#异步代码","children":[]},{"level":3,"title":"认识Promise","slug":"认识promise","link":"#认识promise","children":[]},{"level":3,"title":"Promise类方法","slug":"promise类方法","link":"#promise类方法","children":[]}]},{"level":2,"title":"迭代器与生成器","slug":"迭代器与生成器","link":"#迭代器与生成器","children":[{"level":3,"title":"什么是迭代器","slug":"什么是迭代器","link":"#什么是迭代器","children":[]},{"level":3,"title":"异步处理","slug":"异步处理","link":"#异步处理","children":[]}]},{"level":2,"title":"let与const","slug":"let与const","link":"#let与const","children":[{"level":3,"title":"作用域提升","slug":"作用域提升","link":"#作用域提升","children":[]},{"level":3,"title":"暂时性死区","slug":"暂时性死区","link":"#暂时性死区","children":[]},{"level":3,"title":"变量保存位置","slug":"变量保存位置","link":"#变量保存位置","children":[]},{"level":3,"title":"块级作用域","slug":"块级作用域","link":"#块级作用域","children":[]},{"level":3,"title":"开发中的应用","slug":"开发中的应用","link":"#开发中的应用","children":[]}]},{"level":2,"title":"await async 事件循环","slug":"await-async-事件循环","link":"#await-async-事件循环","children":[{"level":3,"title":"异步函数 async","slug":"异步函数-async","link":"#异步函数-async","children":[]},{"level":3,"title":"await关键字","slug":"await关键字","link":"#await关键字","children":[]},{"level":3,"title":"进程与线程","slug":"进程与线程","link":"#进程与线程","children":[]},{"level":3,"title":"JavaScript线程","slug":"javascript线程","link":"#javascript线程","children":[]},{"level":3,"title":"微任务与宏任务","slug":"微任务与宏任务","link":"#微任务与宏任务","children":[]},{"level":3,"title":"事件循环 面试题","slug":"事件循环-面试题","link":"#事件循环-面试题","children":[]},{"level":3,"title":"Node事件循环","slug":"node事件循环","link":"#node事件循环","children":[]}]},{"level":2,"title":"防抖与节流","slug":"防抖与节流","link":"#防抖与节流","children":[{"level":3,"title":"防抖函数","slug":"防抖函数","link":"#防抖函数","children":[]},{"level":3,"title":"节流函数","slug":"节流函数","link":"#节流函数","children":[]}]},{"level":2,"title":"深拷贝与浅拷贝","slug":"深拷贝与浅拷贝","link":"#深拷贝与浅拷贝","children":[{"level":3,"title":"浅拷贝","slug":"浅拷贝","link":"#浅拷贝","children":[]},{"level":3,"title":"深拷贝","slug":"深拷贝","link":"#深拷贝","children":[]},{"level":3,"title":"完整代码","slug":"完整代码","link":"#完整代码","children":[]}]},{"level":2,"title":"事件总线","slug":"事件总线","link":"#事件总线","children":[]}],"relativePath":"note/JavaScriptEnhanced.md","lastUpdated":1676737739000}'),F={name:"note/JavaScriptEnhanced.md"},D=l(`

JavaScript 高级教程

函数中this指向

函数在调用时, Javascript会默认为this绑定一个值

js
// 定义一个函数
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const p="/assets/image-20221118222207332-16687813334481.64935e06.png",o="/assets/image-20221118222311200-16687813941873.8c07f79f.png",e="/assets/image-20221122103111654.29f48e34.png",c="/assets/image-20221122103256116.b7d76f81.png",r="/assets/image-20221122103715428.587185d1.png",t="/assets/image-20221125090752249.baeedc2b.png",y="/assets/image-20221125094148365.3adfbe2d.png",g=JSON.parse('{"title":"JavaScript 高级教程","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"函数中this指向","slug":"函数中this指向","link":"#函数中this指向","children":[{"level":3,"title":"如何改变this的指向","slug":"如何改变this的指向","link":"#如何改变this的指向","children":[]},{"level":3,"title":"new 实例化一个函数","slug":"new-实例化一个函数","link":"#new-实例化一个函数","children":[]},{"level":3,"title":"使用 call apply bind","slug":"使用-call-apply-bind","link":"#使用-call-apply-bind","children":[]},{"level":3,"title":"箭头函数","slug":"箭头函数","link":"#箭头函数","children":[]},{"level":3,"title":"严格模式","slug":"严格模式","link":"#严格模式","children":[]},{"level":3,"title":"this面试题","slug":"this面试题","link":"#this面试题","children":[]}]},{"level":2,"title":"原型与继承","slug":"原型与继承","link":"#原型与继承","children":[{"level":3,"title":"原型有什么作用?","slug":"原型有什么作用","link":"#原型有什么作用","children":[]},{"level":3,"title":"函数的显式原型","slug":"函数的显式原型","link":"#函数的显式原型","children":[]},{"level":3,"title":"Object的原型","slug":"object的原型","link":"#object的原型","children":[]},{"level":3,"title":"原型链实现继承","slug":"原型链实现继承","link":"#原型链实现继承","children":[]},{"level":3,"title":"创建原型对象的方法","slug":"创建原型对象的方法","link":"#创建原型对象的方法","children":[]},{"level":3,"title":"对象方法补充","slug":"对象方法补充","link":"#对象方法补充","children":[]},{"level":3,"title":"解读原型继承关系图","slug":"解读原型继承关系图","link":"#解读原型继承关系图","children":[]},{"level":3,"title":"构造函数的类方法","slug":"构造函数的类方法","link":"#构造函数的类方法","children":[]}]},{"level":2,"title":"ES6继承","slug":"es6继承","link":"#es6继承","children":[{"level":3,"title":"与function的异同","slug":"与function的异同","link":"#与function的异同","children":[]},{"level":3,"title":"定义访问器方法","slug":"定义访问器方法","link":"#定义访问器方法","children":[]},{"level":3,"title":"类的静态方法","slug":"类的静态方法","link":"#类的静态方法","children":[]},{"level":3,"title":"extends实现继承","slug":"extends实现继承","link":"#extends实现继承","children":[]},{"level":3,"title":"继承自默认类","slug":"继承自默认类","link":"#继承自默认类","children":[]},{"level":3,"title":"类的混入mixin","slug":"类的混入mixin","link":"#类的混入mixin","children":[]},{"level":3,"title":"Babel是如何转化ES6的","slug":"babel是如何转化es6的","link":"#babel是如何转化es6的","children":[]}]},{"level":2,"title":"浏览器运行原理","slug":"浏览器运行原理","link":"#浏览器运行原理","children":[{"level":3,"title":"网页解析过程","slug":"网页解析过程","link":"#网页解析过程","children":[]},{"level":3,"title":"浏览器对script元素的处理","slug":"浏览器对script元素的处理","link":"#浏览器对script元素的处理","children":[]}]},{"level":2,"title":"JavaScript 运行原理","slug":"javascript-运行原理","link":"#javascript-运行原理","children":[{"level":3,"title":"JS代码的执行","slug":"js代码的执行","link":"#js代码的执行","children":[]},{"level":3,"title":"JavaScript V8引擎","slug":"javascript-v8引擎","link":"#javascript-v8引擎","children":[]},{"level":3,"title":"JavaScript代码执行过程","slug":"javascript代码执行过程","link":"#javascript代码执行过程","children":[]}]},{"level":2,"title":"Proxy与Reflect","slug":"proxy与reflect","link":"#proxy与reflect","children":[{"level":3,"title":"监听对象方法","slug":"监听对象方法","link":"#监听对象方法","children":[]},{"level":3,"title":"Proxy","slug":"proxy","link":"#proxy","children":[]},{"level":3,"title":"Reflect","slug":"reflect","link":"#reflect","children":[]},{"level":3,"title":"理解Proxy与Reflect中的receiver参数","slug":"理解proxy与reflect中的receiver参数","link":"#理解proxy与reflect中的receiver参数","children":[]}]},{"level":2,"title":"Promise详解","slug":"promise详解","link":"#promise详解","children":[{"level":3,"title":"异步代码","slug":"异步代码","link":"#异步代码","children":[]},{"level":3,"title":"认识Promise","slug":"认识promise","link":"#认识promise","children":[]},{"level":3,"title":"Promise类方法","slug":"promise类方法","link":"#promise类方法","children":[]}]},{"level":2,"title":"迭代器与生成器","slug":"迭代器与生成器","link":"#迭代器与生成器","children":[{"level":3,"title":"什么是迭代器","slug":"什么是迭代器","link":"#什么是迭代器","children":[]},{"level":3,"title":"异步处理","slug":"异步处理","link":"#异步处理","children":[]}]},{"level":2,"title":"let与const","slug":"let与const","link":"#let与const","children":[{"level":3,"title":"作用域提升","slug":"作用域提升","link":"#作用域提升","children":[]},{"level":3,"title":"暂时性死区","slug":"暂时性死区","link":"#暂时性死区","children":[]},{"level":3,"title":"变量保存位置","slug":"变量保存位置","link":"#变量保存位置","children":[]},{"level":3,"title":"块级作用域","slug":"块级作用域","link":"#块级作用域","children":[]},{"level":3,"title":"开发中的应用","slug":"开发中的应用","link":"#开发中的应用","children":[]}]},{"level":2,"title":"await async 事件循环","slug":"await-async-事件循环","link":"#await-async-事件循环","children":[{"level":3,"title":"异步函数 async","slug":"异步函数-async","link":"#异步函数-async","children":[]},{"level":3,"title":"await关键字","slug":"await关键字","link":"#await关键字","children":[]},{"level":3,"title":"进程与线程","slug":"进程与线程","link":"#进程与线程","children":[]},{"level":3,"title":"JavaScript线程","slug":"javascript线程","link":"#javascript线程","children":[]},{"level":3,"title":"微任务与宏任务","slug":"微任务与宏任务","link":"#微任务与宏任务","children":[]},{"level":3,"title":"事件循环 面试题","slug":"事件循环-面试题","link":"#事件循环-面试题","children":[]},{"level":3,"title":"Node事件循环","slug":"node事件循环","link":"#node事件循环","children":[]}]},{"level":2,"title":"防抖与节流","slug":"防抖与节流","link":"#防抖与节流","children":[{"level":3,"title":"防抖函数","slug":"防抖函数","link":"#防抖函数","children":[]},{"level":3,"title":"节流函数","slug":"节流函数","link":"#节流函数","children":[]}]},{"level":2,"title":"深拷贝与浅拷贝","slug":"深拷贝与浅拷贝","link":"#深拷贝与浅拷贝","children":[{"level":3,"title":"浅拷贝","slug":"浅拷贝","link":"#浅拷贝","children":[]},{"level":3,"title":"深拷贝","slug":"深拷贝","link":"#深拷贝","children":[]},{"level":3,"title":"完整代码","slug":"完整代码","link":"#完整代码","children":[]}]},{"level":2,"title":"事件总线","slug":"事件总线","link":"#事件总线","children":[]}],"relativePath":"note/JavaScriptEnhanced.md","lastUpdated":1676979063000}'),F={name:"note/JavaScriptEnhanced.md"},D=l(`

JavaScript 高级教程

函数中this指向

函数在调用时, Javascript会默认为this绑定一个值

js
// 定义一个函数
 function foo() {
   console.log(this)
 }
diff --git a/assets/note_JavaScriptEnhanced.md.209d0c05.lean.js b/assets/note_JavaScriptEnhanced.md.b46ba179.lean.js
similarity index 99%
rename from assets/note_JavaScriptEnhanced.md.209d0c05.lean.js
rename to assets/note_JavaScriptEnhanced.md.b46ba179.lean.js
index f8430590..025a96f1 100644
--- a/assets/note_JavaScriptEnhanced.md.209d0c05.lean.js
+++ b/assets/note_JavaScriptEnhanced.md.b46ba179.lean.js
@@ -1 +1 @@
-import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const p="/assets/image-20221118222207332-16687813334481.64935e06.png",o="/assets/image-20221118222311200-16687813941873.8c07f79f.png",e="/assets/image-20221122103111654.29f48e34.png",c="/assets/image-20221122103256116.b7d76f81.png",r="/assets/image-20221122103715428.587185d1.png",t="/assets/image-20221125090752249.baeedc2b.png",y="/assets/image-20221125094148365.3adfbe2d.png",g=JSON.parse('{"title":"JavaScript 高级教程","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"函数中this指向","slug":"函数中this指向","link":"#函数中this指向","children":[{"level":3,"title":"如何改变this的指向","slug":"如何改变this的指向","link":"#如何改变this的指向","children":[]},{"level":3,"title":"new 实例化一个函数","slug":"new-实例化一个函数","link":"#new-实例化一个函数","children":[]},{"level":3,"title":"使用 call apply bind","slug":"使用-call-apply-bind","link":"#使用-call-apply-bind","children":[]},{"level":3,"title":"箭头函数","slug":"箭头函数","link":"#箭头函数","children":[]},{"level":3,"title":"严格模式","slug":"严格模式","link":"#严格模式","children":[]},{"level":3,"title":"this面试题","slug":"this面试题","link":"#this面试题","children":[]}]},{"level":2,"title":"原型与继承","slug":"原型与继承","link":"#原型与继承","children":[{"level":3,"title":"原型有什么作用?","slug":"原型有什么作用","link":"#原型有什么作用","children":[]},{"level":3,"title":"函数的显式原型","slug":"函数的显式原型","link":"#函数的显式原型","children":[]},{"level":3,"title":"Object的原型","slug":"object的原型","link":"#object的原型","children":[]},{"level":3,"title":"原型链实现继承","slug":"原型链实现继承","link":"#原型链实现继承","children":[]},{"level":3,"title":"创建原型对象的方法","slug":"创建原型对象的方法","link":"#创建原型对象的方法","children":[]},{"level":3,"title":"对象方法补充","slug":"对象方法补充","link":"#对象方法补充","children":[]},{"level":3,"title":"解读原型继承关系图","slug":"解读原型继承关系图","link":"#解读原型继承关系图","children":[]},{"level":3,"title":"构造函数的类方法","slug":"构造函数的类方法","link":"#构造函数的类方法","children":[]}]},{"level":2,"title":"ES6继承","slug":"es6继承","link":"#es6继承","children":[{"level":3,"title":"与function的异同","slug":"与function的异同","link":"#与function的异同","children":[]},{"level":3,"title":"定义访问器方法","slug":"定义访问器方法","link":"#定义访问器方法","children":[]},{"level":3,"title":"类的静态方法","slug":"类的静态方法","link":"#类的静态方法","children":[]},{"level":3,"title":"extends实现继承","slug":"extends实现继承","link":"#extends实现继承","children":[]},{"level":3,"title":"继承自默认类","slug":"继承自默认类","link":"#继承自默认类","children":[]},{"level":3,"title":"类的混入mixin","slug":"类的混入mixin","link":"#类的混入mixin","children":[]},{"level":3,"title":"Babel是如何转化ES6的","slug":"babel是如何转化es6的","link":"#babel是如何转化es6的","children":[]}]},{"level":2,"title":"浏览器运行原理","slug":"浏览器运行原理","link":"#浏览器运行原理","children":[{"level":3,"title":"网页解析过程","slug":"网页解析过程","link":"#网页解析过程","children":[]},{"level":3,"title":"浏览器对script元素的处理","slug":"浏览器对script元素的处理","link":"#浏览器对script元素的处理","children":[]}]},{"level":2,"title":"JavaScript 运行原理","slug":"javascript-运行原理","link":"#javascript-运行原理","children":[{"level":3,"title":"JS代码的执行","slug":"js代码的执行","link":"#js代码的执行","children":[]},{"level":3,"title":"JavaScript V8引擎","slug":"javascript-v8引擎","link":"#javascript-v8引擎","children":[]},{"level":3,"title":"JavaScript代码执行过程","slug":"javascript代码执行过程","link":"#javascript代码执行过程","children":[]}]},{"level":2,"title":"Proxy与Reflect","slug":"proxy与reflect","link":"#proxy与reflect","children":[{"level":3,"title":"监听对象方法","slug":"监听对象方法","link":"#监听对象方法","children":[]},{"level":3,"title":"Proxy","slug":"proxy","link":"#proxy","children":[]},{"level":3,"title":"Reflect","slug":"reflect","link":"#reflect","children":[]},{"level":3,"title":"理解Proxy与Reflect中的receiver参数","slug":"理解proxy与reflect中的receiver参数","link":"#理解proxy与reflect中的receiver参数","children":[]}]},{"level":2,"title":"Promise详解","slug":"promise详解","link":"#promise详解","children":[{"level":3,"title":"异步代码","slug":"异步代码","link":"#异步代码","children":[]},{"level":3,"title":"认识Promise","slug":"认识promise","link":"#认识promise","children":[]},{"level":3,"title":"Promise类方法","slug":"promise类方法","link":"#promise类方法","children":[]}]},{"level":2,"title":"迭代器与生成器","slug":"迭代器与生成器","link":"#迭代器与生成器","children":[{"level":3,"title":"什么是迭代器","slug":"什么是迭代器","link":"#什么是迭代器","children":[]},{"level":3,"title":"异步处理","slug":"异步处理","link":"#异步处理","children":[]}]},{"level":2,"title":"let与const","slug":"let与const","link":"#let与const","children":[{"level":3,"title":"作用域提升","slug":"作用域提升","link":"#作用域提升","children":[]},{"level":3,"title":"暂时性死区","slug":"暂时性死区","link":"#暂时性死区","children":[]},{"level":3,"title":"变量保存位置","slug":"变量保存位置","link":"#变量保存位置","children":[]},{"level":3,"title":"块级作用域","slug":"块级作用域","link":"#块级作用域","children":[]},{"level":3,"title":"开发中的应用","slug":"开发中的应用","link":"#开发中的应用","children":[]}]},{"level":2,"title":"await async 事件循环","slug":"await-async-事件循环","link":"#await-async-事件循环","children":[{"level":3,"title":"异步函数 async","slug":"异步函数-async","link":"#异步函数-async","children":[]},{"level":3,"title":"await关键字","slug":"await关键字","link":"#await关键字","children":[]},{"level":3,"title":"进程与线程","slug":"进程与线程","link":"#进程与线程","children":[]},{"level":3,"title":"JavaScript线程","slug":"javascript线程","link":"#javascript线程","children":[]},{"level":3,"title":"微任务与宏任务","slug":"微任务与宏任务","link":"#微任务与宏任务","children":[]},{"level":3,"title":"事件循环 面试题","slug":"事件循环-面试题","link":"#事件循环-面试题","children":[]},{"level":3,"title":"Node事件循环","slug":"node事件循环","link":"#node事件循环","children":[]}]},{"level":2,"title":"防抖与节流","slug":"防抖与节流","link":"#防抖与节流","children":[{"level":3,"title":"防抖函数","slug":"防抖函数","link":"#防抖函数","children":[]},{"level":3,"title":"节流函数","slug":"节流函数","link":"#节流函数","children":[]}]},{"level":2,"title":"深拷贝与浅拷贝","slug":"深拷贝与浅拷贝","link":"#深拷贝与浅拷贝","children":[{"level":3,"title":"浅拷贝","slug":"浅拷贝","link":"#浅拷贝","children":[]},{"level":3,"title":"深拷贝","slug":"深拷贝","link":"#深拷贝","children":[]},{"level":3,"title":"完整代码","slug":"完整代码","link":"#完整代码","children":[]}]},{"level":2,"title":"事件总线","slug":"事件总线","link":"#事件总线","children":[]}],"relativePath":"note/JavaScriptEnhanced.md","lastUpdated":1676737739000}'),F={name:"note/JavaScriptEnhanced.md"},D=l("",668),i=[D];function A(C,b,u,d,m,h){return n(),a("div",null,i)}const E=s(F,[["render",A]]);export{g as __pageData,E as default};
+import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const p="/assets/image-20221118222207332-16687813334481.64935e06.png",o="/assets/image-20221118222311200-16687813941873.8c07f79f.png",e="/assets/image-20221122103111654.29f48e34.png",c="/assets/image-20221122103256116.b7d76f81.png",r="/assets/image-20221122103715428.587185d1.png",t="/assets/image-20221125090752249.baeedc2b.png",y="/assets/image-20221125094148365.3adfbe2d.png",g=JSON.parse('{"title":"JavaScript 高级教程","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"函数中this指向","slug":"函数中this指向","link":"#函数中this指向","children":[{"level":3,"title":"如何改变this的指向","slug":"如何改变this的指向","link":"#如何改变this的指向","children":[]},{"level":3,"title":"new 实例化一个函数","slug":"new-实例化一个函数","link":"#new-实例化一个函数","children":[]},{"level":3,"title":"使用 call apply bind","slug":"使用-call-apply-bind","link":"#使用-call-apply-bind","children":[]},{"level":3,"title":"箭头函数","slug":"箭头函数","link":"#箭头函数","children":[]},{"level":3,"title":"严格模式","slug":"严格模式","link":"#严格模式","children":[]},{"level":3,"title":"this面试题","slug":"this面试题","link":"#this面试题","children":[]}]},{"level":2,"title":"原型与继承","slug":"原型与继承","link":"#原型与继承","children":[{"level":3,"title":"原型有什么作用?","slug":"原型有什么作用","link":"#原型有什么作用","children":[]},{"level":3,"title":"函数的显式原型","slug":"函数的显式原型","link":"#函数的显式原型","children":[]},{"level":3,"title":"Object的原型","slug":"object的原型","link":"#object的原型","children":[]},{"level":3,"title":"原型链实现继承","slug":"原型链实现继承","link":"#原型链实现继承","children":[]},{"level":3,"title":"创建原型对象的方法","slug":"创建原型对象的方法","link":"#创建原型对象的方法","children":[]},{"level":3,"title":"对象方法补充","slug":"对象方法补充","link":"#对象方法补充","children":[]},{"level":3,"title":"解读原型继承关系图","slug":"解读原型继承关系图","link":"#解读原型继承关系图","children":[]},{"level":3,"title":"构造函数的类方法","slug":"构造函数的类方法","link":"#构造函数的类方法","children":[]}]},{"level":2,"title":"ES6继承","slug":"es6继承","link":"#es6继承","children":[{"level":3,"title":"与function的异同","slug":"与function的异同","link":"#与function的异同","children":[]},{"level":3,"title":"定义访问器方法","slug":"定义访问器方法","link":"#定义访问器方法","children":[]},{"level":3,"title":"类的静态方法","slug":"类的静态方法","link":"#类的静态方法","children":[]},{"level":3,"title":"extends实现继承","slug":"extends实现继承","link":"#extends实现继承","children":[]},{"level":3,"title":"继承自默认类","slug":"继承自默认类","link":"#继承自默认类","children":[]},{"level":3,"title":"类的混入mixin","slug":"类的混入mixin","link":"#类的混入mixin","children":[]},{"level":3,"title":"Babel是如何转化ES6的","slug":"babel是如何转化es6的","link":"#babel是如何转化es6的","children":[]}]},{"level":2,"title":"浏览器运行原理","slug":"浏览器运行原理","link":"#浏览器运行原理","children":[{"level":3,"title":"网页解析过程","slug":"网页解析过程","link":"#网页解析过程","children":[]},{"level":3,"title":"浏览器对script元素的处理","slug":"浏览器对script元素的处理","link":"#浏览器对script元素的处理","children":[]}]},{"level":2,"title":"JavaScript 运行原理","slug":"javascript-运行原理","link":"#javascript-运行原理","children":[{"level":3,"title":"JS代码的执行","slug":"js代码的执行","link":"#js代码的执行","children":[]},{"level":3,"title":"JavaScript V8引擎","slug":"javascript-v8引擎","link":"#javascript-v8引擎","children":[]},{"level":3,"title":"JavaScript代码执行过程","slug":"javascript代码执行过程","link":"#javascript代码执行过程","children":[]}]},{"level":2,"title":"Proxy与Reflect","slug":"proxy与reflect","link":"#proxy与reflect","children":[{"level":3,"title":"监听对象方法","slug":"监听对象方法","link":"#监听对象方法","children":[]},{"level":3,"title":"Proxy","slug":"proxy","link":"#proxy","children":[]},{"level":3,"title":"Reflect","slug":"reflect","link":"#reflect","children":[]},{"level":3,"title":"理解Proxy与Reflect中的receiver参数","slug":"理解proxy与reflect中的receiver参数","link":"#理解proxy与reflect中的receiver参数","children":[]}]},{"level":2,"title":"Promise详解","slug":"promise详解","link":"#promise详解","children":[{"level":3,"title":"异步代码","slug":"异步代码","link":"#异步代码","children":[]},{"level":3,"title":"认识Promise","slug":"认识promise","link":"#认识promise","children":[]},{"level":3,"title":"Promise类方法","slug":"promise类方法","link":"#promise类方法","children":[]}]},{"level":2,"title":"迭代器与生成器","slug":"迭代器与生成器","link":"#迭代器与生成器","children":[{"level":3,"title":"什么是迭代器","slug":"什么是迭代器","link":"#什么是迭代器","children":[]},{"level":3,"title":"异步处理","slug":"异步处理","link":"#异步处理","children":[]}]},{"level":2,"title":"let与const","slug":"let与const","link":"#let与const","children":[{"level":3,"title":"作用域提升","slug":"作用域提升","link":"#作用域提升","children":[]},{"level":3,"title":"暂时性死区","slug":"暂时性死区","link":"#暂时性死区","children":[]},{"level":3,"title":"变量保存位置","slug":"变量保存位置","link":"#变量保存位置","children":[]},{"level":3,"title":"块级作用域","slug":"块级作用域","link":"#块级作用域","children":[]},{"level":3,"title":"开发中的应用","slug":"开发中的应用","link":"#开发中的应用","children":[]}]},{"level":2,"title":"await async 事件循环","slug":"await-async-事件循环","link":"#await-async-事件循环","children":[{"level":3,"title":"异步函数 async","slug":"异步函数-async","link":"#异步函数-async","children":[]},{"level":3,"title":"await关键字","slug":"await关键字","link":"#await关键字","children":[]},{"level":3,"title":"进程与线程","slug":"进程与线程","link":"#进程与线程","children":[]},{"level":3,"title":"JavaScript线程","slug":"javascript线程","link":"#javascript线程","children":[]},{"level":3,"title":"微任务与宏任务","slug":"微任务与宏任务","link":"#微任务与宏任务","children":[]},{"level":3,"title":"事件循环 面试题","slug":"事件循环-面试题","link":"#事件循环-面试题","children":[]},{"level":3,"title":"Node事件循环","slug":"node事件循环","link":"#node事件循环","children":[]}]},{"level":2,"title":"防抖与节流","slug":"防抖与节流","link":"#防抖与节流","children":[{"level":3,"title":"防抖函数","slug":"防抖函数","link":"#防抖函数","children":[]},{"level":3,"title":"节流函数","slug":"节流函数","link":"#节流函数","children":[]}]},{"level":2,"title":"深拷贝与浅拷贝","slug":"深拷贝与浅拷贝","link":"#深拷贝与浅拷贝","children":[{"level":3,"title":"浅拷贝","slug":"浅拷贝","link":"#浅拷贝","children":[]},{"level":3,"title":"深拷贝","slug":"深拷贝","link":"#深拷贝","children":[]},{"level":3,"title":"完整代码","slug":"完整代码","link":"#完整代码","children":[]}]},{"level":2,"title":"事件总线","slug":"事件总线","link":"#事件总线","children":[]}],"relativePath":"note/JavaScriptEnhanced.md","lastUpdated":1676979063000}'),F={name:"note/JavaScriptEnhanced.md"},D=l("",668),i=[D];function A(C,b,u,d,m,h){return n(),a("div",null,i)}const E=s(F,[["render",A]]);export{g as __pageData,E as default};
diff --git a/assets/note_SSR.md.eafce674.js b/assets/note_SSR.md.5b580a05.js
similarity index 99%
rename from assets/note_SSR.md.eafce674.js
rename to assets/note_SSR.md.5b580a05.js
index 2a605641..c5ebc4b7 100644
--- a/assets/note_SSR.md.eafce674.js
+++ b/assets/note_SSR.md.5b580a05.js
@@ -1,4 +1,4 @@
-import{_ as l,o as e,c as i,a as s}from"./app.33820b61.js";const g=JSON.parse('{"title":"服务端渲染(SSR)","description":"","frontmatter":{},"headers":[{"level":2,"title":"邂逅SPA和SSR","slug":"邂逅spa和ssr","link":"#邂逅spa和ssr","children":[{"level":3,"title":"SPA的优点与缺点","slug":"spa的优点与缺点","link":"#spa的优点与缺点","children":[]},{"level":3,"title":"SEO优化","slug":"seo优化","link":"#seo优化","children":[]}]},{"level":2,"title":"服务端渲染 SSR","slug":"服务端渲染-ssr-1","link":"#服务端渲染-ssr-1","children":[{"level":3,"title":"SSR的优点","slug":"ssr的优点","link":"#ssr的优点","children":[]},{"level":3,"title":"SSR的缺点","slug":"ssr的缺点","link":"#ssr的缺点","children":[]},{"level":3,"title":"SSR 解决方案","slug":"ssr-解决方案","link":"#ssr-解决方案","children":[]}]},{"level":2,"title":"静态网站生成 SSG","slug":"静态网站生成-ssg","link":"#静态网站生成-ssg","children":[{"level":3,"title":"SSR与SSG的优势","slug":"ssr与ssg的优势","link":"#ssr与ssg的优势","children":[]},{"level":3,"title":"跨请求状态污染","slug":"跨请求状态污染","link":"#跨请求状态污染","children":[]}]},{"level":2,"title":"Nuxt3 系统学习","slug":"nuxt3-系统学习","link":"#nuxt3-系统学习","children":[{"level":3,"title":"认识Nuxt3","slug":"认识nuxt3","link":"#认识nuxt3","children":[]},{"level":3,"title":"搭建Nuxt3环境","slug":"搭建nuxt3环境","link":"#搭建nuxt3环境","children":[]},{"level":3,"title":"配置 Configuration","slug":"配置-configuration","link":"#配置-configuration","children":[]},{"level":3,"title":"页面与组件 View and Component","slug":"页面与组件-view-and-component","link":"#页面与组件-view-and-component","children":[]},{"level":3,"title":"创建页面","slug":"创建页面","link":"#创建页面","children":[]},{"level":3,"title":"页面布局 Layout","slug":"页面布局-layout","link":"#页面布局-layout","children":[]},{"level":3,"title":"渲染模式","slug":"渲染模式","link":"#渲染模式","children":[]}]}],"relativePath":"note/SSR.md","lastUpdated":1676737739000}'),o={name:"note/SSR.md"},a=s(`

服务端渲染(SSR)

  • 邂逅SPA和SSR
  • Node服务搭建
  • Vue3 + SSR搭建
  • SSR + Hydration 水合
  • Vue SSR + Router
  • Vue SSR + Pinia

邂逅SPA和SSR

我们使用Vue开发的网页一般都是单页面应用程序(SPA Single Page Application)

  • SPA应用是在客户端呈现的,我们称这个渲染过程为CSR(Client Side Rendering)
  • 常见的B端Web应用开发模式,渲染工作在客户端进行,服务器压力较轻,服务器直接返回未经加工的.html文件
  • 所需要的资源(HTML CSS JS等),在一次请求中就加载完成,首屏时间更长,需要额外的首屏优化

与之相对的,就是服务端渲染(SSR Server Side Rendering)

  • SSR并不是什么新鲜的概念,早期的JSP或PHP就已经体现了服务端渲染的原理
  • 但是传统开发模式,代码耦合度较高,不容易维护

于是,同构SSR应运而生,我们称之为BFF(Backend for Frontend 服务于前端的后端)

  • 前后端一体化,一套Vue / React代码在服务器上运行一遍,在到达浏览器又运行一遍。
  • 前后端都参与到渲染中,并且首次渲染出的HTML相同

浏览器请求.html文件 => 服务端运行Vue / React代码并生成.html => 发送.html文件给浏览器 => 浏览器显示网页内容

=> 浏览器加载JS文件 => 绑定DOM事件 客户端渲染接管界面 => 再次跳转路由就是客户端渲染 无需请求后台

SPA的优点与缺点

  • SPA的优点
    • 只需要加载一次 更好的用户体验
      • 只有一个.html文件,页面切换不需要重新加载,所以比传统Web应用程序更快
    • 轻松构建功能丰富的Web应用程序
  • SPA的缺点
    • SPA应用默认只返回一个空HTML文件,不利于SEO
    • 首屏加载资源过大,影响首屏渲染速度
    • 不利于复杂项目构建

SEO优化

  • 语义性HTML标记
    • 标题用 h1,一个页面只应当由一个 h1 标签,副标题用 h2 - h6
    • 不要过度使用 h 标签,多次使用不会增加SEO
    • 段落用 p 标签 列表用 ul 标签,且 li 只放在 ul
  • 每个页面都需要包含标题+内部链接
    • 每个页面对应的title,同一个网站所有页面都有内链可以指向首页
  • 保证链接可供抓取
    • <a href="https://www.example.com" />
    • <a href="/relative/path/file" />
  • meta标签优化:设置description和keywords等
  • 文本标记和img
    • 比如<b><strong>加粗文本的标签,爬虫会关注到该内容
    • img标签添加alt属性,图片加载失败时供爬虫读取alt内容
  • robots.txt 文件,规定爬虫可以访问网址上的哪些页面
  • sitemap.xml 站点地图,在站点地图列出所有网页,确保爬虫不会漏掉某些网页

服务端渲染 SSR

服务端渲染 SSR (Server Side Rendering)

  • 页面是在服务端渲染的,用户每请求一个SSR页面,都会先在服务端渲染
  • 服务端渲染完成后,返回给浏览器呈现,浏览器发现JS脚本,解析脚本,向服务器发起请求,之后网页就可以交互了
    • app = createSSRApp(App) renderToString(app) => App String Html
    • client_bundle.js 客户端通过脚本激活应用程序 让应用程序可以进行交互,这个过程叫水合( Hydration)
  • Vue Nuxt / React Next.js,SSR应用也称为同构应用(server_bundle.js & client_bundle.js)

SSR的优点

  • 更快的首屏渲染速度
    • 浏览器显示静态页面的内容要比JavaScript动态生成的内容快得多
    • 用户访问首页时立刻返回静态页面内容,而不需要等待浏览器先加载完整个SPA应用的JS代码
  • 更好的SEO
    • 爬虫擅长爬取HTML页面,服务端直接返回一个静态的HTML给浏览器
    • 有利于爬虫快速爬取网页内容,并编入索引,有利于SEO
  • SSR 应用程序在 Hydration 之后仍然可以保留Web应用程序的可交互性
    • 如:前端路由、响应式数据、虚拟DOM等

SSR的缺点

  • SSR 通过需要对服务器进行更多的API调用,在服务端渲染需要消耗更多的服务器资源,成本较高
  • 100个人访问这个网站,服务器就要为每个人渲染100次
  • 增加了一定的开发成本,开发者需要关心哪些代码是运行在服务端的,哪些则是运行在浏览器的
  • SSR配置站点的缓存通常会比SPA站点要更复杂

SSR 解决方案

  • 传统方案:PHP JSP ...
  • 从0开始,搭建SSR项目:Node+Webpack+Vue/React
  • 选用现成的框架
    • React Next.js
    • Vue3 + Nuxt3 || Vue2 + Nuxt.js

静态网站生成 SSG

静态网页生成 SSG(Static Site Generate)

  • SSG应用在构建阶段就确定了.html页面的内容
  • 用户访问网站,服务器直接返回.html文件给客户端,相当于一个静态资源
  • 优点
    • 直接返回静态的html文件,有利于SEO
    • 相比于SSR,不需要每次请求都由服务端处理,所以可以大幅减轻服务端压力,也可以将文件放到CDN上优化访问速度
    • 保留了SPA应用的特性,比如前端路由、响应式数据、虚拟DOM等
  • 缺点
    • 如果网站的内容需要更新,那么需要重新构建与部署
    • 只能生成偏静态的页面,不利于与用户的交互,所有用户获取到的页面都是相同的
  • 哪些应用场景:文档站、个人博客、新闻站点等

SSR与SSG的优势

  • 更短的首屏时间
    • 只需要请求一个HTML文件就能展示出页面
    • 虽然在服务端仍然需要调取相关接口,但是服务器-服务器之间的通信远比客户端快,有时甚至是同一台服务器的本地接口
    • 不再需要大量的js文件请求,这就使得SSR/SSG可以拥有更短的首屏时间

跨请求状态污染

  • 在SPA中,整个生命周期只有一个App对象实例/一个Router对象实例/一个Store对象实例

    • 因为每个用户使用SPA时,各自的渲染进程都是在自己的浏览器上独立进行的,这是一种单例模式
  • 然而在SSR的环境下,App模块通常只在

    服务器启动时

    初始化一次,同一个应用模块会在多个服务器请求之间被复用

    • 单例状态对象也会在多个请求之间被复用:
    • 某个用户对共享的单例状态进行修改,那么这个状态可能会意外地泄露给另一位正在请求的用户
    • 我们将这种情况称为:跨请求状态污染
  • 为了避免这种跨请求状态污染,SSR的解决方案是:

    • 在每个请求中,为整个应用创建一个全新的实例,包括后面的Router和Store等实例
    • 带来的缺点就是:需要消耗更多的服务器资源

Nuxt3 系统学习

  • 邂逅Nuxt3
  • Nuxt3 初体验
  • Nuxt3 全局配置
  • Nuxt3 内置组件
  • Nuxt3 样式和资源
  • Nuxt3 页面和导航
  • Nuxt3 动态路由

认识Nuxt3

  • 支持数据双向绑定和组件化:Vue.js
  • 处理客户端导航:Vue Router
  • 支持开发中热模块替换、生产环境代码打包:Webpack5 Vite
  • 兼容旧版浏览器,支持ES6+语法转译:ESBuild
  • 支持开发环境服务器,支持服务端渲染/API接口转发
  • 使用h3实现部署可移植性h3是一个极小的高性能http框架)
    • 如:支持在Serverless、Worker、Node.js环境中运行

搭建Nuxt3环境

使用命令行工具 Nuxi 初始化Nuxt:

  • npx nuxi init project-name
  • pnpm dlx nuxi init project-name
  • npm install -g nuxi && nuxi init project-name

解读脚手架创建的初始化项目的package.json中的脚本:

json
{
+import{_ as l,o as e,c as i,a as s}from"./app.33820b61.js";const g=JSON.parse('{"title":"服务端渲染(SSR)","description":"","frontmatter":{},"headers":[{"level":2,"title":"邂逅SPA和SSR","slug":"邂逅spa和ssr","link":"#邂逅spa和ssr","children":[{"level":3,"title":"SPA的优点与缺点","slug":"spa的优点与缺点","link":"#spa的优点与缺点","children":[]},{"level":3,"title":"SEO优化","slug":"seo优化","link":"#seo优化","children":[]}]},{"level":2,"title":"服务端渲染 SSR","slug":"服务端渲染-ssr-1","link":"#服务端渲染-ssr-1","children":[{"level":3,"title":"SSR的优点","slug":"ssr的优点","link":"#ssr的优点","children":[]},{"level":3,"title":"SSR的缺点","slug":"ssr的缺点","link":"#ssr的缺点","children":[]},{"level":3,"title":"SSR 解决方案","slug":"ssr-解决方案","link":"#ssr-解决方案","children":[]}]},{"level":2,"title":"静态网站生成 SSG","slug":"静态网站生成-ssg","link":"#静态网站生成-ssg","children":[{"level":3,"title":"SSR与SSG的优势","slug":"ssr与ssg的优势","link":"#ssr与ssg的优势","children":[]},{"level":3,"title":"跨请求状态污染","slug":"跨请求状态污染","link":"#跨请求状态污染","children":[]}]},{"level":2,"title":"Nuxt3 系统学习","slug":"nuxt3-系统学习","link":"#nuxt3-系统学习","children":[{"level":3,"title":"认识Nuxt3","slug":"认识nuxt3","link":"#认识nuxt3","children":[]},{"level":3,"title":"搭建Nuxt3环境","slug":"搭建nuxt3环境","link":"#搭建nuxt3环境","children":[]},{"level":3,"title":"配置 Configuration","slug":"配置-configuration","link":"#配置-configuration","children":[]},{"level":3,"title":"页面与组件 View and Component","slug":"页面与组件-view-and-component","link":"#页面与组件-view-and-component","children":[]},{"level":3,"title":"创建页面","slug":"创建页面","link":"#创建页面","children":[]},{"level":3,"title":"页面布局 Layout","slug":"页面布局-layout","link":"#页面布局-layout","children":[]},{"level":3,"title":"渲染模式","slug":"渲染模式","link":"#渲染模式","children":[]}]}],"relativePath":"note/SSR.md","lastUpdated":1676979063000}'),o={name:"note/SSR.md"},a=s(`

服务端渲染(SSR)

  • 邂逅SPA和SSR
  • Node服务搭建
  • Vue3 + SSR搭建
  • SSR + Hydration 水合
  • Vue SSR + Router
  • Vue SSR + Pinia

邂逅SPA和SSR

我们使用Vue开发的网页一般都是单页面应用程序(SPA Single Page Application)

  • SPA应用是在客户端呈现的,我们称这个渲染过程为CSR(Client Side Rendering)
  • 常见的B端Web应用开发模式,渲染工作在客户端进行,服务器压力较轻,服务器直接返回未经加工的.html文件
  • 所需要的资源(HTML CSS JS等),在一次请求中就加载完成,首屏时间更长,需要额外的首屏优化

与之相对的,就是服务端渲染(SSR Server Side Rendering)

  • SSR并不是什么新鲜的概念,早期的JSP或PHP就已经体现了服务端渲染的原理
  • 但是传统开发模式,代码耦合度较高,不容易维护

于是,同构SSR应运而生,我们称之为BFF(Backend for Frontend 服务于前端的后端)

  • 前后端一体化,一套Vue / React代码在服务器上运行一遍,在到达浏览器又运行一遍。
  • 前后端都参与到渲染中,并且首次渲染出的HTML相同

浏览器请求.html文件 => 服务端运行Vue / React代码并生成.html => 发送.html文件给浏览器 => 浏览器显示网页内容

=> 浏览器加载JS文件 => 绑定DOM事件 客户端渲染接管界面 => 再次跳转路由就是客户端渲染 无需请求后台

SPA的优点与缺点

  • SPA的优点
    • 只需要加载一次 更好的用户体验
      • 只有一个.html文件,页面切换不需要重新加载,所以比传统Web应用程序更快
    • 轻松构建功能丰富的Web应用程序
  • SPA的缺点
    • SPA应用默认只返回一个空HTML文件,不利于SEO
    • 首屏加载资源过大,影响首屏渲染速度
    • 不利于复杂项目构建

SEO优化

  • 语义性HTML标记
    • 标题用 h1,一个页面只应当由一个 h1 标签,副标题用 h2 - h6
    • 不要过度使用 h 标签,多次使用不会增加SEO
    • 段落用 p 标签 列表用 ul 标签,且 li 只放在 ul
  • 每个页面都需要包含标题+内部链接
    • 每个页面对应的title,同一个网站所有页面都有内链可以指向首页
  • 保证链接可供抓取
    • <a href="https://www.example.com" />
    • <a href="/relative/path/file" />
  • meta标签优化:设置description和keywords等
  • 文本标记和img
    • 比如<b><strong>加粗文本的标签,爬虫会关注到该内容
    • img标签添加alt属性,图片加载失败时供爬虫读取alt内容
  • robots.txt 文件,规定爬虫可以访问网址上的哪些页面
  • sitemap.xml 站点地图,在站点地图列出所有网页,确保爬虫不会漏掉某些网页

服务端渲染 SSR

服务端渲染 SSR (Server Side Rendering)

  • 页面是在服务端渲染的,用户每请求一个SSR页面,都会先在服务端渲染
  • 服务端渲染完成后,返回给浏览器呈现,浏览器发现JS脚本,解析脚本,向服务器发起请求,之后网页就可以交互了
    • app = createSSRApp(App) renderToString(app) => App String Html
    • client_bundle.js 客户端通过脚本激活应用程序 让应用程序可以进行交互,这个过程叫水合( Hydration)
  • Vue Nuxt / React Next.js,SSR应用也称为同构应用(server_bundle.js & client_bundle.js)

SSR的优点

  • 更快的首屏渲染速度
    • 浏览器显示静态页面的内容要比JavaScript动态生成的内容快得多
    • 用户访问首页时立刻返回静态页面内容,而不需要等待浏览器先加载完整个SPA应用的JS代码
  • 更好的SEO
    • 爬虫擅长爬取HTML页面,服务端直接返回一个静态的HTML给浏览器
    • 有利于爬虫快速爬取网页内容,并编入索引,有利于SEO
  • SSR 应用程序在 Hydration 之后仍然可以保留Web应用程序的可交互性
    • 如:前端路由、响应式数据、虚拟DOM等

SSR的缺点

  • SSR 通过需要对服务器进行更多的API调用,在服务端渲染需要消耗更多的服务器资源,成本较高
  • 100个人访问这个网站,服务器就要为每个人渲染100次
  • 增加了一定的开发成本,开发者需要关心哪些代码是运行在服务端的,哪些则是运行在浏览器的
  • SSR配置站点的缓存通常会比SPA站点要更复杂

SSR 解决方案

  • 传统方案:PHP JSP ...
  • 从0开始,搭建SSR项目:Node+Webpack+Vue/React
  • 选用现成的框架
    • React Next.js
    • Vue3 + Nuxt3 || Vue2 + Nuxt.js

静态网站生成 SSG

静态网页生成 SSG(Static Site Generate)

  • SSG应用在构建阶段就确定了.html页面的内容
  • 用户访问网站,服务器直接返回.html文件给客户端,相当于一个静态资源
  • 优点
    • 直接返回静态的html文件,有利于SEO
    • 相比于SSR,不需要每次请求都由服务端处理,所以可以大幅减轻服务端压力,也可以将文件放到CDN上优化访问速度
    • 保留了SPA应用的特性,比如前端路由、响应式数据、虚拟DOM等
  • 缺点
    • 如果网站的内容需要更新,那么需要重新构建与部署
    • 只能生成偏静态的页面,不利于与用户的交互,所有用户获取到的页面都是相同的
  • 哪些应用场景:文档站、个人博客、新闻站点等

SSR与SSG的优势

  • 更短的首屏时间
    • 只需要请求一个HTML文件就能展示出页面
    • 虽然在服务端仍然需要调取相关接口,但是服务器-服务器之间的通信远比客户端快,有时甚至是同一台服务器的本地接口
    • 不再需要大量的js文件请求,这就使得SSR/SSG可以拥有更短的首屏时间

跨请求状态污染

  • 在SPA中,整个生命周期只有一个App对象实例/一个Router对象实例/一个Store对象实例

    • 因为每个用户使用SPA时,各自的渲染进程都是在自己的浏览器上独立进行的,这是一种单例模式
  • 然而在SSR的环境下,App模块通常只在

    服务器启动时

    初始化一次,同一个应用模块会在多个服务器请求之间被复用

    • 单例状态对象也会在多个请求之间被复用:
    • 某个用户对共享的单例状态进行修改,那么这个状态可能会意外地泄露给另一位正在请求的用户
    • 我们将这种情况称为:跨请求状态污染
  • 为了避免这种跨请求状态污染,SSR的解决方案是:

    • 在每个请求中,为整个应用创建一个全新的实例,包括后面的Router和Store等实例
    • 带来的缺点就是:需要消耗更多的服务器资源

Nuxt3 系统学习

  • 邂逅Nuxt3
  • Nuxt3 初体验
  • Nuxt3 全局配置
  • Nuxt3 内置组件
  • Nuxt3 样式和资源
  • Nuxt3 页面和导航
  • Nuxt3 动态路由

认识Nuxt3

  • 支持数据双向绑定和组件化:Vue.js
  • 处理客户端导航:Vue Router
  • 支持开发中热模块替换、生产环境代码打包:Webpack5 Vite
  • 兼容旧版浏览器,支持ES6+语法转译:ESBuild
  • 支持开发环境服务器,支持服务端渲染/API接口转发
  • 使用h3实现部署可移植性h3是一个极小的高性能http框架)
    • 如:支持在Serverless、Worker、Node.js环境中运行

搭建Nuxt3环境

使用命令行工具 Nuxi 初始化Nuxt:

  • npx nuxi init project-name
  • pnpm dlx nuxi init project-name
  • npm install -g nuxi && nuxi init project-name

解读脚手架创建的初始化项目的package.json中的脚本:

json
{
   "private": true,
   "scripts": {
     "build": "nuxt build",
diff --git a/assets/note_SSR.md.eafce674.lean.js b/assets/note_SSR.md.5b580a05.lean.js
similarity index 94%
rename from assets/note_SSR.md.eafce674.lean.js
rename to assets/note_SSR.md.5b580a05.lean.js
index f4f975f9..7970189e 100644
--- a/assets/note_SSR.md.eafce674.lean.js
+++ b/assets/note_SSR.md.5b580a05.lean.js
@@ -1 +1 @@
-import{_ as l,o as e,c as i,a as s}from"./app.33820b61.js";const g=JSON.parse('{"title":"服务端渲染(SSR)","description":"","frontmatter":{},"headers":[{"level":2,"title":"邂逅SPA和SSR","slug":"邂逅spa和ssr","link":"#邂逅spa和ssr","children":[{"level":3,"title":"SPA的优点与缺点","slug":"spa的优点与缺点","link":"#spa的优点与缺点","children":[]},{"level":3,"title":"SEO优化","slug":"seo优化","link":"#seo优化","children":[]}]},{"level":2,"title":"服务端渲染 SSR","slug":"服务端渲染-ssr-1","link":"#服务端渲染-ssr-1","children":[{"level":3,"title":"SSR的优点","slug":"ssr的优点","link":"#ssr的优点","children":[]},{"level":3,"title":"SSR的缺点","slug":"ssr的缺点","link":"#ssr的缺点","children":[]},{"level":3,"title":"SSR 解决方案","slug":"ssr-解决方案","link":"#ssr-解决方案","children":[]}]},{"level":2,"title":"静态网站生成 SSG","slug":"静态网站生成-ssg","link":"#静态网站生成-ssg","children":[{"level":3,"title":"SSR与SSG的优势","slug":"ssr与ssg的优势","link":"#ssr与ssg的优势","children":[]},{"level":3,"title":"跨请求状态污染","slug":"跨请求状态污染","link":"#跨请求状态污染","children":[]}]},{"level":2,"title":"Nuxt3 系统学习","slug":"nuxt3-系统学习","link":"#nuxt3-系统学习","children":[{"level":3,"title":"认识Nuxt3","slug":"认识nuxt3","link":"#认识nuxt3","children":[]},{"level":3,"title":"搭建Nuxt3环境","slug":"搭建nuxt3环境","link":"#搭建nuxt3环境","children":[]},{"level":3,"title":"配置 Configuration","slug":"配置-configuration","link":"#配置-configuration","children":[]},{"level":3,"title":"页面与组件 View and Component","slug":"页面与组件-view-and-component","link":"#页面与组件-view-and-component","children":[]},{"level":3,"title":"创建页面","slug":"创建页面","link":"#创建页面","children":[]},{"level":3,"title":"页面布局 Layout","slug":"页面布局-layout","link":"#页面布局-layout","children":[]},{"level":3,"title":"渲染模式","slug":"渲染模式","link":"#渲染模式","children":[]}]}],"relativePath":"note/SSR.md","lastUpdated":1676737739000}'),o={name:"note/SSR.md"},a=s("",80),n=[a];function t(d,c,r,p,u,h){return e(),i("div",null,n)}const D=l(o,[["render",t]]);export{g as __pageData,D as default};
+import{_ as l,o as e,c as i,a as s}from"./app.33820b61.js";const g=JSON.parse('{"title":"服务端渲染(SSR)","description":"","frontmatter":{},"headers":[{"level":2,"title":"邂逅SPA和SSR","slug":"邂逅spa和ssr","link":"#邂逅spa和ssr","children":[{"level":3,"title":"SPA的优点与缺点","slug":"spa的优点与缺点","link":"#spa的优点与缺点","children":[]},{"level":3,"title":"SEO优化","slug":"seo优化","link":"#seo优化","children":[]}]},{"level":2,"title":"服务端渲染 SSR","slug":"服务端渲染-ssr-1","link":"#服务端渲染-ssr-1","children":[{"level":3,"title":"SSR的优点","slug":"ssr的优点","link":"#ssr的优点","children":[]},{"level":3,"title":"SSR的缺点","slug":"ssr的缺点","link":"#ssr的缺点","children":[]},{"level":3,"title":"SSR 解决方案","slug":"ssr-解决方案","link":"#ssr-解决方案","children":[]}]},{"level":2,"title":"静态网站生成 SSG","slug":"静态网站生成-ssg","link":"#静态网站生成-ssg","children":[{"level":3,"title":"SSR与SSG的优势","slug":"ssr与ssg的优势","link":"#ssr与ssg的优势","children":[]},{"level":3,"title":"跨请求状态污染","slug":"跨请求状态污染","link":"#跨请求状态污染","children":[]}]},{"level":2,"title":"Nuxt3 系统学习","slug":"nuxt3-系统学习","link":"#nuxt3-系统学习","children":[{"level":3,"title":"认识Nuxt3","slug":"认识nuxt3","link":"#认识nuxt3","children":[]},{"level":3,"title":"搭建Nuxt3环境","slug":"搭建nuxt3环境","link":"#搭建nuxt3环境","children":[]},{"level":3,"title":"配置 Configuration","slug":"配置-configuration","link":"#配置-configuration","children":[]},{"level":3,"title":"页面与组件 View and Component","slug":"页面与组件-view-and-component","link":"#页面与组件-view-and-component","children":[]},{"level":3,"title":"创建页面","slug":"创建页面","link":"#创建页面","children":[]},{"level":3,"title":"页面布局 Layout","slug":"页面布局-layout","link":"#页面布局-layout","children":[]},{"level":3,"title":"渲染模式","slug":"渲染模式","link":"#渲染模式","children":[]}]}],"relativePath":"note/SSR.md","lastUpdated":1676979063000}'),o={name:"note/SSR.md"},a=s("",80),n=[a];function t(d,c,r,p,u,h){return e(),i("div",null,n)}const D=l(o,[["render",t]]);export{g as __pageData,D as default};
diff --git a/assets/project_ClipboardManager_guide_index.md.cbb1b2e8.js b/assets/project_ClipboardManager_guide_index.md.caf90979.js
similarity index 99%
rename from assets/project_ClipboardManager_guide_index.md.cbb1b2e8.js
rename to assets/project_ClipboardManager_guide_index.md.caf90979.js
index e1a41710..aa9e3a57 100644
--- a/assets/project_ClipboardManager_guide_index.md.cbb1b2e8.js
+++ b/assets/project_ClipboardManager_guide_index.md.caf90979.js
@@ -1,4 +1,4 @@
-import{_ as l,r as p,o as c,c as t,b as s,d as e,e as n,a as o}from"./app.33820b61.js";const r="/assets/gi1.b601202a.png",d="/assets/gi2.e2b1f9d9.png",i="/assets/gi3.c83cee76.png",D="/assets/gi3-2.8cc1f8a9.png",h="/assets/gi3-3.47dffc9b.png",u="/assets/sign-mac.2c3e272f.png",F="/assets/sign-mac-2.5861d44c.png",y="/assets/mac-chmod.bf888724.jpg",_="/assets/guide-jianguo-1.a7e6fa82.png",g="/assets/guide-jianguo-2.14924b1b.png",C="/assets/gi4.e4051a3e.png",m="/assets/gi5.f517b425.png",$=JSON.parse('{"title":"使用指南","description":"","frontmatter":{},"headers":[{"level":2,"title":"快捷键一览","slug":"快捷键一览","link":"#快捷键一览","children":[]},{"level":2,"title":"如何手动安装clipboard-event-handler","slug":"如何手动安装clipboard-event-handler","link":"#如何手动安装clipboard-event-handler","children":[{"level":3,"title":"1. 下载监听程序","slug":"_1-下载监听程序","link":"#_1-下载监听程序","children":[]},{"level":3,"title":"2. 找到剪贴板数据文件所在目录","slug":"_2-找到剪贴板数据文件所在目录","link":"#_2-找到剪贴板数据文件所在目录","children":[]},{"level":3,"title":"3. 将监听程序拷贝到目录中","slug":"_3-将监听程序拷贝到目录中","link":"#_3-将监听程序拷贝到目录中","children":[]},{"level":3,"title":"4. 【重要】注意事项","slug":"_4-【重要】注意事项","link":"#_4-【重要】注意事项","children":[]}]},{"level":2,"title":"如何实现多端同步","slug":"如何实现多端同步","link":"#如何实现多端同步","children":[{"level":3,"title":"WebDav同步","slug":"webdav同步","link":"#webdav同步","children":[]},{"level":3,"title":"坚果云同步文件夹","slug":"坚果云同步文件夹","link":"#坚果云同步文件夹","children":[]}]},{"level":2,"title":"如何迁移数据","slug":"如何迁移数据","link":"#如何迁移数据","children":[]},{"level":2,"title":"如何创造自己的功能按钮","slug":"如何创造自己的功能按钮","link":"#如何创造自己的功能按钮","children":[]}],"relativePath":"project/ClipboardManager/guide/index.md","lastUpdated":1676737739000}'),b={name:"project/ClipboardManager/guide/index.md"},A=s("h1",{id:"使用指南",tabindex:"-1"},[e("使用指南 "),s("a",{class:"header-anchor",href:"#使用指南","aria-hidden":"true"},"#")],-1),v=s("h2",{id:"快捷键一览",tabindex:"-1"},[e("快捷键一览 "),s("a",{class:"header-anchor",href:"#快捷键一览","aria-hidden":"true"},"#")],-1),q=o("
  • Shift进入多选模式 按下空格连续向下选择 支持跨标签合并复制/粘贴
  • 鼠标左键复制并粘贴 鼠标右键仅复制
  • 选中历史记录 按下直接粘贴 Ctrl+C仅复制
  • 切换分类 Tab键连续切换分类
  • Ctrl+数字键快速粘贴 Alt+数字键快速复制
  • 输入任意字母或数字/Ctrl+F聚焦搜索框并输入 支持使用空格同时检索多个关键词
  • ",6),f=s("code",null,"Ctrl/Command+鼠标左键",-1),x=o('

    如何手动安装clipboard-event-handler

    新版 超级剪贴板 对剪贴板内容更新事件的监听,依赖于可执行文件:

    • Windows系统: clipboard-event-handler-win32.exe
    • Linux系统: clipboard-event-handler-linux
    • MacOS系统: clipboard-event-handler-mac

    插件每次启动时,将自动检查剪贴板数据文件所在目录下是否存在剪贴板监听程序,如存在,则使用性能更优秀的新的监听策略,如不存在,则仍然使用旧的策略。


    1. 下载监听程序

    点击此处(百度网盘)或访问node-clipboard-event手动下载对应系统的文件,并将其移动到剪贴板数据文件所在目录

    插件使用的二进制文件拷贝自node-clipboard-event,请避免从其它不可信的来源下载文件,并在下载文件后比较哈希,有能力的也可以从仓库源代码自行编译

    2. 找到剪贴板数据文件所在目录

    进入插件设置页(右上角💡按钮),打开插件数据文件所在路径:

    3. 将监听程序拷贝到目录中

    Windows:

    Linux:

    Mac:

    4. 【重要】注意事项

    MacOS需要特殊配置

    MacOS拷贝完成后需要对插件进行签名&授权才能正常使用具体步骤如下

    1. 签名

    打开终端输入以下命令

    sh
    sudo codesign --force --deep --sign - 
    +import{_ as l,r as p,o as c,c as t,b as s,d as e,e as n,a as o}from"./app.33820b61.js";const r="/assets/gi1.b601202a.png",d="/assets/gi2.e2b1f9d9.png",i="/assets/gi3.c83cee76.png",D="/assets/gi3-2.8cc1f8a9.png",h="/assets/gi3-3.47dffc9b.png",u="/assets/sign-mac.2c3e272f.png",F="/assets/sign-mac-2.5861d44c.png",y="/assets/mac-chmod.bf888724.jpg",_="/assets/guide-jianguo-1.a7e6fa82.png",g="/assets/guide-jianguo-2.14924b1b.png",C="/assets/gi4.e4051a3e.png",m="/assets/gi5.f517b425.png",$=JSON.parse('{"title":"使用指南","description":"","frontmatter":{},"headers":[{"level":2,"title":"快捷键一览","slug":"快捷键一览","link":"#快捷键一览","children":[]},{"level":2,"title":"如何手动安装clipboard-event-handler","slug":"如何手动安装clipboard-event-handler","link":"#如何手动安装clipboard-event-handler","children":[{"level":3,"title":"1. 下载监听程序","slug":"_1-下载监听程序","link":"#_1-下载监听程序","children":[]},{"level":3,"title":"2. 找到剪贴板数据文件所在目录","slug":"_2-找到剪贴板数据文件所在目录","link":"#_2-找到剪贴板数据文件所在目录","children":[]},{"level":3,"title":"3. 将监听程序拷贝到目录中","slug":"_3-将监听程序拷贝到目录中","link":"#_3-将监听程序拷贝到目录中","children":[]},{"level":3,"title":"4. 【重要】注意事项","slug":"_4-【重要】注意事项","link":"#_4-【重要】注意事项","children":[]}]},{"level":2,"title":"如何实现多端同步","slug":"如何实现多端同步","link":"#如何实现多端同步","children":[{"level":3,"title":"WebDav同步","slug":"webdav同步","link":"#webdav同步","children":[]},{"level":3,"title":"坚果云同步文件夹","slug":"坚果云同步文件夹","link":"#坚果云同步文件夹","children":[]}]},{"level":2,"title":"如何迁移数据","slug":"如何迁移数据","link":"#如何迁移数据","children":[]},{"level":2,"title":"如何创造自己的功能按钮","slug":"如何创造自己的功能按钮","link":"#如何创造自己的功能按钮","children":[]}],"relativePath":"project/ClipboardManager/guide/index.md","lastUpdated":1676979063000}'),b={name:"project/ClipboardManager/guide/index.md"},A=s("h1",{id:"使用指南",tabindex:"-1"},[e("使用指南 "),s("a",{class:"header-anchor",href:"#使用指南","aria-hidden":"true"},"#")],-1),v=s("h2",{id:"快捷键一览",tabindex:"-1"},[e("快捷键一览 "),s("a",{class:"header-anchor",href:"#快捷键一览","aria-hidden":"true"},"#")],-1),q=o("
  • Shift进入多选模式 按下空格连续向下选择 支持跨标签合并复制/粘贴
  • 鼠标左键复制并粘贴 鼠标右键仅复制
  • 选中历史记录 按下直接粘贴 Ctrl+C仅复制
  • 切换分类 Tab键连续切换分类
  • Ctrl+数字键快速粘贴 Alt+数字键快速复制
  • 输入任意字母或数字/Ctrl+F聚焦搜索框并输入 支持使用空格同时检索多个关键词
  • ",6),f=s("code",null,"Ctrl/Command+鼠标左键",-1),x=o('

    如何手动安装clipboard-event-handler

    新版 超级剪贴板 对剪贴板内容更新事件的监听,依赖于可执行文件:

    • Windows系统: clipboard-event-handler-win32.exe
    • Linux系统: clipboard-event-handler-linux
    • MacOS系统: clipboard-event-handler-mac

    插件每次启动时,将自动检查剪贴板数据文件所在目录下是否存在剪贴板监听程序,如存在,则使用性能更优秀的新的监听策略,如不存在,则仍然使用旧的策略。


    1. 下载监听程序

    点击此处(百度网盘)或访问node-clipboard-event手动下载对应系统的文件,并将其移动到剪贴板数据文件所在目录

    插件使用的二进制文件拷贝自node-clipboard-event,请避免从其它不可信的来源下载文件,并在下载文件后比较哈希,有能力的也可以从仓库源代码自行编译

    2. 找到剪贴板数据文件所在目录

    进入插件设置页(右上角💡按钮),打开插件数据文件所在路径:

    3. 将监听程序拷贝到目录中

    Windows:

    Linux:

    Mac:

    4. 【重要】注意事项

    MacOS需要特殊配置

    MacOS拷贝完成后需要对插件进行签名&授权才能正常使用具体步骤如下

    1. 签名

    打开终端输入以下命令

    sh
    sudo codesign --force --deep --sign - 
     

    然后将此目录中的clipboard-event-handler-mac文件拖入终端执行命令

    2. 授权

    左上角🍎 -> 系统偏好设置 -> 安全性与隐私 -> 通用 -> 点击允许

    监听程序不生效如何排查?

    请务必完整按照教程完成安装,如果程序仍未生效,请按照如下方式排查:

    • 监听程序拷贝完成后,需要重启插件方可生效
    • 设置页剪贴板监听程序状态选项是否为已安装
    • 系统进程管理器中是否存在clipboard-event-handler-xxxxx的进程

    使用中遇到任何问题,请尝试通过论坛或加入QQ群反馈

    如何实现多端同步

    ',35),E={id:"webdav同步",tabindex:"-1"},k=s("a",{class:"header-anchor",href:"#webdav同步","aria-hidden":"true"},"#",-1),w=s("div",{class:"tip custom-block"},[s("p",{class:"custom-block-title"},"TIP"),s("p",null,[e("自"),s("code",null,"v2.0.0"),e("起,可以通过开通插件会员启用"),s("strong",null,"WebDav同步功能")])],-1),T=s("p",null,[e("👉👉👉"),s("a",{href:"./../vip/#webdav同步功能"},"插件会员/WebDav同步功能"),e("👈👈👈")],-1),S={id:"坚果云同步文件夹",tabindex:"-1"},j=s("a",{class:"header-anchor",href:"#坚果云同步文件夹","aria-hidden":"true"},"#",-1),B=o('

    WARNING

    以下方法仅适用于v2.0.0之前的版本

    数据库文件默认是直接存放在用户文件夹根目录下的,如果需要使用同步功能,请使用插件内提供的数据库路径自定义功能,将数据库路径改为其他路径,而后才能通过下文中讲述的同步文件夹实现云同步。

    坚果云官网安装好软件后,找到_utools_clipboard_manager_storage文件所在的目录

    右键目录,坚果云/同步该文件夹,将此文件夹加入到坚果云的同步服务中

    这样,每次剪贴板内容更新都将自动触发坚果云的同步服务,将剪贴板数据同步到云端

    其他安装了坚果云的设备也将自动同步更新

    如何迁移数据

    剪贴板数据默认存放在

    • Windows Linux用户:{home}\\_utools_clipboard_manager_storage
    • Mac用户:{userData}\\_utools_clipboard_manager_storage

    也可以在设置页中点击按钮打开数据库路径。要手动迁移数据,只需要在新设备上运行一次插件,而后将原设备上的数据文件拷贝并替换新设备中的数据文件即可

    如何创造自己的功能按钮

    v1.4.0起,插件为用户提供了自定义功能按钮的能力

    这让超级剪贴板真正变得“超级”起来,用户可以通过编写json实现携带数据跳转到任何其他插件,这项功能给超级剪贴板带来了无限可能。

    插件中,默认内置了若干使用样例:

    • 讯飞OCR识别
    • 百度搜索
    • 百度识图
    • 统计文本字数
    • 颜色管理
    • 识别图片中二维码
    • 上传到图床
    • 翻译

    下面我将从这些样例出发对这项功能做简单介绍:

    这项功能的原理是utools.redirect(),在不分离插件的情况下,在不同插件之间的跳转体验是连贯的。

    百度搜索为例,是通过网页快开提供的关键词实现的,我们可以编写以下json:

    json
    {
       "id": "custom.1663490859",
       "title": "百度搜索",
    diff --git a/assets/project_ClipboardManager_guide_index.md.cbb1b2e8.lean.js b/assets/project_ClipboardManager_guide_index.md.caf90979.lean.js
    similarity index 98%
    rename from assets/project_ClipboardManager_guide_index.md.cbb1b2e8.lean.js
    rename to assets/project_ClipboardManager_guide_index.md.caf90979.lean.js
    index 08f677b8..9db8e4a5 100644
    --- a/assets/project_ClipboardManager_guide_index.md.cbb1b2e8.lean.js
    +++ b/assets/project_ClipboardManager_guide_index.md.caf90979.lean.js
    @@ -1 +1 @@
    -import{_ as l,r as p,o as c,c as t,b as s,d as e,e as n,a as o}from"./app.33820b61.js";const r="/assets/gi1.b601202a.png",d="/assets/gi2.e2b1f9d9.png",i="/assets/gi3.c83cee76.png",D="/assets/gi3-2.8cc1f8a9.png",h="/assets/gi3-3.47dffc9b.png",u="/assets/sign-mac.2c3e272f.png",F="/assets/sign-mac-2.5861d44c.png",y="/assets/mac-chmod.bf888724.jpg",_="/assets/guide-jianguo-1.a7e6fa82.png",g="/assets/guide-jianguo-2.14924b1b.png",C="/assets/gi4.e4051a3e.png",m="/assets/gi5.f517b425.png",$=JSON.parse('{"title":"使用指南","description":"","frontmatter":{},"headers":[{"level":2,"title":"快捷键一览","slug":"快捷键一览","link":"#快捷键一览","children":[]},{"level":2,"title":"如何手动安装clipboard-event-handler","slug":"如何手动安装clipboard-event-handler","link":"#如何手动安装clipboard-event-handler","children":[{"level":3,"title":"1. 下载监听程序","slug":"_1-下载监听程序","link":"#_1-下载监听程序","children":[]},{"level":3,"title":"2. 找到剪贴板数据文件所在目录","slug":"_2-找到剪贴板数据文件所在目录","link":"#_2-找到剪贴板数据文件所在目录","children":[]},{"level":3,"title":"3. 将监听程序拷贝到目录中","slug":"_3-将监听程序拷贝到目录中","link":"#_3-将监听程序拷贝到目录中","children":[]},{"level":3,"title":"4. 【重要】注意事项","slug":"_4-【重要】注意事项","link":"#_4-【重要】注意事项","children":[]}]},{"level":2,"title":"如何实现多端同步","slug":"如何实现多端同步","link":"#如何实现多端同步","children":[{"level":3,"title":"WebDav同步","slug":"webdav同步","link":"#webdav同步","children":[]},{"level":3,"title":"坚果云同步文件夹","slug":"坚果云同步文件夹","link":"#坚果云同步文件夹","children":[]}]},{"level":2,"title":"如何迁移数据","slug":"如何迁移数据","link":"#如何迁移数据","children":[]},{"level":2,"title":"如何创造自己的功能按钮","slug":"如何创造自己的功能按钮","link":"#如何创造自己的功能按钮","children":[]}],"relativePath":"project/ClipboardManager/guide/index.md","lastUpdated":1676737739000}'),b={name:"project/ClipboardManager/guide/index.md"},A=s("h1",{id:"使用指南",tabindex:"-1"},[e("使用指南 "),s("a",{class:"header-anchor",href:"#使用指南","aria-hidden":"true"},"#")],-1),v=s("h2",{id:"快捷键一览",tabindex:"-1"},[e("快捷键一览 "),s("a",{class:"header-anchor",href:"#快捷键一览","aria-hidden":"true"},"#")],-1),q=o("",6),f=s("code",null,"Ctrl/Command+鼠标左键",-1),x=o("",35),E={id:"webdav同步",tabindex:"-1"},k=s("a",{class:"header-anchor",href:"#webdav同步","aria-hidden":"true"},"#",-1),w=s("div",{class:"tip custom-block"},[s("p",{class:"custom-block-title"},"TIP"),s("p",null,[e("自"),s("code",null,"v2.0.0"),e("起,可以通过开通插件会员启用"),s("strong",null,"WebDav同步功能")])],-1),T=s("p",null,[e("👉👉👉"),s("a",{href:"./../vip/#webdav同步功能"},"插件会员/WebDav同步功能"),e("👈👈👈")],-1),S={id:"坚果云同步文件夹",tabindex:"-1"},j=s("a",{class:"header-anchor",href:"#坚果云同步文件夹","aria-hidden":"true"},"#",-1),B=o("",28);function N(V,I,W,P,M,O){const a=p("Badge");return c(),t("div",null,[A,v,s("ul",null,[q,s("li",null,[f,e("点击文本/图片/文件 直接进入预览/打开所在文件夹 "),n(a,{type:"warning",text:"插件会员"})])]),x,s("h3",E,[e("WebDav同步 "),n(a,{type:"tip",text:"^2.0.0"}),e(),k]),w,T,s("h3",S,[e("坚果云同步文件夹 "),n(a,{type:"warning",text:"仅旧版本"}),e(),j]),B])}const L=l(b,[["render",N]]);export{$ as __pageData,L as default};
    +import{_ as l,r as p,o as c,c as t,b as s,d as e,e as n,a as o}from"./app.33820b61.js";const r="/assets/gi1.b601202a.png",d="/assets/gi2.e2b1f9d9.png",i="/assets/gi3.c83cee76.png",D="/assets/gi3-2.8cc1f8a9.png",h="/assets/gi3-3.47dffc9b.png",u="/assets/sign-mac.2c3e272f.png",F="/assets/sign-mac-2.5861d44c.png",y="/assets/mac-chmod.bf888724.jpg",_="/assets/guide-jianguo-1.a7e6fa82.png",g="/assets/guide-jianguo-2.14924b1b.png",C="/assets/gi4.e4051a3e.png",m="/assets/gi5.f517b425.png",$=JSON.parse('{"title":"使用指南","description":"","frontmatter":{},"headers":[{"level":2,"title":"快捷键一览","slug":"快捷键一览","link":"#快捷键一览","children":[]},{"level":2,"title":"如何手动安装clipboard-event-handler","slug":"如何手动安装clipboard-event-handler","link":"#如何手动安装clipboard-event-handler","children":[{"level":3,"title":"1. 下载监听程序","slug":"_1-下载监听程序","link":"#_1-下载监听程序","children":[]},{"level":3,"title":"2. 找到剪贴板数据文件所在目录","slug":"_2-找到剪贴板数据文件所在目录","link":"#_2-找到剪贴板数据文件所在目录","children":[]},{"level":3,"title":"3. 将监听程序拷贝到目录中","slug":"_3-将监听程序拷贝到目录中","link":"#_3-将监听程序拷贝到目录中","children":[]},{"level":3,"title":"4. 【重要】注意事项","slug":"_4-【重要】注意事项","link":"#_4-【重要】注意事项","children":[]}]},{"level":2,"title":"如何实现多端同步","slug":"如何实现多端同步","link":"#如何实现多端同步","children":[{"level":3,"title":"WebDav同步","slug":"webdav同步","link":"#webdav同步","children":[]},{"level":3,"title":"坚果云同步文件夹","slug":"坚果云同步文件夹","link":"#坚果云同步文件夹","children":[]}]},{"level":2,"title":"如何迁移数据","slug":"如何迁移数据","link":"#如何迁移数据","children":[]},{"level":2,"title":"如何创造自己的功能按钮","slug":"如何创造自己的功能按钮","link":"#如何创造自己的功能按钮","children":[]}],"relativePath":"project/ClipboardManager/guide/index.md","lastUpdated":1676979063000}'),b={name:"project/ClipboardManager/guide/index.md"},A=s("h1",{id:"使用指南",tabindex:"-1"},[e("使用指南 "),s("a",{class:"header-anchor",href:"#使用指南","aria-hidden":"true"},"#")],-1),v=s("h2",{id:"快捷键一览",tabindex:"-1"},[e("快捷键一览 "),s("a",{class:"header-anchor",href:"#快捷键一览","aria-hidden":"true"},"#")],-1),q=o("",6),f=s("code",null,"Ctrl/Command+鼠标左键",-1),x=o("",35),E={id:"webdav同步",tabindex:"-1"},k=s("a",{class:"header-anchor",href:"#webdav同步","aria-hidden":"true"},"#",-1),w=s("div",{class:"tip custom-block"},[s("p",{class:"custom-block-title"},"TIP"),s("p",null,[e("自"),s("code",null,"v2.0.0"),e("起,可以通过开通插件会员启用"),s("strong",null,"WebDav同步功能")])],-1),T=s("p",null,[e("👉👉👉"),s("a",{href:"./../vip/#webdav同步功能"},"插件会员/WebDav同步功能"),e("👈👈👈")],-1),S={id:"坚果云同步文件夹",tabindex:"-1"},j=s("a",{class:"header-anchor",href:"#坚果云同步文件夹","aria-hidden":"true"},"#",-1),B=o("",28);function N(V,I,W,P,M,O){const a=p("Badge");return c(),t("div",null,[A,v,s("ul",null,[q,s("li",null,[f,e("点击文本/图片/文件 直接进入预览/打开所在文件夹 "),n(a,{type:"warning",text:"插件会员"})])]),x,s("h3",E,[e("WebDav同步 "),n(a,{type:"tip",text:"^2.0.0"}),e(),k]),w,T,s("h3",S,[e("坚果云同步文件夹 "),n(a,{type:"warning",text:"仅旧版本"}),e(),j]),B])}const L=l(b,[["render",N]]);export{$ as __pageData,L as default};
    diff --git a/assets/project_ClipboardManager_index.md.c8cba791.js b/assets/project_ClipboardManager_index.md.fcacbc6c.js
    similarity index 98%
    rename from assets/project_ClipboardManager_index.md.c8cba791.js
    rename to assets/project_ClipboardManager_index.md.fcacbc6c.js
    index d380947d..6fc52e3b 100644
    --- a/assets/project_ClipboardManager_index.md.c8cba791.js
    +++ b/assets/project_ClipboardManager_index.md.fcacbc6c.js
    @@ -1 +1 @@
    -import{r as e,o as d,c as a,e as o,n as i,g as l,a as t}from"./app.33820b61.js";const g="/assets/logo.98e788ed.png",_="/assets/11.3cd0cf4e.png",p="/assets/22.8fe09229.png",m="/assets/33.63eddf1e.png",h="/assets/44.a788d6b3.png",u="/assets/55.9e8a964d.png",f="/assets/66.54616de1.png",b="/assets/77.2791123e.png",T=t('

    🔰 开始使用

    首次安装需要设置“跟随主程序同时启动”

    • ✅ 监听剪贴板并持续将新内容更新到本地磁盘 数据读写完全本地化
    • ✅ 快速收藏/转存/分词/复制/删除/打开文件&目标文件夹
    • ✅ 功能按钮 定义无限可能 OCR识别 百度搜索 百度识图 统计文本字数 颜色管理 识别图片中二维码 上传到图床 翻译
    • 鼠标左键 复制并粘贴 鼠标右键 仅复制
    • ✅ 按下Shift空格进入多选模式 连续选择多条内容合并复制 支持跨标签合并复制/粘贴
    • ✅ 键盘 选中历史记录,按下回车直接粘贴
    • ✅ 键盘 切换分类 Tab键连续切换分类
    • ✅ 使用 Ctrl/Alt+数字键 快速粘贴
    • ✅ 插件内输入任意字母或数字自动聚焦搜索框 支持使用空格同时检索多个关键词
    • 智慧分词 快速拖选指定内容 超级粘贴 直接转存为文件
    • ✅ 优雅的界面动效与交互 跟随系统的深色模式
    • ✅ 优秀的剪贴板监听性能 强大的自定义功能按钮 自搭建多端同步 ···
    ',3),S=t('

    📚 安装方式

    催更群 769115389 Github

    ',4),P=JSON.parse('{"title":"超级剪贴板","description":"","frontmatter":{"title":"超级剪贴板","navbar":false},"headers":[{"level":2,"title":"🔰 开始使用","slug":"🔰-开始使用","link":"#🔰-开始使用","children":[]},{"level":2,"title":"📚 安装方式","slug":"📚-安装方式","link":"#📚-安装方式","children":[]}],"relativePath":"project/ClipboardManager/index.md","lastUpdated":1676737739000}'),C={name:"project/ClipboardManager/index.md"},A=Object.assign(C,{setup(k){const c={subTitle:"✨ 强大的剪贴板管理工具。",logo:g,linkList:[{content:"⭐ 开源代码",target:"https://github.com/ZiuChen/ClipboardManager"},{content:"🚀 使用指南",target:"./guide/"},{content:"🌎 疑难解答",target:"./statement/"},{content:"👑 插件会员",target:"./vip/"},{content:"🚚 更新日志",target:"./log/"}]},s=[{src:_},{src:p},{src:m},{src:h},{src:u},{src:f},{src:b}];return(q,I)=>{const r=e("Title"),n=e("ImgSlider");return d(),a("div",null,[o(r,i(l(c)),null,16),T,o(n,{imgSliderList:s}),S])}}});export{P as __pageData,A as default}; +import{r as e,o as d,c as a,e as o,n as i,g as l,a as t}from"./app.33820b61.js";const g="/assets/logo.98e788ed.png",_="/assets/11.3cd0cf4e.png",p="/assets/22.8fe09229.png",m="/assets/33.63eddf1e.png",h="/assets/44.a788d6b3.png",u="/assets/55.9e8a964d.png",f="/assets/66.54616de1.png",b="/assets/77.2791123e.png",T=t('

    🔰 开始使用

    首次安装需要设置“跟随主程序同时启动”

    • ✅ 监听剪贴板并持续将新内容更新到本地磁盘 数据读写完全本地化
    • ✅ 快速收藏/转存/分词/复制/删除/打开文件&目标文件夹
    • ✅ 功能按钮 定义无限可能 OCR识别 百度搜索 百度识图 统计文本字数 颜色管理 识别图片中二维码 上传到图床 翻译
    • 鼠标左键 复制并粘贴 鼠标右键 仅复制
    • ✅ 按下Shift空格进入多选模式 连续选择多条内容合并复制 支持跨标签合并复制/粘贴
    • ✅ 键盘 选中历史记录,按下回车直接粘贴
    • ✅ 键盘 切换分类 Tab键连续切换分类
    • ✅ 使用 Ctrl/Alt+数字键 快速粘贴
    • ✅ 插件内输入任意字母或数字自动聚焦搜索框 支持使用空格同时检索多个关键词
    • 智慧分词 快速拖选指定内容 超级粘贴 直接转存为文件
    • ✅ 优雅的界面动效与交互 跟随系统的深色模式
    • ✅ 优秀的剪贴板监听性能 强大的自定义功能按钮 自搭建多端同步 ···
    ',3),S=t('

    📚 安装方式

    催更群 769115389 Github

    ',4),P=JSON.parse('{"title":"超级剪贴板","description":"","frontmatter":{"title":"超级剪贴板","navbar":false},"headers":[{"level":2,"title":"🔰 开始使用","slug":"🔰-开始使用","link":"#🔰-开始使用","children":[]},{"level":2,"title":"📚 安装方式","slug":"📚-安装方式","link":"#📚-安装方式","children":[]}],"relativePath":"project/ClipboardManager/index.md","lastUpdated":1676979063000}'),C={name:"project/ClipboardManager/index.md"},A=Object.assign(C,{setup(k){const c={subTitle:"✨ 强大的剪贴板管理工具。",logo:g,linkList:[{content:"⭐ 开源代码",target:"https://github.com/ZiuChen/ClipboardManager"},{content:"🚀 使用指南",target:"./guide/"},{content:"🌎 疑难解答",target:"./statement/"},{content:"👑 插件会员",target:"./vip/"},{content:"🚚 更新日志",target:"./log/"}]},s=[{src:_},{src:p},{src:m},{src:h},{src:u},{src:f},{src:b}];return(q,I)=>{const r=e("Title"),n=e("ImgSlider");return d(),a("div",null,[o(r,i(l(c)),null,16),T,o(n,{imgSliderList:s}),S])}}});export{P as __pageData,A as default}; diff --git a/assets/project_ClipboardManager_index.md.c8cba791.lean.js b/assets/project_ClipboardManager_index.md.fcacbc6c.lean.js similarity index 95% rename from assets/project_ClipboardManager_index.md.c8cba791.lean.js rename to assets/project_ClipboardManager_index.md.fcacbc6c.lean.js index 92d62aa9..6b9bad22 100644 --- a/assets/project_ClipboardManager_index.md.c8cba791.lean.js +++ b/assets/project_ClipboardManager_index.md.fcacbc6c.lean.js @@ -1 +1 @@ -import{r as e,o as d,c as a,e as o,n as i,g as l,a as t}from"./app.33820b61.js";const g="/assets/logo.98e788ed.png",_="/assets/11.3cd0cf4e.png",p="/assets/22.8fe09229.png",m="/assets/33.63eddf1e.png",h="/assets/44.a788d6b3.png",u="/assets/55.9e8a964d.png",f="/assets/66.54616de1.png",b="/assets/77.2791123e.png",T=t("",3),S=t("",4),P=JSON.parse('{"title":"超级剪贴板","description":"","frontmatter":{"title":"超级剪贴板","navbar":false},"headers":[{"level":2,"title":"🔰 开始使用","slug":"🔰-开始使用","link":"#🔰-开始使用","children":[]},{"level":2,"title":"📚 安装方式","slug":"📚-安装方式","link":"#📚-安装方式","children":[]}],"relativePath":"project/ClipboardManager/index.md","lastUpdated":1676737739000}'),C={name:"project/ClipboardManager/index.md"},A=Object.assign(C,{setup(k){const c={subTitle:"✨ 强大的剪贴板管理工具。",logo:g,linkList:[{content:"⭐ 开源代码",target:"https://github.com/ZiuChen/ClipboardManager"},{content:"🚀 使用指南",target:"./guide/"},{content:"🌎 疑难解答",target:"./statement/"},{content:"👑 插件会员",target:"./vip/"},{content:"🚚 更新日志",target:"./log/"}]},s=[{src:_},{src:p},{src:m},{src:h},{src:u},{src:f},{src:b}];return(q,I)=>{const r=e("Title"),n=e("ImgSlider");return d(),a("div",null,[o(r,i(l(c)),null,16),T,o(n,{imgSliderList:s}),S])}}});export{P as __pageData,A as default}; +import{r as e,o as d,c as a,e as o,n as i,g as l,a as t}from"./app.33820b61.js";const g="/assets/logo.98e788ed.png",_="/assets/11.3cd0cf4e.png",p="/assets/22.8fe09229.png",m="/assets/33.63eddf1e.png",h="/assets/44.a788d6b3.png",u="/assets/55.9e8a964d.png",f="/assets/66.54616de1.png",b="/assets/77.2791123e.png",T=t("",3),S=t("",4),P=JSON.parse('{"title":"超级剪贴板","description":"","frontmatter":{"title":"超级剪贴板","navbar":false},"headers":[{"level":2,"title":"🔰 开始使用","slug":"🔰-开始使用","link":"#🔰-开始使用","children":[]},{"level":2,"title":"📚 安装方式","slug":"📚-安装方式","link":"#📚-安装方式","children":[]}],"relativePath":"project/ClipboardManager/index.md","lastUpdated":1676979063000}'),C={name:"project/ClipboardManager/index.md"},A=Object.assign(C,{setup(k){const c={subTitle:"✨ 强大的剪贴板管理工具。",logo:g,linkList:[{content:"⭐ 开源代码",target:"https://github.com/ZiuChen/ClipboardManager"},{content:"🚀 使用指南",target:"./guide/"},{content:"🌎 疑难解答",target:"./statement/"},{content:"👑 插件会员",target:"./vip/"},{content:"🚚 更新日志",target:"./log/"}]},s=[{src:_},{src:p},{src:m},{src:h},{src:u},{src:f},{src:b}];return(q,I)=>{const r=e("Title"),n=e("ImgSlider");return d(),a("div",null,[o(r,i(l(c)),null,16),T,o(n,{imgSliderList:s}),S])}}});export{P as __pageData,A as default}; diff --git a/assets/project_ClipboardManager_log_index.md.4ee5fe53.js b/assets/project_ClipboardManager_log_index.md.4ee5fe53.js deleted file mode 100644 index 7422aa8f..00000000 --- a/assets/project_ClipboardManager_log_index.md.4ee5fe53.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,o as l,c as i,a}from"./app.33820b61.js";const x=JSON.parse('{"title":"更新日志","description":"","frontmatter":{},"headers":[{"level":2,"title":"v2.0.5","slug":"v2-0-5","link":"#v2-0-5","children":[]},{"level":2,"title":"v2.0.4","slug":"v2-0-4","link":"#v2-0-4","children":[]},{"level":2,"title":"v2.0.3","slug":"v2-0-3","link":"#v2-0-3","children":[]},{"level":2,"title":"v2.0.2","slug":"v2-0-2","link":"#v2-0-2","children":[]},{"level":2,"title":"v2.0.1","slug":"v2-0-1","link":"#v2-0-1","children":[]},{"level":2,"title":"v2.0.0","slug":"v2-0-0","link":"#v2-0-0","children":[]},{"level":2,"title":"v1.4.7","slug":"v1-4-7","link":"#v1-4-7","children":[]},{"level":2,"title":"v1.4.6","slug":"v1-4-6","link":"#v1-4-6","children":[]},{"level":2,"title":"v1.4.5","slug":"v1-4-5","link":"#v1-4-5","children":[]},{"level":2,"title":"v1.4.4","slug":"v1-4-4","link":"#v1-4-4","children":[]},{"level":2,"title":"v1.4.3","slug":"v1-4-3","link":"#v1-4-3","children":[]},{"level":2,"title":"v1.4.2","slug":"v1-4-2","link":"#v1-4-2","children":[]},{"level":2,"title":"v1.4.1","slug":"v1-4-1","link":"#v1-4-1","children":[]},{"level":2,"title":"v1.4.0","slug":"v1-4-0","link":"#v1-4-0","children":[]},{"level":2,"title":"v1.3.4","slug":"v1-3-4","link":"#v1-3-4","children":[]},{"level":2,"title":"v1.3.3","slug":"v1-3-3","link":"#v1-3-3","children":[]},{"level":2,"title":"v1.3.2","slug":"v1-3-2","link":"#v1-3-2","children":[]},{"level":2,"title":"v1.3.1","slug":"v1-3-1","link":"#v1-3-1","children":[]},{"level":2,"title":"v1.3.0","slug":"v1-3-0","link":"#v1-3-0","children":[]},{"level":2,"title":"v1.2.3","slug":"v1-2-3","link":"#v1-2-3","children":[]},{"level":2,"title":"v1.2.2","slug":"v1-2-2","link":"#v1-2-2","children":[]},{"level":2,"title":"v1.2.1","slug":"v1-2-1","link":"#v1-2-1","children":[]},{"level":2,"title":"v1.2.0","slug":"v1-2-0","link":"#v1-2-0","children":[]},{"level":2,"title":"v1.1.7","slug":"v1-1-7","link":"#v1-1-7","children":[]},{"level":2,"title":"v1.1.6","slug":"v1-1-6","link":"#v1-1-6","children":[]},{"level":2,"title":"v1.1.5","slug":"v1-1-5","link":"#v1-1-5","children":[]},{"level":2,"title":"v1.1.4","slug":"v1-1-4","link":"#v1-1-4","children":[]},{"level":2,"title":"v1.1.3","slug":"v1-1-3","link":"#v1-1-3","children":[]},{"level":2,"title":"v1.1.2","slug":"v1-1-2","link":"#v1-1-2","children":[]},{"level":2,"title":"v1.1.1","slug":"v1-1-1","link":"#v1-1-1","children":[]},{"level":2,"title":"v1.1.0","slug":"v1-1-0","link":"#v1-1-0","children":[]},{"level":2,"title":"v1.0.4","slug":"v1-0-4","link":"#v1-0-4","children":[]},{"level":2,"title":"v1.0.3","slug":"v1-0-3","link":"#v1-0-3","children":[]},{"level":2,"title":"v1.0.2","slug":"v1-0-2","link":"#v1-0-2","children":[]},{"level":2,"title":"v1.0.1","slug":"v1-0-1","link":"#v1-0-1","children":[]},{"level":2,"title":"v1.0.0","slug":"v1-0-0","link":"#v1-0-0","children":[]}],"relativePath":"project/ClipboardManager/log/index.md","lastUpdated":1676737739000}'),d={name:"project/ClipboardManager/log/index.md"},c=a('

    更新日志

    v2.0.5

    2023-02-19

    • fix: 修复插件启动时WebDav上传失败报错的问题
    • fix: 修复插件启动时会员用户登录联网失败的问题

    v2.0.4

    2023-02-13

    • feat: 支持修改代码高亮主题、样式与是否启用
    • feat: 右下角常驻当前选中条目的更新日期
    • feat: 页面滚动条样式优化
    • fix: 修复错误识别文本内容为网址的问题
    • fix: 修复删除条目后插件卡死的问题
    • fix: 修复某些情况下数据不再向下展示的问题

    v2.0.3

    2023-02-10

    • feat: 按住Ctrl/Command点击文本/链接 可以直接预览/跳转
    • feat: 按住Ctrl/Command点击图片 可以直接全局预览
    • feat: 按住Ctrl/Command点击文件 可以打开其所在文件夹
    • feat: 调整预览页展开样式
    • fix: 多选状态无法通过点击鼠标添加选项
    • fix: 某些情况下预览页无法执行Ctrl+C部分复制

    v2.0.2

    2023-02-10

    • fix: 更新到新版后首次进入白屏问题
    • fix: 新设备首次进入插件数据库路径读取问题
    • fix: 优化联网失败的弹窗逻辑
    • fix: 普通用户图标颜色异常

    v2.0.1

    2023-02-10

    • feat: 工具栏按钮顺序调整 会员用户添加金色标识
    • fix: 切换分类时出现明显卡顿
    • fix: 未登录用户进入用户中心白屏
    • fix: 添加网络问题导致登录验证失败的弹窗提醒

    v2.0.0

    2023-02-07

    • feat: 界面焕新 简洁高效
    • feat: 支持WebDav自动同步功能
    • feat: 支持预览页代码高亮
    • feat: 支持自定义分类卡片的顺序
    • feat: 支持识别文本内容为色值、链接等
    • feat: 支持左右键切换导航
    • feat: 支持关闭剪贴板图片记录
    • feat: 支持手动设置偏好主题
    • fix: 清空数据库保留收藏内容
    • fix: 滚动到底部触发懒加载失败
    • refactor: 组件重构 优化大列表运行时性能
    • refactor: 本地读写性能优化

    v1.4.7

    2022-11-03

    • feat: 设置页支持使用ESC返回上一级
    • fix: 移除了启动监听程序时对MacOS的特殊判断
    • fix: 移除了缺少监听程序时的通知报错

    v1.4.6

    2022-11-01

    • feat: 调整设置页图标与界面按钮细节
    • fix: 会员用户由于数据同步导致的插件白屏问题
    • fix: 多选复制时条目排序被颠倒

    v1.4.5

    2022-10-10

    • feat: 调整过期天数列表 最长支持31天
    • feat: 设置页添加handler安装引导
    • fix: 清空数据时内存数据未清空
    • fix: 多端同步时内存数据未更新
    • fix: 开发者模式下listener错误挂载

    v1.4.4

    2022-09-26

    • fix: 修复重复粘贴的问题

    v1.4.3

    2022-09-25

    • feat: 增加空格快捷键 按下连续多选的功能
    • feat: 多选状态下移动鼠标不再激活列表条目
    • feat: 支持展示剪贴板监听程序状态
    • fix: 删除某条历史记录时不再返回顶部
    • fix: 多选图片无法合并复制
    • fix: 内置按钮颜色管理关键字错误
    • fix: 设置页下拉框过长时被卡片遮挡
    • fix: 设置页滚动到底部触发懒加载

    v1.4.2

    2022-09-21

    • chore: 移除了插件内的二进制文件 恢复旧的监听机制 性能问题有待解决

    v1.4.1

    2022-09-21

    • fix: 修复了新的监听机制在 Mac 下无法正确获取剪贴板更新事件的问题

    v1.4.0

    2022-09-20

    插件能够正确在Linux上运行 离不开 小千 不厌其烦的测试与调试 💖

    感谢每一位为超级剪贴板提出过建议、参与测试与调试的用户

    • feat: 支持自定义数据库路径/存储条数/过期时间/展示在主界面的按钮
    • feat: 功能按钮支持自定义 创造属于你自己的功能按钮
    • feat: 添加了9个内置的自定义功能按钮
    • feat: 增加了更优雅的弹窗与提示界面
    • feat: 预览页更宽了 支持预览图片
    • feat: 导航栏图标样式修改
    • fix: 解决了CPU占用高、浏览大图卡顿的性能问题
    • fix: 从后台进入插件自动清空搜索框
    • refactor: 改变了监听剪贴板的方式 性能更优
    • refactor: 引入了ElementPlus组件库与图标库

    v1.3.4

    2022-09-19

    • feat: 移除插件内收藏Tab
    • feat: 点击收藏按钮后将携带数据跳转至备忘快贴
    • refactor: 优化代码执行逻辑 移除冗余代码

    v1.3.3

    2022-09-16

    • feat: 提高主色在深色模式下的对比度 改善长文本表现
    • feat: 添加快存功能按钮 配合超级粘贴插件实现快速转存
    • feat: 支持在预览页展示全部功能按钮
    • feat: 重要版本更新自动展示通知卡片
    • fix: 修正多选快捷键Shift影响检索输入的问题
    • fix: 检索词更新后 未自动激活首条记录

    v1.3.2

    2022-09-15

    • feat: 鼠标悬停展示具体日期、完整数据
    • feat: 调整历史记录上限为800条
    • fix: 修复鼠标置于功能按钮时上下键失效的问题
    • fix: 调整大图片判定尺寸

    v1.3.1

    2022-09-12

    • feat: 支持通过历史记录列表进入分词
    • feat: 减小插件体积 对智慧分词的支持改为插件跳转

    v1.3.0

    2022-09-09

    • feat: 添加多选功能 支持跨标签合并文本/图片/文件
    • feat: 支持通过按下Shift进入多选功能 支持按住Shift快速选择
    • feat: 支持使用Ctrl+CEnter快捷合并复制/粘贴
    • feat: 添加智慧分词功能 可对文本进行分割提取
    • feat: 长文本以蓝色高亮显示 不再提供查看全部按钮
    • feat: 优化界面动效

    v1.2.3

    2022-09-08

    • fix: 修复了检索内容时搜索记录不准确的问题

    v1.2.2

    2022-09-07

    • feat: 搜索框支持使用空格分词以同时检索多个关键词
    • fix: 修复了剪贴板数据记录遗漏的问题
    • fix: 收藏内容不再计入到条数限制中
    • fix: 修复了非预期的搜索框聚焦行为
    • fix: 预览页的按钮改为固定在顶部

    v1.2.1

    2022-09-05

    • feat: 支持通过功能按钮进入任意数据的预览页面
    • feat: 支持通过功能按钮打开文件所在目录
    • feat: 添加取消收藏功能按钮
    • feat: 搜索框支持展开/收起 输入任意内容展开并聚焦搜索
    • feat: 侧栏预览页添加复制全部智慧分词按钮
    • feat: 功能按钮改为使用图标展示
    • feat: 优化了界面样式
    • refactor: 清理定时器 优化插件性能

    v1.2.0

    2022-09-04

    • feat: 添加右侧操作栏 支持复制/收藏/删除操作
    • feat: 添加标签页收藏 支持在此页面管理所有收藏
    • feat: 调整侧栏宽度 调整界面样式细节

    v1.1.7

    2022-08-30

    • fix: 定时器检查剪贴板,修复了不记录剪贴板的问题

    v1.1.6

    2022-08-27

    • feat: 添加Alt+数字键Ctrl+数字键快速选择功能
    • feat: 调整界面样式 调整查看全部位置 移除图片背景色 增加动效
    • feat: 搜索框增加检索条数展示
    • fix: 改善插件读取图片的性能

    v1.1.5

    2022-08-25

    • fix: 提高剪贴板读取频率,避免高频复制时丢数据的情况

    v1.1.4

    2022-08-20

    • feat: 增加清空搜索框的按钮
    • feat: 优化插件内按下ESC的功能: 退出完整预览/清空搜索框
    • feat: 进入插件自动选中框内全部文本
    • fix: Mac在分离窗口状态左键会粘贴到搜索框 #13

    v1.1.3

    2022-08-19

    • feat: 调整界面在深色模式下的表现样式
    • fix: 在侧栏全部数据中使用Ctrl+C复制部分文本失效
    • fix: Mac下使用Ctrl+C复制单条记录失效
    • fix: 通过换行符个数区分超长文本
    • fix: 窗口分离下鼠标单击导致粘贴到搜索框
    • chore: 原插件名剪贴板改为超级剪贴板

    v1.1.2

    2022-08-18

    • feat: 执行复制后只隐藏主界面而不退出插件到后台
    • feat: 搜索时不再区分大小写
    • fix: 文本内容会出现异常首行缩进
    • fix: 图片展示在列表中的时候 右侧多出一个图块
    • fix: 移除鼠标hover时数据底部的色块

    v1.1.1

    2022-08-17

    • fix: 复制超大图片进入插件时崩溃

    v1.1.0

    2022-08-16

    • feat: 支持使用 键切换选中记录
    • feat: 支持使用 Ctrl+C 复制选中记录
    • feat: 支持使用 Enter 复制选中记录并粘贴

    v1.0.4

    2022-08-16

    • feat: 进入插件自动回到顶部、切换至全部分类
    • feat: 监听到键盘事件自动聚焦到搜索框
    • feat: 调整鼠标hover动画与历史记录的active样式
    • fix: 使用Tab切换导航失效
    • fix: 超长图片显示越界

    v1.0.3

    2022-08-16

    • fix: 路径分隔符导致写入错误的数据文件

    v1.0.2

    2022-08-15

    • fix: Mac下由权限导致的无法写入数据

    v1.0.1

    2022-08-15

    • feat: 区分鼠标点击行为:左键复制并粘贴,右键仅复制
    • feat: 适配深色模式
    • feat: 移除了右侧的查看更多按钮
    • feat: 单次展示的条数增加到了15条
    • feat: 增加条数限制500条 增加存储日期限制14天
    • feat: 增加了多平台支持
    • fix: 执行粘贴后主输入框未隐藏
    • refactor: Vue3重构

    v1.0.0

    2022-08-14

    • release: v1.0.0发布
    ',111),t=[c];function r(h,v,o,n,f,u){return l(),i("div",null,t)}const p=e(d,[["render",r]]);export{x as __pageData,p as default}; diff --git a/assets/project_ClipboardManager_log_index.md.4ee5fe53.lean.js b/assets/project_ClipboardManager_log_index.md.4ee5fe53.lean.js deleted file mode 100644 index 253becad..00000000 --- a/assets/project_ClipboardManager_log_index.md.4ee5fe53.lean.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as e,o as l,c as i,a}from"./app.33820b61.js";const x=JSON.parse('{"title":"更新日志","description":"","frontmatter":{},"headers":[{"level":2,"title":"v2.0.5","slug":"v2-0-5","link":"#v2-0-5","children":[]},{"level":2,"title":"v2.0.4","slug":"v2-0-4","link":"#v2-0-4","children":[]},{"level":2,"title":"v2.0.3","slug":"v2-0-3","link":"#v2-0-3","children":[]},{"level":2,"title":"v2.0.2","slug":"v2-0-2","link":"#v2-0-2","children":[]},{"level":2,"title":"v2.0.1","slug":"v2-0-1","link":"#v2-0-1","children":[]},{"level":2,"title":"v2.0.0","slug":"v2-0-0","link":"#v2-0-0","children":[]},{"level":2,"title":"v1.4.7","slug":"v1-4-7","link":"#v1-4-7","children":[]},{"level":2,"title":"v1.4.6","slug":"v1-4-6","link":"#v1-4-6","children":[]},{"level":2,"title":"v1.4.5","slug":"v1-4-5","link":"#v1-4-5","children":[]},{"level":2,"title":"v1.4.4","slug":"v1-4-4","link":"#v1-4-4","children":[]},{"level":2,"title":"v1.4.3","slug":"v1-4-3","link":"#v1-4-3","children":[]},{"level":2,"title":"v1.4.2","slug":"v1-4-2","link":"#v1-4-2","children":[]},{"level":2,"title":"v1.4.1","slug":"v1-4-1","link":"#v1-4-1","children":[]},{"level":2,"title":"v1.4.0","slug":"v1-4-0","link":"#v1-4-0","children":[]},{"level":2,"title":"v1.3.4","slug":"v1-3-4","link":"#v1-3-4","children":[]},{"level":2,"title":"v1.3.3","slug":"v1-3-3","link":"#v1-3-3","children":[]},{"level":2,"title":"v1.3.2","slug":"v1-3-2","link":"#v1-3-2","children":[]},{"level":2,"title":"v1.3.1","slug":"v1-3-1","link":"#v1-3-1","children":[]},{"level":2,"title":"v1.3.0","slug":"v1-3-0","link":"#v1-3-0","children":[]},{"level":2,"title":"v1.2.3","slug":"v1-2-3","link":"#v1-2-3","children":[]},{"level":2,"title":"v1.2.2","slug":"v1-2-2","link":"#v1-2-2","children":[]},{"level":2,"title":"v1.2.1","slug":"v1-2-1","link":"#v1-2-1","children":[]},{"level":2,"title":"v1.2.0","slug":"v1-2-0","link":"#v1-2-0","children":[]},{"level":2,"title":"v1.1.7","slug":"v1-1-7","link":"#v1-1-7","children":[]},{"level":2,"title":"v1.1.6","slug":"v1-1-6","link":"#v1-1-6","children":[]},{"level":2,"title":"v1.1.5","slug":"v1-1-5","link":"#v1-1-5","children":[]},{"level":2,"title":"v1.1.4","slug":"v1-1-4","link":"#v1-1-4","children":[]},{"level":2,"title":"v1.1.3","slug":"v1-1-3","link":"#v1-1-3","children":[]},{"level":2,"title":"v1.1.2","slug":"v1-1-2","link":"#v1-1-2","children":[]},{"level":2,"title":"v1.1.1","slug":"v1-1-1","link":"#v1-1-1","children":[]},{"level":2,"title":"v1.1.0","slug":"v1-1-0","link":"#v1-1-0","children":[]},{"level":2,"title":"v1.0.4","slug":"v1-0-4","link":"#v1-0-4","children":[]},{"level":2,"title":"v1.0.3","slug":"v1-0-3","link":"#v1-0-3","children":[]},{"level":2,"title":"v1.0.2","slug":"v1-0-2","link":"#v1-0-2","children":[]},{"level":2,"title":"v1.0.1","slug":"v1-0-1","link":"#v1-0-1","children":[]},{"level":2,"title":"v1.0.0","slug":"v1-0-0","link":"#v1-0-0","children":[]}],"relativePath":"project/ClipboardManager/log/index.md","lastUpdated":1676737739000}'),d={name:"project/ClipboardManager/log/index.md"},c=a("",111),t=[c];function r(h,v,o,n,f,u){return l(),i("div",null,t)}const p=e(d,[["render",r]]);export{x as __pageData,p as default}; diff --git a/assets/project_ClipboardManager_log_index.md.9bd18ae1.js b/assets/project_ClipboardManager_log_index.md.9bd18ae1.js new file mode 100644 index 00000000..0bc864d9 --- /dev/null +++ b/assets/project_ClipboardManager_log_index.md.9bd18ae1.js @@ -0,0 +1 @@ +import{_ as l,o as e,c as i,a}from"./app.33820b61.js";const x=JSON.parse('{"title":"更新日志","description":"","frontmatter":{},"headers":[{"level":2,"title":"v2.0.6","slug":"v2-0-6","link":"#v2-0-6","children":[]},{"level":2,"title":"v2.0.5","slug":"v2-0-5","link":"#v2-0-5","children":[]},{"level":2,"title":"v2.0.4","slug":"v2-0-4","link":"#v2-0-4","children":[]},{"level":2,"title":"v2.0.3","slug":"v2-0-3","link":"#v2-0-3","children":[]},{"level":2,"title":"v2.0.2","slug":"v2-0-2","link":"#v2-0-2","children":[]},{"level":2,"title":"v2.0.1","slug":"v2-0-1","link":"#v2-0-1","children":[]},{"level":2,"title":"v2.0.0","slug":"v2-0-0","link":"#v2-0-0","children":[]},{"level":2,"title":"v1.4.7","slug":"v1-4-7","link":"#v1-4-7","children":[]},{"level":2,"title":"v1.4.6","slug":"v1-4-6","link":"#v1-4-6","children":[]},{"level":2,"title":"v1.4.5","slug":"v1-4-5","link":"#v1-4-5","children":[]},{"level":2,"title":"v1.4.4","slug":"v1-4-4","link":"#v1-4-4","children":[]},{"level":2,"title":"v1.4.3","slug":"v1-4-3","link":"#v1-4-3","children":[]},{"level":2,"title":"v1.4.2","slug":"v1-4-2","link":"#v1-4-2","children":[]},{"level":2,"title":"v1.4.1","slug":"v1-4-1","link":"#v1-4-1","children":[]},{"level":2,"title":"v1.4.0","slug":"v1-4-0","link":"#v1-4-0","children":[]},{"level":2,"title":"v1.3.4","slug":"v1-3-4","link":"#v1-3-4","children":[]},{"level":2,"title":"v1.3.3","slug":"v1-3-3","link":"#v1-3-3","children":[]},{"level":2,"title":"v1.3.2","slug":"v1-3-2","link":"#v1-3-2","children":[]},{"level":2,"title":"v1.3.1","slug":"v1-3-1","link":"#v1-3-1","children":[]},{"level":2,"title":"v1.3.0","slug":"v1-3-0","link":"#v1-3-0","children":[]},{"level":2,"title":"v1.2.3","slug":"v1-2-3","link":"#v1-2-3","children":[]},{"level":2,"title":"v1.2.2","slug":"v1-2-2","link":"#v1-2-2","children":[]},{"level":2,"title":"v1.2.1","slug":"v1-2-1","link":"#v1-2-1","children":[]},{"level":2,"title":"v1.2.0","slug":"v1-2-0","link":"#v1-2-0","children":[]},{"level":2,"title":"v1.1.7","slug":"v1-1-7","link":"#v1-1-7","children":[]},{"level":2,"title":"v1.1.6","slug":"v1-1-6","link":"#v1-1-6","children":[]},{"level":2,"title":"v1.1.5","slug":"v1-1-5","link":"#v1-1-5","children":[]},{"level":2,"title":"v1.1.4","slug":"v1-1-4","link":"#v1-1-4","children":[]},{"level":2,"title":"v1.1.3","slug":"v1-1-3","link":"#v1-1-3","children":[]},{"level":2,"title":"v1.1.2","slug":"v1-1-2","link":"#v1-1-2","children":[]},{"level":2,"title":"v1.1.1","slug":"v1-1-1","link":"#v1-1-1","children":[]},{"level":2,"title":"v1.1.0","slug":"v1-1-0","link":"#v1-1-0","children":[]},{"level":2,"title":"v1.0.4","slug":"v1-0-4","link":"#v1-0-4","children":[]},{"level":2,"title":"v1.0.3","slug":"v1-0-3","link":"#v1-0-3","children":[]},{"level":2,"title":"v1.0.2","slug":"v1-0-2","link":"#v1-0-2","children":[]},{"level":2,"title":"v1.0.1","slug":"v1-0-1","link":"#v1-0-1","children":[]},{"level":2,"title":"v1.0.0","slug":"v1-0-0","link":"#v1-0-0","children":[]}],"relativePath":"project/ClipboardManager/log/index.md","lastUpdated":1676979063000}'),d={name:"project/ClipboardManager/log/index.md"},c=a('

    更新日志

    v2.0.6

    2023-02-22

    • fix: 优化列表展示性能
    • fix: 优化本地读写稳定性 修复数据损坏导致的白屏问题
    • fix: 优化代码高亮依赖缓存 避免多次请求下载

    v2.0.5

    2023-02-19

    • fix: 修复插件启动时WebDav上传失败报错的问题
    • fix: 修复插件启动时会员用户登录联网失败的问题

    v2.0.4

    2023-02-13

    • feat: 支持修改代码高亮主题、样式与是否启用
    • feat: 右下角常驻当前选中条目的更新日期
    • feat: 页面滚动条样式优化
    • fix: 修复错误识别文本内容为网址的问题
    • fix: 修复删除条目后插件卡死的问题
    • fix: 修复某些情况下数据不再向下展示的问题

    v2.0.3

    2023-02-10

    • feat: 按住Ctrl/Command点击文本/链接 可以直接预览/跳转
    • feat: 按住Ctrl/Command点击图片 可以直接全局预览
    • feat: 按住Ctrl/Command点击文件 可以打开其所在文件夹
    • feat: 调整预览页展开样式
    • fix: 多选状态无法通过点击鼠标添加选项
    • fix: 某些情况下预览页无法执行Ctrl+C部分复制

    v2.0.2

    2023-02-10

    • fix: 更新到新版后首次进入白屏问题
    • fix: 新设备首次进入插件数据库路径读取问题
    • fix: 优化联网失败的弹窗逻辑
    • fix: 普通用户图标颜色异常

    v2.0.1

    2023-02-10

    • feat: 工具栏按钮顺序调整 会员用户添加金色标识
    • fix: 切换分类时出现明显卡顿
    • fix: 未登录用户进入用户中心白屏
    • fix: 添加网络问题导致登录验证失败的弹窗提醒

    v2.0.0

    2023-02-07

    • feat: 界面焕新 简洁高效
    • feat: 支持WebDav自动同步功能
    • feat: 支持预览页代码高亮
    • feat: 支持自定义分类卡片的顺序
    • feat: 支持识别文本内容为色值、链接等
    • feat: 支持左右键切换导航
    • feat: 支持关闭剪贴板图片记录
    • feat: 支持手动设置偏好主题
    • fix: 清空数据库保留收藏内容
    • fix: 滚动到底部触发懒加载失败
    • refactor: 组件重构 优化大列表运行时性能
    • refactor: 本地读写性能优化

    v1.4.7

    2022-11-03

    • feat: 设置页支持使用ESC返回上一级
    • fix: 移除了启动监听程序时对MacOS的特殊判断
    • fix: 移除了缺少监听程序时的通知报错

    v1.4.6

    2022-11-01

    • feat: 调整设置页图标与界面按钮细节
    • fix: 会员用户由于数据同步导致的插件白屏问题
    • fix: 多选复制时条目排序被颠倒

    v1.4.5

    2022-10-10

    • feat: 调整过期天数列表 最长支持31天
    • feat: 设置页添加handler安装引导
    • fix: 清空数据时内存数据未清空
    • fix: 多端同步时内存数据未更新
    • fix: 开发者模式下listener错误挂载

    v1.4.4

    2022-09-26

    • fix: 修复重复粘贴的问题

    v1.4.3

    2022-09-25

    • feat: 增加空格快捷键 按下连续多选的功能
    • feat: 多选状态下移动鼠标不再激活列表条目
    • feat: 支持展示剪贴板监听程序状态
    • fix: 删除某条历史记录时不再返回顶部
    • fix: 多选图片无法合并复制
    • fix: 内置按钮颜色管理关键字错误
    • fix: 设置页下拉框过长时被卡片遮挡
    • fix: 设置页滚动到底部触发懒加载

    v1.4.2

    2022-09-21

    • chore: 移除了插件内的二进制文件 恢复旧的监听机制 性能问题有待解决

    v1.4.1

    2022-09-21

    • fix: 修复了新的监听机制在 Mac 下无法正确获取剪贴板更新事件的问题

    v1.4.0

    2022-09-20

    插件能够正确在Linux上运行 离不开 小千 不厌其烦的测试与调试 💖

    感谢每一位为超级剪贴板提出过建议、参与测试与调试的用户

    • feat: 支持自定义数据库路径/存储条数/过期时间/展示在主界面的按钮
    • feat: 功能按钮支持自定义 创造属于你自己的功能按钮
    • feat: 添加了9个内置的自定义功能按钮
    • feat: 增加了更优雅的弹窗与提示界面
    • feat: 预览页更宽了 支持预览图片
    • feat: 导航栏图标样式修改
    • fix: 解决了CPU占用高、浏览大图卡顿的性能问题
    • fix: 从后台进入插件自动清空搜索框
    • refactor: 改变了监听剪贴板的方式 性能更优
    • refactor: 引入了ElementPlus组件库与图标库

    v1.3.4

    2022-09-19

    • feat: 移除插件内收藏Tab
    • feat: 点击收藏按钮后将携带数据跳转至备忘快贴
    • refactor: 优化代码执行逻辑 移除冗余代码

    v1.3.3

    2022-09-16

    • feat: 提高主色在深色模式下的对比度 改善长文本表现
    • feat: 添加快存功能按钮 配合超级粘贴插件实现快速转存
    • feat: 支持在预览页展示全部功能按钮
    • feat: 重要版本更新自动展示通知卡片
    • fix: 修正多选快捷键Shift影响检索输入的问题
    • fix: 检索词更新后 未自动激活首条记录

    v1.3.2

    2022-09-15

    • feat: 鼠标悬停展示具体日期、完整数据
    • feat: 调整历史记录上限为800条
    • fix: 修复鼠标置于功能按钮时上下键失效的问题
    • fix: 调整大图片判定尺寸

    v1.3.1

    2022-09-12

    • feat: 支持通过历史记录列表进入分词
    • feat: 减小插件体积 对智慧分词的支持改为插件跳转

    v1.3.0

    2022-09-09

    • feat: 添加多选功能 支持跨标签合并文本/图片/文件
    • feat: 支持通过按下Shift进入多选功能 支持按住Shift快速选择
    • feat: 支持使用Ctrl+CEnter快捷合并复制/粘贴
    • feat: 添加智慧分词功能 可对文本进行分割提取
    • feat: 长文本以蓝色高亮显示 不再提供查看全部按钮
    • feat: 优化界面动效

    v1.2.3

    2022-09-08

    • fix: 修复了检索内容时搜索记录不准确的问题

    v1.2.2

    2022-09-07

    • feat: 搜索框支持使用空格分词以同时检索多个关键词
    • fix: 修复了剪贴板数据记录遗漏的问题
    • fix: 收藏内容不再计入到条数限制中
    • fix: 修复了非预期的搜索框聚焦行为
    • fix: 预览页的按钮改为固定在顶部

    v1.2.1

    2022-09-05

    • feat: 支持通过功能按钮进入任意数据的预览页面
    • feat: 支持通过功能按钮打开文件所在目录
    • feat: 添加取消收藏功能按钮
    • feat: 搜索框支持展开/收起 输入任意内容展开并聚焦搜索
    • feat: 侧栏预览页添加复制全部智慧分词按钮
    • feat: 功能按钮改为使用图标展示
    • feat: 优化了界面样式
    • refactor: 清理定时器 优化插件性能

    v1.2.0

    2022-09-04

    • feat: 添加右侧操作栏 支持复制/收藏/删除操作
    • feat: 添加标签页收藏 支持在此页面管理所有收藏
    • feat: 调整侧栏宽度 调整界面样式细节

    v1.1.7

    2022-08-30

    • fix: 定时器检查剪贴板,修复了不记录剪贴板的问题

    v1.1.6

    2022-08-27

    • feat: 添加Alt+数字键Ctrl+数字键快速选择功能
    • feat: 调整界面样式 调整查看全部位置 移除图片背景色 增加动效
    • feat: 搜索框增加检索条数展示
    • fix: 改善插件读取图片的性能

    v1.1.5

    2022-08-25

    • fix: 提高剪贴板读取频率,避免高频复制时丢数据的情况

    v1.1.4

    2022-08-20

    • feat: 增加清空搜索框的按钮
    • feat: 优化插件内按下ESC的功能: 退出完整预览/清空搜索框
    • feat: 进入插件自动选中框内全部文本
    • fix: Mac在分离窗口状态左键会粘贴到搜索框 #13

    v1.1.3

    2022-08-19

    • feat: 调整界面在深色模式下的表现样式
    • fix: 在侧栏全部数据中使用Ctrl+C复制部分文本失效
    • fix: Mac下使用Ctrl+C复制单条记录失效
    • fix: 通过换行符个数区分超长文本
    • fix: 窗口分离下鼠标单击导致粘贴到搜索框
    • chore: 原插件名剪贴板改为超级剪贴板

    v1.1.2

    2022-08-18

    • feat: 执行复制后只隐藏主界面而不退出插件到后台
    • feat: 搜索时不再区分大小写
    • fix: 文本内容会出现异常首行缩进
    • fix: 图片展示在列表中的时候 右侧多出一个图块
    • fix: 移除鼠标hover时数据底部的色块

    v1.1.1

    2022-08-17

    • fix: 复制超大图片进入插件时崩溃

    v1.1.0

    2022-08-16

    • feat: 支持使用 键切换选中记录
    • feat: 支持使用 Ctrl+C 复制选中记录
    • feat: 支持使用 Enter 复制选中记录并粘贴

    v1.0.4

    2022-08-16

    • feat: 进入插件自动回到顶部、切换至全部分类
    • feat: 监听到键盘事件自动聚焦到搜索框
    • feat: 调整鼠标hover动画与历史记录的active样式
    • fix: 使用Tab切换导航失效
    • fix: 超长图片显示越界

    v1.0.3

    2022-08-16

    • fix: 路径分隔符导致写入错误的数据文件

    v1.0.2

    2022-08-15

    • fix: Mac下由权限导致的无法写入数据

    v1.0.1

    2022-08-15

    • feat: 区分鼠标点击行为:左键复制并粘贴,右键仅复制
    • feat: 适配深色模式
    • feat: 移除了右侧的查看更多按钮
    • feat: 单次展示的条数增加到了15条
    • feat: 增加条数限制500条 增加存储日期限制14天
    • feat: 增加了多平台支持
    • fix: 执行粘贴后主输入框未隐藏
    • refactor: Vue3重构

    v1.0.0

    2022-08-14

    • release: v1.0.0发布
    ',114),t=[c];function r(h,v,n,o,f,u){return e(),i("div",null,t)}const p=l(d,[["render",r]]);export{x as __pageData,p as default}; diff --git a/assets/project_ClipboardManager_log_index.md.9bd18ae1.lean.js b/assets/project_ClipboardManager_log_index.md.9bd18ae1.lean.js new file mode 100644 index 00000000..c5bfe626 --- /dev/null +++ b/assets/project_ClipboardManager_log_index.md.9bd18ae1.lean.js @@ -0,0 +1 @@ +import{_ as l,o as e,c as i,a}from"./app.33820b61.js";const x=JSON.parse('{"title":"更新日志","description":"","frontmatter":{},"headers":[{"level":2,"title":"v2.0.6","slug":"v2-0-6","link":"#v2-0-6","children":[]},{"level":2,"title":"v2.0.5","slug":"v2-0-5","link":"#v2-0-5","children":[]},{"level":2,"title":"v2.0.4","slug":"v2-0-4","link":"#v2-0-4","children":[]},{"level":2,"title":"v2.0.3","slug":"v2-0-3","link":"#v2-0-3","children":[]},{"level":2,"title":"v2.0.2","slug":"v2-0-2","link":"#v2-0-2","children":[]},{"level":2,"title":"v2.0.1","slug":"v2-0-1","link":"#v2-0-1","children":[]},{"level":2,"title":"v2.0.0","slug":"v2-0-0","link":"#v2-0-0","children":[]},{"level":2,"title":"v1.4.7","slug":"v1-4-7","link":"#v1-4-7","children":[]},{"level":2,"title":"v1.4.6","slug":"v1-4-6","link":"#v1-4-6","children":[]},{"level":2,"title":"v1.4.5","slug":"v1-4-5","link":"#v1-4-5","children":[]},{"level":2,"title":"v1.4.4","slug":"v1-4-4","link":"#v1-4-4","children":[]},{"level":2,"title":"v1.4.3","slug":"v1-4-3","link":"#v1-4-3","children":[]},{"level":2,"title":"v1.4.2","slug":"v1-4-2","link":"#v1-4-2","children":[]},{"level":2,"title":"v1.4.1","slug":"v1-4-1","link":"#v1-4-1","children":[]},{"level":2,"title":"v1.4.0","slug":"v1-4-0","link":"#v1-4-0","children":[]},{"level":2,"title":"v1.3.4","slug":"v1-3-4","link":"#v1-3-4","children":[]},{"level":2,"title":"v1.3.3","slug":"v1-3-3","link":"#v1-3-3","children":[]},{"level":2,"title":"v1.3.2","slug":"v1-3-2","link":"#v1-3-2","children":[]},{"level":2,"title":"v1.3.1","slug":"v1-3-1","link":"#v1-3-1","children":[]},{"level":2,"title":"v1.3.0","slug":"v1-3-0","link":"#v1-3-0","children":[]},{"level":2,"title":"v1.2.3","slug":"v1-2-3","link":"#v1-2-3","children":[]},{"level":2,"title":"v1.2.2","slug":"v1-2-2","link":"#v1-2-2","children":[]},{"level":2,"title":"v1.2.1","slug":"v1-2-1","link":"#v1-2-1","children":[]},{"level":2,"title":"v1.2.0","slug":"v1-2-0","link":"#v1-2-0","children":[]},{"level":2,"title":"v1.1.7","slug":"v1-1-7","link":"#v1-1-7","children":[]},{"level":2,"title":"v1.1.6","slug":"v1-1-6","link":"#v1-1-6","children":[]},{"level":2,"title":"v1.1.5","slug":"v1-1-5","link":"#v1-1-5","children":[]},{"level":2,"title":"v1.1.4","slug":"v1-1-4","link":"#v1-1-4","children":[]},{"level":2,"title":"v1.1.3","slug":"v1-1-3","link":"#v1-1-3","children":[]},{"level":2,"title":"v1.1.2","slug":"v1-1-2","link":"#v1-1-2","children":[]},{"level":2,"title":"v1.1.1","slug":"v1-1-1","link":"#v1-1-1","children":[]},{"level":2,"title":"v1.1.0","slug":"v1-1-0","link":"#v1-1-0","children":[]},{"level":2,"title":"v1.0.4","slug":"v1-0-4","link":"#v1-0-4","children":[]},{"level":2,"title":"v1.0.3","slug":"v1-0-3","link":"#v1-0-3","children":[]},{"level":2,"title":"v1.0.2","slug":"v1-0-2","link":"#v1-0-2","children":[]},{"level":2,"title":"v1.0.1","slug":"v1-0-1","link":"#v1-0-1","children":[]},{"level":2,"title":"v1.0.0","slug":"v1-0-0","link":"#v1-0-0","children":[]}],"relativePath":"project/ClipboardManager/log/index.md","lastUpdated":1676979063000}'),d={name:"project/ClipboardManager/log/index.md"},c=a("",114),t=[c];function r(h,v,n,o,f,u){return e(),i("div",null,t)}const p=l(d,[["render",r]]);export{x as __pageData,p as default}; diff --git a/assets/project_ClipboardManager_statement_index.md.6751fd19.js b/assets/project_ClipboardManager_statement_index.md.fddb5934.js similarity index 99% rename from assets/project_ClipboardManager_statement_index.md.6751fd19.js rename to assets/project_ClipboardManager_statement_index.md.fddb5934.js index 22bb9d52..6892cf58 100644 --- a/assets/project_ClipboardManager_statement_index.md.6751fd19.js +++ b/assets/project_ClipboardManager_statement_index.md.fddb5934.js @@ -1 +1 @@ -import{_ as e,o as a,c as l,a as i}from"./app.33820b61.js";const g=JSON.parse('{"title":"Q&A","description":"","frontmatter":{"navbar":false},"headers":[{"level":2,"title":"为什么偶尔CPU占用特别高? 为什么预览图片时插件卡顿?","slug":"为什么偶尔cpu占用特别高-为什么预览图片时插件卡顿","link":"#为什么偶尔cpu占用特别高-为什么预览图片时插件卡顿","children":[]},{"level":2,"title":"为什么官方的剪贴板插件没有CPU占用高这个问题?","slug":"为什么官方的剪贴板插件没有cpu占用高这个问题","link":"#为什么官方的剪贴板插件没有cpu占用高这个问题","children":[]},{"level":2,"title":"启动报错, 读取剪切板出错","slug":"启动报错-读取剪切板出错","link":"#启动报错-读取剪切板出错","children":[]},{"level":2,"title":"为什么剪贴板记录会丢失?","slug":"为什么剪贴板记录会丢失","link":"#为什么剪贴板记录会丢失","children":[]},{"level":2,"title":"我对这个插件的安全性有担忧, 插件偷窃我的隐私怎么办?","slug":"我对这个插件的安全性有担忧-插件偷窃我的隐私怎么办","link":"#我对这个插件的安全性有担忧-插件偷窃我的隐私怎么办","children":[]},{"level":2,"title":"我不懂代码, 我也不会构建, 但是我担心你的插件会窃取我的隐私","slug":"我不懂代码-我也不会构建-但是我担心你的插件会窃取我的隐私","link":"#我不懂代码-我也不会构建-但是我担心你的插件会窃取我的隐私","children":[]},{"level":2,"title":"开源版本和插件市场版本的区别?","slug":"开源版本和插件市场版本的区别","link":"#开源版本和插件市场版本的区别","children":[]},{"level":2,"title":"为什么不开源了, 为什么要开始收费?","slug":"为什么不开源了-为什么要开始收费","link":"#为什么不开源了-为什么要开始收费","children":[]}],"relativePath":"project/ClipboardManager/statement/index.md","lastUpdated":1676737739000}'),r={name:"project/ClipboardManager/statement/index.md"},t=i('

    Q&A

    为什么偶尔CPU占用特别高? 为什么预览图片时插件卡顿?

    这是由超级剪贴板监听剪贴板内容更新的机制决定的,为了不漏数据,超级剪贴板的监听策略为每300ms读取一次剪贴板内容并与上一次读取到的内容作比较。如果剪贴板当前位置是一张大图片,那么插件会反复读取这张图片,导致大量计算被用在了无意义的读取与对比上。

    插件市场中相同原理的同类插件的处理方法是:

    • 轮询比较两次剪贴板内容,如果检查到当前剪贴板内容数据量较大,则降低轮询时间间隔。
      • 这避免了读取大图片/长文本时的高占用,然而这很容易导致漏数据
    • 轮询比较两次剪贴板内容,由用户自定义轮询时间
      • 用户设置的轮询间隔时间长,读取大图片/长文本时不会导致高占用,但很容易漏数据。
      • 用户设置的轮询间隔时间较短,则又会造成高占用

    v1.4.0版本更新中,超级剪贴板换用了clipboard-event库监听剪贴板更新事件,这种方式性能更优,不需要反复读取剪贴板内容来做比较,而只需要在检查到剪贴板更新事件时通知插件读取一次剪贴板即可,完全解决了CPU占用高、浏览图片卡顿的问题。

    然而该库包含了二进制文件,这触发了uTools插件市场的安全限制而无法上架。所以自v1.4.2起,插件不再内置监听剪贴板更新事件的二进制文件,用户要使用低占用、高性能的剪贴板监听方案,可以自行下载并将其移动到剪贴板数据库文件所在目录,详见如何手动安装clipboard-event-handler,插件会自动判断使用新的抑或是旧的方案监听剪贴板更新。同时,自v1.4.3起,你可以在设置页查看当前剪贴板监听程序的运行状态。

    为什么官方的剪贴板插件没有CPU占用高这个问题?

    官方的剪贴板内容更新事件监听函数也是从一个二进制文件引出的,这个二进制文件跟随主程序启动,不受剪贴板插件的打开或关闭的影响。

    启动报错, 读取剪切板出错

    请尝试以下方法:

    1. 清空本地数据库文件
    2. 格式化uTools内的插件数据
    3. 完全退出插件后重启插件

    如果上述方法都无法解决你的问题,欢迎论坛回帖或加入QQ群交流具体情况

    为什么剪贴板记录会丢失?

    一般是由于插件退出后台运行导致的, 插件需要保持后台运行才能记录剪贴板, 请检查:

    • 是否正确设置了插件跟随主程序启动
    • 是否手动清理或关闭了后台插件 (在分离模式下关闭插件 使用clear命令 在插件列表退出插件)
    • 是否存在高频复制的操作 (高频复制可能会漏掉记录)

    我对这个插件的安全性有担忧, 插件偷窃我的隐私怎么办?

    首先, 我写这个插件不是为了获取你的隐私的, 我对你的隐私没有兴趣, 这一点你完全可以放心;

    其次uTools官方在插件上架前会对代码进行审查, 如果插件有高危行为, 那也不会过审;

    再其次, uTools大部分用户是程序员, 如果我真的在代码里藏了"毒", 那他们也有办法发现, 如果你真的对你的隐私十分关心, 可以选择从开源仓库下载代码自行构建

    我不懂代码, 我也不会构建, 但是我担心你的插件会窃取我的隐私

    我在贡献教程中详细说明了如何构建, JavaScript也并不是一门很高深的语言, 祝你能早日入门, 构建出安全的版本供自己使用, 学习的过程中遇到任何问题, 也欢迎随时与我交流 😄

    开源版本和插件市场版本的区别?

    开源版本后续将只提供必要的BUG修复, 不再添加新功能

    • 开源版本: 包含完整的基本功能, 可以自行构建开源版本, 通过安装离线插件方式使用
    • 市场版本: 包含后续更新的新功能插件会员功能, 可以直接从插件应用市场安装

    为什么不开源了, 为什么要开始收费?

    目前由我个人维护的开源版本已经趋于稳定, 可以满足绝大部分场景的需求

    • 代码开源的出发点不是为了让不愿付费的人白嫖开发者的劳动, 而是为开发提供更多的经验和思路, 开源的代码已经启发了一些开发者上架了自己的剪贴板插件应用
    • 开发和维护插件需要时间和精力, 插件付费可以鼓励我更积极的更新
    • 目前插件内已有的基本功能都不会转为收费, 可以放心使用
    ',28),d=[t];function n(o,c,h,s,p,u){return a(),l("div",null,d)}const f=e(r,[["render",n]]);export{g as __pageData,f as default}; +import{_ as e,o as a,c as l,a as i}from"./app.33820b61.js";const g=JSON.parse('{"title":"Q&A","description":"","frontmatter":{"navbar":false},"headers":[{"level":2,"title":"为什么偶尔CPU占用特别高? 为什么预览图片时插件卡顿?","slug":"为什么偶尔cpu占用特别高-为什么预览图片时插件卡顿","link":"#为什么偶尔cpu占用特别高-为什么预览图片时插件卡顿","children":[]},{"level":2,"title":"为什么官方的剪贴板插件没有CPU占用高这个问题?","slug":"为什么官方的剪贴板插件没有cpu占用高这个问题","link":"#为什么官方的剪贴板插件没有cpu占用高这个问题","children":[]},{"level":2,"title":"启动报错, 读取剪切板出错","slug":"启动报错-读取剪切板出错","link":"#启动报错-读取剪切板出错","children":[]},{"level":2,"title":"为什么剪贴板记录会丢失?","slug":"为什么剪贴板记录会丢失","link":"#为什么剪贴板记录会丢失","children":[]},{"level":2,"title":"我对这个插件的安全性有担忧, 插件偷窃我的隐私怎么办?","slug":"我对这个插件的安全性有担忧-插件偷窃我的隐私怎么办","link":"#我对这个插件的安全性有担忧-插件偷窃我的隐私怎么办","children":[]},{"level":2,"title":"我不懂代码, 我也不会构建, 但是我担心你的插件会窃取我的隐私","slug":"我不懂代码-我也不会构建-但是我担心你的插件会窃取我的隐私","link":"#我不懂代码-我也不会构建-但是我担心你的插件会窃取我的隐私","children":[]},{"level":2,"title":"开源版本和插件市场版本的区别?","slug":"开源版本和插件市场版本的区别","link":"#开源版本和插件市场版本的区别","children":[]},{"level":2,"title":"为什么不开源了, 为什么要开始收费?","slug":"为什么不开源了-为什么要开始收费","link":"#为什么不开源了-为什么要开始收费","children":[]}],"relativePath":"project/ClipboardManager/statement/index.md","lastUpdated":1676979063000}'),r={name:"project/ClipboardManager/statement/index.md"},t=i('

    Q&A

    为什么偶尔CPU占用特别高? 为什么预览图片时插件卡顿?

    这是由超级剪贴板监听剪贴板内容更新的机制决定的,为了不漏数据,超级剪贴板的监听策略为每300ms读取一次剪贴板内容并与上一次读取到的内容作比较。如果剪贴板当前位置是一张大图片,那么插件会反复读取这张图片,导致大量计算被用在了无意义的读取与对比上。

    插件市场中相同原理的同类插件的处理方法是:

    • 轮询比较两次剪贴板内容,如果检查到当前剪贴板内容数据量较大,则降低轮询时间间隔。
      • 这避免了读取大图片/长文本时的高占用,然而这很容易导致漏数据
    • 轮询比较两次剪贴板内容,由用户自定义轮询时间
      • 用户设置的轮询间隔时间长,读取大图片/长文本时不会导致高占用,但很容易漏数据。
      • 用户设置的轮询间隔时间较短,则又会造成高占用

    v1.4.0版本更新中,超级剪贴板换用了clipboard-event库监听剪贴板更新事件,这种方式性能更优,不需要反复读取剪贴板内容来做比较,而只需要在检查到剪贴板更新事件时通知插件读取一次剪贴板即可,完全解决了CPU占用高、浏览图片卡顿的问题。

    然而该库包含了二进制文件,这触发了uTools插件市场的安全限制而无法上架。所以自v1.4.2起,插件不再内置监听剪贴板更新事件的二进制文件,用户要使用低占用、高性能的剪贴板监听方案,可以自行下载并将其移动到剪贴板数据库文件所在目录,详见如何手动安装clipboard-event-handler,插件会自动判断使用新的抑或是旧的方案监听剪贴板更新。同时,自v1.4.3起,你可以在设置页查看当前剪贴板监听程序的运行状态。

    为什么官方的剪贴板插件没有CPU占用高这个问题?

    官方的剪贴板内容更新事件监听函数也是从一个二进制文件引出的,这个二进制文件跟随主程序启动,不受剪贴板插件的打开或关闭的影响。

    启动报错, 读取剪切板出错

    请尝试以下方法:

    1. 清空本地数据库文件
    2. 格式化uTools内的插件数据
    3. 完全退出插件后重启插件

    如果上述方法都无法解决你的问题,欢迎论坛回帖或加入QQ群交流具体情况

    为什么剪贴板记录会丢失?

    一般是由于插件退出后台运行导致的, 插件需要保持后台运行才能记录剪贴板, 请检查:

    • 是否正确设置了插件跟随主程序启动
    • 是否手动清理或关闭了后台插件 (在分离模式下关闭插件 使用clear命令 在插件列表退出插件)
    • 是否存在高频复制的操作 (高频复制可能会漏掉记录)

    我对这个插件的安全性有担忧, 插件偷窃我的隐私怎么办?

    首先, 我写这个插件不是为了获取你的隐私的, 我对你的隐私没有兴趣, 这一点你完全可以放心;

    其次uTools官方在插件上架前会对代码进行审查, 如果插件有高危行为, 那也不会过审;

    再其次, uTools大部分用户是程序员, 如果我真的在代码里藏了"毒", 那他们也有办法发现, 如果你真的对你的隐私十分关心, 可以选择从开源仓库下载代码自行构建

    我不懂代码, 我也不会构建, 但是我担心你的插件会窃取我的隐私

    我在贡献教程中详细说明了如何构建, JavaScript也并不是一门很高深的语言, 祝你能早日入门, 构建出安全的版本供自己使用, 学习的过程中遇到任何问题, 也欢迎随时与我交流 😄

    开源版本和插件市场版本的区别?

    开源版本后续将只提供必要的BUG修复, 不再添加新功能

    • 开源版本: 包含完整的基本功能, 可以自行构建开源版本, 通过安装离线插件方式使用
    • 市场版本: 包含后续更新的新功能插件会员功能, 可以直接从插件应用市场安装

    为什么不开源了, 为什么要开始收费?

    目前由我个人维护的开源版本已经趋于稳定, 可以满足绝大部分场景的需求

    • 代码开源的出发点不是为了让不愿付费的人白嫖开发者的劳动, 而是为开发提供更多的经验和思路, 开源的代码已经启发了一些开发者上架了自己的剪贴板插件应用
    • 开发和维护插件需要时间和精力, 插件付费可以鼓励我更积极的更新
    • 目前插件内已有的基本功能都不会转为收费, 可以放心使用
    ',28),d=[t];function n(o,c,h,s,p,u){return a(),l("div",null,d)}const f=e(r,[["render",n]]);export{g as __pageData,f as default}; diff --git a/assets/project_ClipboardManager_statement_index.md.6751fd19.lean.js b/assets/project_ClipboardManager_statement_index.md.fddb5934.lean.js similarity index 97% rename from assets/project_ClipboardManager_statement_index.md.6751fd19.lean.js rename to assets/project_ClipboardManager_statement_index.md.fddb5934.lean.js index 377fbcb7..3f1b5c2e 100644 --- a/assets/project_ClipboardManager_statement_index.md.6751fd19.lean.js +++ b/assets/project_ClipboardManager_statement_index.md.fddb5934.lean.js @@ -1 +1 @@ -import{_ as e,o as a,c as l,a as i}from"./app.33820b61.js";const g=JSON.parse('{"title":"Q&A","description":"","frontmatter":{"navbar":false},"headers":[{"level":2,"title":"为什么偶尔CPU占用特别高? 为什么预览图片时插件卡顿?","slug":"为什么偶尔cpu占用特别高-为什么预览图片时插件卡顿","link":"#为什么偶尔cpu占用特别高-为什么预览图片时插件卡顿","children":[]},{"level":2,"title":"为什么官方的剪贴板插件没有CPU占用高这个问题?","slug":"为什么官方的剪贴板插件没有cpu占用高这个问题","link":"#为什么官方的剪贴板插件没有cpu占用高这个问题","children":[]},{"level":2,"title":"启动报错, 读取剪切板出错","slug":"启动报错-读取剪切板出错","link":"#启动报错-读取剪切板出错","children":[]},{"level":2,"title":"为什么剪贴板记录会丢失?","slug":"为什么剪贴板记录会丢失","link":"#为什么剪贴板记录会丢失","children":[]},{"level":2,"title":"我对这个插件的安全性有担忧, 插件偷窃我的隐私怎么办?","slug":"我对这个插件的安全性有担忧-插件偷窃我的隐私怎么办","link":"#我对这个插件的安全性有担忧-插件偷窃我的隐私怎么办","children":[]},{"level":2,"title":"我不懂代码, 我也不会构建, 但是我担心你的插件会窃取我的隐私","slug":"我不懂代码-我也不会构建-但是我担心你的插件会窃取我的隐私","link":"#我不懂代码-我也不会构建-但是我担心你的插件会窃取我的隐私","children":[]},{"level":2,"title":"开源版本和插件市场版本的区别?","slug":"开源版本和插件市场版本的区别","link":"#开源版本和插件市场版本的区别","children":[]},{"level":2,"title":"为什么不开源了, 为什么要开始收费?","slug":"为什么不开源了-为什么要开始收费","link":"#为什么不开源了-为什么要开始收费","children":[]}],"relativePath":"project/ClipboardManager/statement/index.md","lastUpdated":1676737739000}'),r={name:"project/ClipboardManager/statement/index.md"},t=i("",28),d=[t];function n(o,c,h,s,p,u){return a(),l("div",null,d)}const f=e(r,[["render",n]]);export{g as __pageData,f as default}; +import{_ as e,o as a,c as l,a as i}from"./app.33820b61.js";const g=JSON.parse('{"title":"Q&A","description":"","frontmatter":{"navbar":false},"headers":[{"level":2,"title":"为什么偶尔CPU占用特别高? 为什么预览图片时插件卡顿?","slug":"为什么偶尔cpu占用特别高-为什么预览图片时插件卡顿","link":"#为什么偶尔cpu占用特别高-为什么预览图片时插件卡顿","children":[]},{"level":2,"title":"为什么官方的剪贴板插件没有CPU占用高这个问题?","slug":"为什么官方的剪贴板插件没有cpu占用高这个问题","link":"#为什么官方的剪贴板插件没有cpu占用高这个问题","children":[]},{"level":2,"title":"启动报错, 读取剪切板出错","slug":"启动报错-读取剪切板出错","link":"#启动报错-读取剪切板出错","children":[]},{"level":2,"title":"为什么剪贴板记录会丢失?","slug":"为什么剪贴板记录会丢失","link":"#为什么剪贴板记录会丢失","children":[]},{"level":2,"title":"我对这个插件的安全性有担忧, 插件偷窃我的隐私怎么办?","slug":"我对这个插件的安全性有担忧-插件偷窃我的隐私怎么办","link":"#我对这个插件的安全性有担忧-插件偷窃我的隐私怎么办","children":[]},{"level":2,"title":"我不懂代码, 我也不会构建, 但是我担心你的插件会窃取我的隐私","slug":"我不懂代码-我也不会构建-但是我担心你的插件会窃取我的隐私","link":"#我不懂代码-我也不会构建-但是我担心你的插件会窃取我的隐私","children":[]},{"level":2,"title":"开源版本和插件市场版本的区别?","slug":"开源版本和插件市场版本的区别","link":"#开源版本和插件市场版本的区别","children":[]},{"level":2,"title":"为什么不开源了, 为什么要开始收费?","slug":"为什么不开源了-为什么要开始收费","link":"#为什么不开源了-为什么要开始收费","children":[]}],"relativePath":"project/ClipboardManager/statement/index.md","lastUpdated":1676979063000}'),r={name:"project/ClipboardManager/statement/index.md"},t=i("",28),d=[t];function n(o,c,h,s,p,u){return a(),l("div",null,d)}const f=e(r,[["render",n]]);export{g as __pageData,f as default}; diff --git a/assets/project_ClipboardManager_vip_index.md.00c8bdb1.js b/assets/project_ClipboardManager_vip_index.md.8d894bfc.js similarity index 98% rename from assets/project_ClipboardManager_vip_index.md.00c8bdb1.js rename to assets/project_ClipboardManager_vip_index.md.8d894bfc.js index 8a6ddd67..b4b8529a 100644 --- a/assets/project_ClipboardManager_vip_index.md.00c8bdb1.js +++ b/assets/project_ClipboardManager_vip_index.md.8d894bfc.js @@ -1 +1 @@ -import{_ as a,r as n,o as c,c as d,b as e,d as t,e as o,a as i}from"./app.33820b61.js";const s="/assets/vip-webdav.2e7c539c.png",r="/assets/vip-highlight.e3827906.png",B=JSON.parse('{"title":"插件会员","description":"","frontmatter":{},"headers":[{"level":2,"title":"会员权益","slug":"会员权益","link":"#会员权益","children":[]},{"level":2,"title":"会员定价","slug":"会员定价","link":"#会员定价","children":[]},{"level":2,"title":"WebDav同步功能","slug":"webdav同步功能","link":"#webdav同步功能","children":[]},{"level":2,"title":"代码高亮功能","slug":"代码高亮功能","link":"#代码高亮功能","children":[]},{"level":2,"title":"更多内容","slug":"更多内容","link":"#更多内容","children":[]}],"relativePath":"project/ClipboardManager/vip/index.md","lastUpdated":1676737739000}'),p={name:"project/ClipboardManager/vip/index.md"},h=i('

    插件会员

    TIP

    超级剪贴板是一款 “随心所欲” 的软件。您可以永久免费使用它。

    但是,如果您真的喜欢它,您可以付费支持它的发展。作为答谢,您将获得更多更方便的功能。这取决于您,如果您不想,也没关系。谢谢你,祝你有美好的一天!☀️

    会员权益

    ',3),_=e("strong",null,"插件会员",-1),u=e("code",null,"WebDav数据多端同步",-1),g=e("code",null,"支持保存2000条历史记录",-1),b=e("code",null,"不限制历史记录过期时间",-1),m=e("code",null,"文本内容增强, 按住Ctrl/Command点击文本/链接 可以直接预览/跳转",-1),v=e("code",null,"图片预览增强, 按住Ctrl/Command点击图片 可以直接预览",-1),k=e("code",null,"文件预览增强, 按住Ctrl/Command点击文件 可以打开其所在文件夹",-1),f=e("code",null,"自定义分类排序",-1),x=e("code",null,"预览页代码高亮",-1),T=e("code",null,"关闭剪贴板图片记录",-1),C=e("code",null,"插件使用统计",-1),D=e("li",null,[e("strong",null,"...")],-1),y=e("strong",null,"uTools会员",-1),N=e("code",null,"插件使用统计",-1),w=i('

    会员定价

    WARNING

    • 插件会员为大版本买断制,购买后即可享用当前版本(2.x)后续所有更新的会员内容
    • 插件会员为虚拟商品,购买后不支持退款
    • 插件会员的价格是浮动的,随着功能和权益的增加,不排除涨价的可能
    • 购买插件会员后如果出现相关问题,欢迎加入QQ群反馈

    插件会员定价8元,登录uTools账号后点击插件工具栏中个人中心图标进入购买页面

    购买后可使用会员功能,不购买不影响基本功能的使用,希望大家多多理解,按需购买

    WebDav同步功能

    WARNING

    如果剪贴板数据体积过大,可能出现同步时间过长、同步失败等问题

    建议及时删除保存在超级剪贴板内的图片,或关闭记录图片到剪贴板

    插件会员支持通过WebDav同步剪贴板数据

    获取服务器地址 账号 密钥后,仅需在插件内的设置页面添加WebDav配置后,

    每次本地数据库发生变化,都会将最新数据同步到同步到服务器(须开启插件内的自动同步 否则需要手动同步)

    WebDav

    • 如果配置了WebDav 则每天第一次进入插件时会自动从服务器拉取最新数据
    • 如果设置了自动同步 每次本地数据变化将自动同步本地数据到服务器
      • 插件会缓存云端数据文件的ETag 如果云端数据有更新 则采用云端数据覆盖本地数据
      • 数据文件的上传和下载都开启了gzip以节省流量与带宽
      • 清空本地数据库的同时也会触发云端文件清空
      • 可以选择关闭图片记录 以降低同步的数据文件体积 提高同步效率
    • 插件仅在每次启动时主动从云端拉取数据 云端数据的更新不会自动同步到本地
    • 可以通过点击工具栏按钮主动拉取云端数据到本地或上传数据到云端

    相关链接:

    代码高亮功能

    插件使用Shiki作为代码高亮库,为了压缩插件体积、提高代码执行效率,其相关依赖都将从CDN动态加载

    支持在设置页修改代码高亮的主题、可选语言、CDN地址,设置的首个语言为展开预览后的默认语言

    HighLight

    • 默认CDN地址: https://unpkg.com/shiki@0.14.1/
    • 默认主题: one-dark-pro
    • 默认语言: javascript css html json markdown php python ruby shellscript sql java c cpp csharp go

    更多可用主题/语言,见Github仓库:Shiki

    更多内容

    疑难解答

    ',21);function W(j,S,V,A,I,P){const l=n("Badge");return c(),d("div",null,[h,e("ul",null,[e("li",null,[_,e("ul",null,[e("li",null,[u,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[g,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[b,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[m,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[v,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[k,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[f,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[x,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[T,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[C,t(),o(l,{type:"tip",text:"已上线"})]),D])]),e("li",null,[y,e("ul",null,[e("li",null,[N,t(),o(l,{type:"tip",text:"已上线"})])])])]),w])}const R=a(p,[["render",W]]);export{B as __pageData,R as default}; +import{_ as a,r as n,o as c,c as d,b as e,d as t,e as o,a as i}from"./app.33820b61.js";const s="/assets/vip-webdav.2e7c539c.png",r="/assets/vip-highlight.e3827906.png",B=JSON.parse('{"title":"插件会员","description":"","frontmatter":{},"headers":[{"level":2,"title":"会员权益","slug":"会员权益","link":"#会员权益","children":[]},{"level":2,"title":"会员定价","slug":"会员定价","link":"#会员定价","children":[]},{"level":2,"title":"WebDav同步功能","slug":"webdav同步功能","link":"#webdav同步功能","children":[]},{"level":2,"title":"代码高亮功能","slug":"代码高亮功能","link":"#代码高亮功能","children":[]},{"level":2,"title":"更多内容","slug":"更多内容","link":"#更多内容","children":[]}],"relativePath":"project/ClipboardManager/vip/index.md","lastUpdated":1676979063000}'),p={name:"project/ClipboardManager/vip/index.md"},h=i('

    插件会员

    TIP

    超级剪贴板是一款 “随心所欲” 的软件。您可以永久免费使用它。

    但是,如果您真的喜欢它,您可以付费支持它的发展。作为答谢,您将获得更多更方便的功能。这取决于您,如果您不想,也没关系。谢谢你,祝你有美好的一天!☀️

    会员权益

    ',3),_=e("strong",null,"插件会员",-1),u=e("code",null,"WebDav数据多端同步",-1),g=e("code",null,"支持保存2000条历史记录",-1),b=e("code",null,"不限制历史记录过期时间",-1),m=e("code",null,"文本内容增强, 按住Ctrl/Command点击文本/链接 可以直接预览/跳转",-1),v=e("code",null,"图片预览增强, 按住Ctrl/Command点击图片 可以直接预览",-1),k=e("code",null,"文件预览增强, 按住Ctrl/Command点击文件 可以打开其所在文件夹",-1),f=e("code",null,"自定义分类排序",-1),x=e("code",null,"预览页代码高亮",-1),T=e("code",null,"关闭剪贴板图片记录",-1),C=e("code",null,"插件使用统计",-1),D=e("li",null,[e("strong",null,"...")],-1),y=e("strong",null,"uTools会员",-1),N=e("code",null,"插件使用统计",-1),w=i('

    会员定价

    WARNING

    • 插件会员为大版本买断制,购买后即可享用当前版本(2.x)后续所有更新的会员内容
    • 插件会员为虚拟商品,购买后不支持退款
    • 插件会员的价格是浮动的,随着功能和权益的增加,不排除涨价的可能
    • 购买插件会员后如果出现相关问题,欢迎加入QQ群反馈

    插件会员定价8元,登录uTools账号后点击插件工具栏中个人中心图标进入购买页面

    购买后可使用会员功能,不购买不影响基本功能的使用,希望大家多多理解,按需购买

    WebDav同步功能

    WARNING

    如果剪贴板数据体积过大,可能出现同步时间过长、同步失败等问题

    建议及时删除保存在超级剪贴板内的图片,或关闭记录图片到剪贴板

    插件会员支持通过WebDav同步剪贴板数据

    获取服务器地址 账号 密钥后,仅需在插件内的设置页面添加WebDav配置后,

    每次本地数据库发生变化,都会将最新数据同步到同步到服务器(须开启插件内的自动同步 否则需要手动同步)

    WebDav

    • 如果配置了WebDav 则每天第一次进入插件时会自动从服务器拉取最新数据
    • 如果设置了自动同步 每次本地数据变化将自动同步本地数据到服务器
      • 插件会缓存云端数据文件的ETag 如果云端数据有更新 则采用云端数据覆盖本地数据
      • 数据文件的上传和下载都开启了gzip以节省流量与带宽
      • 清空本地数据库的同时也会触发云端文件清空
      • 可以选择关闭图片记录 以降低同步的数据文件体积 提高同步效率
    • 插件仅在每次启动时主动从云端拉取数据 云端数据的更新不会自动同步到本地
    • 可以通过点击工具栏按钮主动拉取云端数据到本地或上传数据到云端

    相关链接:

    代码高亮功能

    插件使用Shiki作为代码高亮库,为了压缩插件体积、提高代码执行效率,其相关依赖都将从CDN动态加载

    支持在设置页修改代码高亮的主题、可选语言、CDN地址,设置的首个语言为展开预览后的默认语言

    HighLight

    • 默认CDN地址: https://unpkg.com/shiki@0.14.1/
    • 默认主题: one-dark-pro
    • 默认语言: javascript css html json markdown php python ruby shellscript sql java c cpp csharp go

    更多可用主题/语言,见Github仓库:Shiki

    更多内容

    疑难解答

    ',21);function W(j,S,V,A,I,P){const l=n("Badge");return c(),d("div",null,[h,e("ul",null,[e("li",null,[_,e("ul",null,[e("li",null,[u,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[g,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[b,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[m,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[v,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[k,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[f,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[x,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[T,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[C,t(),o(l,{type:"tip",text:"已上线"})]),D])]),e("li",null,[y,e("ul",null,[e("li",null,[N,t(),o(l,{type:"tip",text:"已上线"})])])])]),w])}const R=a(p,[["render",W]]);export{B as __pageData,R as default}; diff --git a/assets/project_ClipboardManager_vip_index.md.00c8bdb1.lean.js b/assets/project_ClipboardManager_vip_index.md.8d894bfc.lean.js similarity index 94% rename from assets/project_ClipboardManager_vip_index.md.00c8bdb1.lean.js rename to assets/project_ClipboardManager_vip_index.md.8d894bfc.lean.js index b1b75497..925e5cea 100644 --- a/assets/project_ClipboardManager_vip_index.md.00c8bdb1.lean.js +++ b/assets/project_ClipboardManager_vip_index.md.8d894bfc.lean.js @@ -1 +1 @@ -import{_ as a,r as n,o as c,c as d,b as e,d as t,e as o,a as i}from"./app.33820b61.js";const s="/assets/vip-webdav.2e7c539c.png",r="/assets/vip-highlight.e3827906.png",B=JSON.parse('{"title":"插件会员","description":"","frontmatter":{},"headers":[{"level":2,"title":"会员权益","slug":"会员权益","link":"#会员权益","children":[]},{"level":2,"title":"会员定价","slug":"会员定价","link":"#会员定价","children":[]},{"level":2,"title":"WebDav同步功能","slug":"webdav同步功能","link":"#webdav同步功能","children":[]},{"level":2,"title":"代码高亮功能","slug":"代码高亮功能","link":"#代码高亮功能","children":[]},{"level":2,"title":"更多内容","slug":"更多内容","link":"#更多内容","children":[]}],"relativePath":"project/ClipboardManager/vip/index.md","lastUpdated":1676737739000}'),p={name:"project/ClipboardManager/vip/index.md"},h=i("",3),_=e("strong",null,"插件会员",-1),u=e("code",null,"WebDav数据多端同步",-1),g=e("code",null,"支持保存2000条历史记录",-1),b=e("code",null,"不限制历史记录过期时间",-1),m=e("code",null,"文本内容增强, 按住Ctrl/Command点击文本/链接 可以直接预览/跳转",-1),v=e("code",null,"图片预览增强, 按住Ctrl/Command点击图片 可以直接预览",-1),k=e("code",null,"文件预览增强, 按住Ctrl/Command点击文件 可以打开其所在文件夹",-1),f=e("code",null,"自定义分类排序",-1),x=e("code",null,"预览页代码高亮",-1),T=e("code",null,"关闭剪贴板图片记录",-1),C=e("code",null,"插件使用统计",-1),D=e("li",null,[e("strong",null,"...")],-1),y=e("strong",null,"uTools会员",-1),N=e("code",null,"插件使用统计",-1),w=i("",21);function W(j,S,V,A,I,P){const l=n("Badge");return c(),d("div",null,[h,e("ul",null,[e("li",null,[_,e("ul",null,[e("li",null,[u,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[g,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[b,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[m,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[v,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[k,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[f,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[x,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[T,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[C,t(),o(l,{type:"tip",text:"已上线"})]),D])]),e("li",null,[y,e("ul",null,[e("li",null,[N,t(),o(l,{type:"tip",text:"已上线"})])])])]),w])}const R=a(p,[["render",W]]);export{B as __pageData,R as default}; +import{_ as a,r as n,o as c,c as d,b as e,d as t,e as o,a as i}from"./app.33820b61.js";const s="/assets/vip-webdav.2e7c539c.png",r="/assets/vip-highlight.e3827906.png",B=JSON.parse('{"title":"插件会员","description":"","frontmatter":{},"headers":[{"level":2,"title":"会员权益","slug":"会员权益","link":"#会员权益","children":[]},{"level":2,"title":"会员定价","slug":"会员定价","link":"#会员定价","children":[]},{"level":2,"title":"WebDav同步功能","slug":"webdav同步功能","link":"#webdav同步功能","children":[]},{"level":2,"title":"代码高亮功能","slug":"代码高亮功能","link":"#代码高亮功能","children":[]},{"level":2,"title":"更多内容","slug":"更多内容","link":"#更多内容","children":[]}],"relativePath":"project/ClipboardManager/vip/index.md","lastUpdated":1676979063000}'),p={name:"project/ClipboardManager/vip/index.md"},h=i("",3),_=e("strong",null,"插件会员",-1),u=e("code",null,"WebDav数据多端同步",-1),g=e("code",null,"支持保存2000条历史记录",-1),b=e("code",null,"不限制历史记录过期时间",-1),m=e("code",null,"文本内容增强, 按住Ctrl/Command点击文本/链接 可以直接预览/跳转",-1),v=e("code",null,"图片预览增强, 按住Ctrl/Command点击图片 可以直接预览",-1),k=e("code",null,"文件预览增强, 按住Ctrl/Command点击文件 可以打开其所在文件夹",-1),f=e("code",null,"自定义分类排序",-1),x=e("code",null,"预览页代码高亮",-1),T=e("code",null,"关闭剪贴板图片记录",-1),C=e("code",null,"插件使用统计",-1),D=e("li",null,[e("strong",null,"...")],-1),y=e("strong",null,"uTools会员",-1),N=e("code",null,"插件使用统计",-1),w=i("",21);function W(j,S,V,A,I,P){const l=n("Badge");return c(),d("div",null,[h,e("ul",null,[e("li",null,[_,e("ul",null,[e("li",null,[u,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[g,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[b,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[m,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[v,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[k,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[f,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[x,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[T,t(),o(l,{type:"tip",text:"已上线"})]),e("li",null,[C,t(),o(l,{type:"tip",text:"已上线"})]),D])]),e("li",null,[y,e("ul",null,[e("li",null,[N,t(),o(l,{type:"tip",text:"已上线"})])])])]),w])}const R=a(p,[["render",W]]);export{B as __pageData,R as default}; diff --git a/assets/project_SmartWordBreak_index.md.8198941b.js b/assets/project_SmartWordBreak_index.md.6364a91a.js similarity index 97% rename from assets/project_SmartWordBreak_index.md.8198941b.js rename to assets/project_SmartWordBreak_index.md.6364a91a.js index 7ea79ab1..372447d2 100644 --- a/assets/project_SmartWordBreak_index.md.8198941b.js +++ b/assets/project_SmartWordBreak_index.md.6364a91a.js @@ -1 +1 @@ -import{r as a,o as l,c as i,e as r,n,g as s,a as o}from"./app.33820b61.js";const c="/assets/img1.c8b019e1.png",d="/assets/img2.e389ad4d.png",_="/assets/logo.b98f7a12.png",p=o('

    🔰 开始使用

    服务器不会保留处理的数据, 但请避免使用此功能处理敏感数据

    • ✅ 支持选中文本后通过超级面板直接进入分词
    • ✅ 支持直接读取剪贴板文本分词
    • ✅ 支持单选/拖拽/跨段落快速拖选
    • ✅ 支持一键合并复制/粘贴/翻译/搜索
    • ✅ 普通用户有每日免费额度 每日0:00重置
    • ✅ 优雅、迅速的动效与交互 适配深色模式
    • ✅ 可以通过插件内入口获取更多额度
    • ✅ 与超级剪贴板插件集成,一次购买 多处使用

    📚 安装方式

    ',8),b=JSON.parse('{"title":"超级分词","description":"","frontmatter":{"title":"超级分词","navbar":false},"headers":[{"level":2,"title":"🔰 开始使用","slug":"🔰-开始使用","link":"#🔰-开始使用","children":[]},{"level":2,"title":"📚 安装方式","slug":"📚-安装方式","link":"#📚-安装方式","children":[]}],"relativePath":"project/SmartWordBreak/index.md","lastUpdated":1676737739000}'),h={name:"project/SmartWordBreak/index.md"},T=Object.assign(h,{setup(g){const e={subTitle:"✨ 智慧分词,快速提取文本关键词。",logo:_,linkList:[{content:"⭐ 插件发布页",target:"https://yuanliao.info/d/5722/29"},{content:"🌎 Q&A",target:"./statement/"},{content:"🚚 更新日志",target:"./log/"}]};return(m,u)=>{const t=a("Title");return l(),i("div",null,[r(t,n(s(e)),null,16),p])}}});export{b as __pageData,T as default}; +import{r as a,o as l,c as i,e as r,n,g as s,a as o}from"./app.33820b61.js";const c="/assets/img1.c8b019e1.png",d="/assets/img2.e389ad4d.png",_="/assets/logo.b98f7a12.png",p=o('

    🔰 开始使用

    服务器不会保留处理的数据, 但请避免使用此功能处理敏感数据

    • ✅ 支持选中文本后通过超级面板直接进入分词
    • ✅ 支持直接读取剪贴板文本分词
    • ✅ 支持单选/拖拽/跨段落快速拖选
    • ✅ 支持一键合并复制/粘贴/翻译/搜索
    • ✅ 普通用户有每日免费额度 每日0:00重置
    • ✅ 优雅、迅速的动效与交互 适配深色模式
    • ✅ 可以通过插件内入口获取更多额度
    • ✅ 与超级剪贴板插件集成,一次购买 多处使用

    📚 安装方式

    ',8),b=JSON.parse('{"title":"超级分词","description":"","frontmatter":{"title":"超级分词","navbar":false},"headers":[{"level":2,"title":"🔰 开始使用","slug":"🔰-开始使用","link":"#🔰-开始使用","children":[]},{"level":2,"title":"📚 安装方式","slug":"📚-安装方式","link":"#📚-安装方式","children":[]}],"relativePath":"project/SmartWordBreak/index.md","lastUpdated":1676979063000}'),h={name:"project/SmartWordBreak/index.md"},T=Object.assign(h,{setup(g){const e={subTitle:"✨ 智慧分词,快速提取文本关键词。",logo:_,linkList:[{content:"⭐ 插件发布页",target:"https://yuanliao.info/d/5722/29"},{content:"🌎 Q&A",target:"./statement/"},{content:"🚚 更新日志",target:"./log/"}]};return(m,u)=>{const t=a("Title");return l(),i("div",null,[r(t,n(s(e)),null,16),p])}}});export{b as __pageData,T as default}; diff --git a/assets/project_SmartWordBreak_index.md.8198941b.lean.js b/assets/project_SmartWordBreak_index.md.6364a91a.lean.js similarity index 93% rename from assets/project_SmartWordBreak_index.md.8198941b.lean.js rename to assets/project_SmartWordBreak_index.md.6364a91a.lean.js index bdc27471..807c5f3a 100644 --- a/assets/project_SmartWordBreak_index.md.8198941b.lean.js +++ b/assets/project_SmartWordBreak_index.md.6364a91a.lean.js @@ -1 +1 @@ -import{r as a,o as l,c as i,e as r,n,g as s,a as o}from"./app.33820b61.js";const c="/assets/img1.c8b019e1.png",d="/assets/img2.e389ad4d.png",_="/assets/logo.b98f7a12.png",p=o("",8),b=JSON.parse('{"title":"超级分词","description":"","frontmatter":{"title":"超级分词","navbar":false},"headers":[{"level":2,"title":"🔰 开始使用","slug":"🔰-开始使用","link":"#🔰-开始使用","children":[]},{"level":2,"title":"📚 安装方式","slug":"📚-安装方式","link":"#📚-安装方式","children":[]}],"relativePath":"project/SmartWordBreak/index.md","lastUpdated":1676737739000}'),h={name:"project/SmartWordBreak/index.md"},T=Object.assign(h,{setup(g){const e={subTitle:"✨ 智慧分词,快速提取文本关键词。",logo:_,linkList:[{content:"⭐ 插件发布页",target:"https://yuanliao.info/d/5722/29"},{content:"🌎 Q&A",target:"./statement/"},{content:"🚚 更新日志",target:"./log/"}]};return(m,u)=>{const t=a("Title");return l(),i("div",null,[r(t,n(s(e)),null,16),p])}}});export{b as __pageData,T as default}; +import{r as a,o as l,c as i,e as r,n,g as s,a as o}from"./app.33820b61.js";const c="/assets/img1.c8b019e1.png",d="/assets/img2.e389ad4d.png",_="/assets/logo.b98f7a12.png",p=o("",8),b=JSON.parse('{"title":"超级分词","description":"","frontmatter":{"title":"超级分词","navbar":false},"headers":[{"level":2,"title":"🔰 开始使用","slug":"🔰-开始使用","link":"#🔰-开始使用","children":[]},{"level":2,"title":"📚 安装方式","slug":"📚-安装方式","link":"#📚-安装方式","children":[]}],"relativePath":"project/SmartWordBreak/index.md","lastUpdated":1676979063000}'),h={name:"project/SmartWordBreak/index.md"},T=Object.assign(h,{setup(g){const e={subTitle:"✨ 智慧分词,快速提取文本关键词。",logo:_,linkList:[{content:"⭐ 插件发布页",target:"https://yuanliao.info/d/5722/29"},{content:"🌎 Q&A",target:"./statement/"},{content:"🚚 更新日志",target:"./log/"}]};return(m,u)=>{const t=a("Title");return l(),i("div",null,[r(t,n(s(e)),null,16),p])}}});export{b as __pageData,T as default}; diff --git a/assets/project_SmartWordBreak_log_index.md.3ca84f95.js b/assets/project_SmartWordBreak_log_index.md.02ecbe98.js similarity index 97% rename from assets/project_SmartWordBreak_log_index.md.3ca84f95.js rename to assets/project_SmartWordBreak_log_index.md.02ecbe98.js index b7d1bb7b..c2a474e4 100644 --- a/assets/project_SmartWordBreak_log_index.md.3ca84f95.js +++ b/assets/project_SmartWordBreak_log_index.md.02ecbe98.js @@ -1 +1 @@ -import{_ as e,o as a,c as l,a as i}from"./app.33820b61.js";const f=JSON.parse('{"title":"更新日志","description":"","frontmatter":{},"headers":[{"level":2,"title":"v1.0.5","slug":"v1-0-5","link":"#v1-0-5","children":[]},{"level":2,"title":"v1.0.4","slug":"v1-0-4","link":"#v1-0-4","children":[]},{"level":2,"title":"v1.0.3","slug":"v1-0-3","link":"#v1-0-3","children":[]},{"level":2,"title":"v1.0.2","slug":"v1-0-2","link":"#v1-0-2","children":[]},{"level":2,"title":"v1.0.1","slug":"v1-0-1","link":"#v1-0-1","children":[]},{"level":2,"title":"v1.0.0","slug":"v1-0-0","link":"#v1-0-0","children":[]}],"relativePath":"project/SmartWordBreak/log/index.md","lastUpdated":1676737739000}'),d={name:"project/SmartWordBreak/log/index.md"},t=i('

    更新日志

    v1.0.5

    2022-12-17

    • feat: 限免活动 每日免费额度调整为99 移除充值入口
    • fix: 修复历史记录显示问题

    v1.0.4

    2022-09-25

    • feat: 分词上限提高到了1000个字符
    • feat: token支持本地缓存

    v1.0.3

    2022-09-19

    • feat: 增加历史记录功能
    • fix: 移除了在tag外按下鼠标拖选的功能

    v1.0.2

    2022-09-13

    • feat: 支持跨段快速拖选
    • feat: 分词页添加了搜索粘贴功能
    • feat: 优化换行符在分词页的表现 支持包含换行符拖选

    v1.0.1

    2022-09-13

    • feat: 增加了拖选过程中的动效
    • feat: 调整了按钮样式与颜色
    • fix: 移除了碍事的toast

    v1.0.0

    2022-09-11

    • release: v1.0.0发布
    ',19),r=[t];function c(n,h,o,v,s,u){return a(),l("div",null,r)}const p=e(d,[["render",c]]);export{f as __pageData,p as default}; +import{_ as e,o as a,c as l,a as i}from"./app.33820b61.js";const f=JSON.parse('{"title":"更新日志","description":"","frontmatter":{},"headers":[{"level":2,"title":"v1.0.5","slug":"v1-0-5","link":"#v1-0-5","children":[]},{"level":2,"title":"v1.0.4","slug":"v1-0-4","link":"#v1-0-4","children":[]},{"level":2,"title":"v1.0.3","slug":"v1-0-3","link":"#v1-0-3","children":[]},{"level":2,"title":"v1.0.2","slug":"v1-0-2","link":"#v1-0-2","children":[]},{"level":2,"title":"v1.0.1","slug":"v1-0-1","link":"#v1-0-1","children":[]},{"level":2,"title":"v1.0.0","slug":"v1-0-0","link":"#v1-0-0","children":[]}],"relativePath":"project/SmartWordBreak/log/index.md","lastUpdated":1676979063000}'),d={name:"project/SmartWordBreak/log/index.md"},t=i('

    更新日志

    v1.0.5

    2022-12-17

    • feat: 限免活动 每日免费额度调整为99 移除充值入口
    • fix: 修复历史记录显示问题

    v1.0.4

    2022-09-25

    • feat: 分词上限提高到了1000个字符
    • feat: token支持本地缓存

    v1.0.3

    2022-09-19

    • feat: 增加历史记录功能
    • fix: 移除了在tag外按下鼠标拖选的功能

    v1.0.2

    2022-09-13

    • feat: 支持跨段快速拖选
    • feat: 分词页添加了搜索粘贴功能
    • feat: 优化换行符在分词页的表现 支持包含换行符拖选

    v1.0.1

    2022-09-13

    • feat: 增加了拖选过程中的动效
    • feat: 调整了按钮样式与颜色
    • fix: 移除了碍事的toast

    v1.0.0

    2022-09-11

    • release: v1.0.0发布
    ',19),r=[t];function c(n,h,o,v,s,u){return a(),l("div",null,r)}const p=e(d,[["render",c]]);export{f as __pageData,p as default}; diff --git a/assets/project_SmartWordBreak_log_index.md.3ca84f95.lean.js b/assets/project_SmartWordBreak_log_index.md.02ecbe98.lean.js similarity index 92% rename from assets/project_SmartWordBreak_log_index.md.3ca84f95.lean.js rename to assets/project_SmartWordBreak_log_index.md.02ecbe98.lean.js index 530933b3..65079f25 100644 --- a/assets/project_SmartWordBreak_log_index.md.3ca84f95.lean.js +++ b/assets/project_SmartWordBreak_log_index.md.02ecbe98.lean.js @@ -1 +1 @@ -import{_ as e,o as a,c as l,a as i}from"./app.33820b61.js";const f=JSON.parse('{"title":"更新日志","description":"","frontmatter":{},"headers":[{"level":2,"title":"v1.0.5","slug":"v1-0-5","link":"#v1-0-5","children":[]},{"level":2,"title":"v1.0.4","slug":"v1-0-4","link":"#v1-0-4","children":[]},{"level":2,"title":"v1.0.3","slug":"v1-0-3","link":"#v1-0-3","children":[]},{"level":2,"title":"v1.0.2","slug":"v1-0-2","link":"#v1-0-2","children":[]},{"level":2,"title":"v1.0.1","slug":"v1-0-1","link":"#v1-0-1","children":[]},{"level":2,"title":"v1.0.0","slug":"v1-0-0","link":"#v1-0-0","children":[]}],"relativePath":"project/SmartWordBreak/log/index.md","lastUpdated":1676737739000}'),d={name:"project/SmartWordBreak/log/index.md"},t=i("",19),r=[t];function c(n,h,o,v,s,u){return a(),l("div",null,r)}const p=e(d,[["render",c]]);export{f as __pageData,p as default}; +import{_ as e,o as a,c as l,a as i}from"./app.33820b61.js";const f=JSON.parse('{"title":"更新日志","description":"","frontmatter":{},"headers":[{"level":2,"title":"v1.0.5","slug":"v1-0-5","link":"#v1-0-5","children":[]},{"level":2,"title":"v1.0.4","slug":"v1-0-4","link":"#v1-0-4","children":[]},{"level":2,"title":"v1.0.3","slug":"v1-0-3","link":"#v1-0-3","children":[]},{"level":2,"title":"v1.0.2","slug":"v1-0-2","link":"#v1-0-2","children":[]},{"level":2,"title":"v1.0.1","slug":"v1-0-1","link":"#v1-0-1","children":[]},{"level":2,"title":"v1.0.0","slug":"v1-0-0","link":"#v1-0-0","children":[]}],"relativePath":"project/SmartWordBreak/log/index.md","lastUpdated":1676979063000}'),d={name:"project/SmartWordBreak/log/index.md"},t=i("",19),r=[t];function c(n,h,o,v,s,u){return a(),l("div",null,r)}const p=e(d,[["render",c]]);export{f as __pageData,p as default}; diff --git a/assets/project_SmartWordBreak_statement_index.md.08faf5e0.js b/assets/project_SmartWordBreak_statement_index.md.4c33c737.js similarity index 96% rename from assets/project_SmartWordBreak_statement_index.md.08faf5e0.js rename to assets/project_SmartWordBreak_statement_index.md.4c33c737.js index 1900523f..7abe8a25 100644 --- a/assets/project_SmartWordBreak_statement_index.md.08faf5e0.js +++ b/assets/project_SmartWordBreak_statement_index.md.4c33c737.js @@ -1 +1 @@ -import{_ as e,o as a,c as o,a as t}from"./app.33820b61.js";const h=JSON.parse('{"title":"Q&A","description":"","frontmatter":{"navbar":false},"headers":[],"relativePath":"project/SmartWordBreak/statement/index.md","lastUpdated":1676737739000}'),i={name:"project/SmartWordBreak/statement/index.md"},l=t('

    Q&A

    • Q: 为什么要收费
    • A: 此功能需要服务器资源, 而服务器资源有限, 故暂时只开放部分的免费资源给大家使用, 普通用户每日有部分免费额度, 额度每日0:00重置

    • Q: 我支付了,但是没有收到额度
    • A: 支付成功后,插件会自动获取最新用户信息,如果信息没有自动更新,请尝试退出插件后重新进入,如果仍未收到额度,请加入QQ群 769115389并联系我,我会尽快核实并为你解决

    • Q: 我之前赞赏过,可以有优惠吗
    • A: 2022年9月13日0:00前,赞赏过我的uTools用户,请发送:
      • UUID(超级分词插件内展示)
      • 赞赏金额
      • 赞赏时间
      • 支付截图
    • 到邮箱ZiuChen@outlook.com,邮箱主题为:申请超级分词赞赏额度,我将在核实后为你提供赞赏金额+15%的额度,感谢你的支持!💖。
    ',6),r=[l];function c(d,n,s,_,m,p){return a(),o("div",null,r)}const f=e(i,[["render",c]]);export{h as __pageData,f as default}; +import{_ as e,o as a,c as o,a as t}from"./app.33820b61.js";const h=JSON.parse('{"title":"Q&A","description":"","frontmatter":{"navbar":false},"headers":[],"relativePath":"project/SmartWordBreak/statement/index.md","lastUpdated":1676979063000}'),i={name:"project/SmartWordBreak/statement/index.md"},l=t('

    Q&A

    • Q: 为什么要收费
    • A: 此功能需要服务器资源, 而服务器资源有限, 故暂时只开放部分的免费资源给大家使用, 普通用户每日有部分免费额度, 额度每日0:00重置

    • Q: 我支付了,但是没有收到额度
    • A: 支付成功后,插件会自动获取最新用户信息,如果信息没有自动更新,请尝试退出插件后重新进入,如果仍未收到额度,请加入QQ群 769115389并联系我,我会尽快核实并为你解决

    • Q: 我之前赞赏过,可以有优惠吗
    • A: 2022年9月13日0:00前,赞赏过我的uTools用户,请发送:
      • UUID(超级分词插件内展示)
      • 赞赏金额
      • 赞赏时间
      • 支付截图
    • 到邮箱ZiuChen@outlook.com,邮箱主题为:申请超级分词赞赏额度,我将在核实后为你提供赞赏金额+15%的额度,感谢你的支持!💖。
    ',6),r=[l];function c(d,n,s,_,m,p){return a(),o("div",null,r)}const f=e(i,[["render",c]]);export{h as __pageData,f as default}; diff --git a/assets/project_SmartWordBreak_statement_index.md.08faf5e0.lean.js b/assets/project_SmartWordBreak_statement_index.md.4c33c737.lean.js similarity index 85% rename from assets/project_SmartWordBreak_statement_index.md.08faf5e0.lean.js rename to assets/project_SmartWordBreak_statement_index.md.4c33c737.lean.js index c01f31bd..8f4b0787 100644 --- a/assets/project_SmartWordBreak_statement_index.md.08faf5e0.lean.js +++ b/assets/project_SmartWordBreak_statement_index.md.4c33c737.lean.js @@ -1 +1 @@ -import{_ as e,o as a,c as o,a as t}from"./app.33820b61.js";const h=JSON.parse('{"title":"Q&A","description":"","frontmatter":{"navbar":false},"headers":[],"relativePath":"project/SmartWordBreak/statement/index.md","lastUpdated":1676737739000}'),i={name:"project/SmartWordBreak/statement/index.md"},l=t("",6),r=[l];function c(d,n,s,_,m,p){return a(),o("div",null,r)}const f=e(i,[["render",c]]);export{h as __pageData,f as default}; +import{_ as e,o as a,c as o,a as t}from"./app.33820b61.js";const h=JSON.parse('{"title":"Q&A","description":"","frontmatter":{"navbar":false},"headers":[],"relativePath":"project/SmartWordBreak/statement/index.md","lastUpdated":1676979063000}'),i={name:"project/SmartWordBreak/statement/index.md"},l=t("",6),r=[l];function c(d,n,s,_,m,p){return a(),o("div",null,r)}const f=e(i,[["render",c]]);export{h as __pageData,f as default}; diff --git a/assets/self_index.md.5b8fe7b6.js b/assets/self_index.md.e7b0b4e0.js similarity index 99% rename from assets/self_index.md.5b8fe7b6.js rename to assets/self_index.md.e7b0b4e0.js index 40a96f8c..9f270145 100644 --- a/assets/self_index.md.5b8fe7b6.js +++ b/assets/self_index.md.e7b0b4e0.js @@ -1 +1 @@ -import{_ as e,o,c as a,a as l}from"./app.33820b61.js";const t="/logo.png",i="/assets/2.7aeaaf23.png",s="/assets/1.136ffa4a.png",_=JSON.parse('{"title":"个人介绍","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"技术栈","slug":"技术栈","link":"#技术栈","children":[{"level":3,"title":"前端技术","slug":"前端技术","link":"#前端技术","children":[]},{"level":3,"title":"后端技术","slug":"后端技术","link":"#后端技术","children":[]},{"level":3,"title":"相关技能","slug":"相关技能","link":"#相关技能","children":[]}]},{"level":2,"title":"获得奖项","slug":"获得奖项","link":"#获得奖项","children":[{"level":3,"title":"Microsoft Edge 浏览器开拓者大赛 开拓之星","slug":"microsoft-edge-浏览器开拓者大赛-开拓之星","link":"#microsoft-edge-浏览器开拓者大赛-开拓之星","children":[]},{"level":3,"title":"稀土掘金2022编程挑战赛 三等奖","slug":"稀土掘金2022编程挑战赛-三等奖","link":"#稀土掘金2022编程挑战赛-三等奖","children":[]},{"level":3,"title":"入选“扬帆计划·中央和国家机关大学生实习”","slug":"入选-扬帆计划·中央和国家机关大学生实习","link":"#入选-扬帆计划·中央和国家机关大学生实习","children":[]},{"level":3,"title":"100周年现场志愿者","slug":"_100周年现场志愿者","link":"#_100周年现场志愿者","children":[]},{"level":3,"title":"优秀学生干部、优秀共青团员","slug":"优秀学生干部、优秀共青团员","link":"#优秀学生干部、优秀共青团员","children":[]},{"level":3,"title":"社会工作优秀奖学金","slug":"社会工作优秀奖学金","link":"#社会工作优秀奖学金","children":[]}]},{"level":2,"title":"相关链接","slug":"相关链接","link":"#相关链接","children":[]}],"relativePath":"self/index.md","lastUpdated":1676737739000}'),r={name:"self/index.md"},d=l('

    个人介绍

    logo

    北京交通大学(BeijingJiaoTong University)电子信息工程学院本科在读

    • 熟悉ES6特性, 有前端领域开发经验, 能独立完成基础的前端开发工作;
    • 熟练使用Vue框架及相关工具开发应用, 阅读过部分Vue源码, 了解Vue响应式实现原理;
    • 掌握NodeJS基本使用, 能够基于NodeJS编写开发工具或搭建Web服务;
    • 了解Webpack基本配置和使用, 有Webpack Vite等前端工程化工具使用经验;
    • 了解Typescript, 有Typescript的项目使用经历;
    • 良好的Git操作, 清晰的Commit提交, 保证代码质量;
    • 对前端学习抱有热情, 有良好的学习能力, 能够快速学习掌握新知识;

    技术栈

    前端技术

    Vue Router Vuex Pinia Element Plus Echart WangEditor

    Sass/Less Axios Ajax ...

    后端技术

    相关技能

    文档处理:

    Microsoft Word Microsoft PowerPoint Microsoft Excel

    平面设计:

    Adobe PhotoShop Adobe Lightroom

    影音制作:

    DaVinci Resolve Studio Adobe Premiere Adobe After Effects

    专业软件:

    MATLAB ICEDA Multisim Keil uVision5

    获得奖项

    Microsoft Edge 浏览器开拓者大赛 开拓之星

    稀土掘金2022编程挑战赛 三等奖

    入选“扬帆计划·中央和国家机关大学生实习”

    100周年现场志愿者

    优秀学生干部、优秀共青团员

    社会工作优秀奖学金

    相关链接

    Github哔哩哔哩稀土掘金CSDNGitee

    ',35),c=[d];function h(g,p,n,m,f,u){return o(),a("div",null,c)}const C=e(r,[["render",h]]);export{_ as __pageData,C as default}; +import{_ as e,o,c as a,a as l}from"./app.33820b61.js";const t="/logo.png",i="/assets/2.7aeaaf23.png",s="/assets/1.136ffa4a.png",_=JSON.parse('{"title":"个人介绍","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"技术栈","slug":"技术栈","link":"#技术栈","children":[{"level":3,"title":"前端技术","slug":"前端技术","link":"#前端技术","children":[]},{"level":3,"title":"后端技术","slug":"后端技术","link":"#后端技术","children":[]},{"level":3,"title":"相关技能","slug":"相关技能","link":"#相关技能","children":[]}]},{"level":2,"title":"获得奖项","slug":"获得奖项","link":"#获得奖项","children":[{"level":3,"title":"Microsoft Edge 浏览器开拓者大赛 开拓之星","slug":"microsoft-edge-浏览器开拓者大赛-开拓之星","link":"#microsoft-edge-浏览器开拓者大赛-开拓之星","children":[]},{"level":3,"title":"稀土掘金2022编程挑战赛 三等奖","slug":"稀土掘金2022编程挑战赛-三等奖","link":"#稀土掘金2022编程挑战赛-三等奖","children":[]},{"level":3,"title":"入选“扬帆计划·中央和国家机关大学生实习”","slug":"入选-扬帆计划·中央和国家机关大学生实习","link":"#入选-扬帆计划·中央和国家机关大学生实习","children":[]},{"level":3,"title":"100周年现场志愿者","slug":"_100周年现场志愿者","link":"#_100周年现场志愿者","children":[]},{"level":3,"title":"优秀学生干部、优秀共青团员","slug":"优秀学生干部、优秀共青团员","link":"#优秀学生干部、优秀共青团员","children":[]},{"level":3,"title":"社会工作优秀奖学金","slug":"社会工作优秀奖学金","link":"#社会工作优秀奖学金","children":[]}]},{"level":2,"title":"相关链接","slug":"相关链接","link":"#相关链接","children":[]}],"relativePath":"self/index.md","lastUpdated":1676979063000}'),r={name:"self/index.md"},d=l('

    个人介绍

    logo

    北京交通大学(BeijingJiaoTong University)电子信息工程学院本科在读

    • 熟悉ES6特性, 有前端领域开发经验, 能独立完成基础的前端开发工作;
    • 熟练使用Vue框架及相关工具开发应用, 阅读过部分Vue源码, 了解Vue响应式实现原理;
    • 掌握NodeJS基本使用, 能够基于NodeJS编写开发工具或搭建Web服务;
    • 了解Webpack基本配置和使用, 有Webpack Vite等前端工程化工具使用经验;
    • 了解Typescript, 有Typescript的项目使用经历;
    • 良好的Git操作, 清晰的Commit提交, 保证代码质量;
    • 对前端学习抱有热情, 有良好的学习能力, 能够快速学习掌握新知识;

    技术栈

    前端技术

    Vue Router Vuex Pinia Element Plus Echart WangEditor

    Sass/Less Axios Ajax ...

    后端技术

    相关技能

    文档处理:

    Microsoft Word Microsoft PowerPoint Microsoft Excel

    平面设计:

    Adobe PhotoShop Adobe Lightroom

    影音制作:

    DaVinci Resolve Studio Adobe Premiere Adobe After Effects

    专业软件:

    MATLAB ICEDA Multisim Keil uVision5

    获得奖项

    Microsoft Edge 浏览器开拓者大赛 开拓之星

    稀土掘金2022编程挑战赛 三等奖

    入选“扬帆计划·中央和国家机关大学生实习”

    100周年现场志愿者

    优秀学生干部、优秀共青团员

    社会工作优秀奖学金

    相关链接

    Github哔哩哔哩稀土掘金CSDNGitee

    ',35),c=[d];function h(g,p,n,m,f,u){return o(),a("div",null,c)}const C=e(r,[["render",h]]);export{_ as __pageData,C as default}; diff --git a/assets/self_index.md.5b8fe7b6.lean.js b/assets/self_index.md.e7b0b4e0.lean.js similarity index 96% rename from assets/self_index.md.5b8fe7b6.lean.js rename to assets/self_index.md.e7b0b4e0.lean.js index 6339c1c9..d2385b5e 100644 --- a/assets/self_index.md.5b8fe7b6.lean.js +++ b/assets/self_index.md.e7b0b4e0.lean.js @@ -1 +1 @@ -import{_ as e,o,c as a,a as l}from"./app.33820b61.js";const t="/logo.png",i="/assets/2.7aeaaf23.png",s="/assets/1.136ffa4a.png",_=JSON.parse('{"title":"个人介绍","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"技术栈","slug":"技术栈","link":"#技术栈","children":[{"level":3,"title":"前端技术","slug":"前端技术","link":"#前端技术","children":[]},{"level":3,"title":"后端技术","slug":"后端技术","link":"#后端技术","children":[]},{"level":3,"title":"相关技能","slug":"相关技能","link":"#相关技能","children":[]}]},{"level":2,"title":"获得奖项","slug":"获得奖项","link":"#获得奖项","children":[{"level":3,"title":"Microsoft Edge 浏览器开拓者大赛 开拓之星","slug":"microsoft-edge-浏览器开拓者大赛-开拓之星","link":"#microsoft-edge-浏览器开拓者大赛-开拓之星","children":[]},{"level":3,"title":"稀土掘金2022编程挑战赛 三等奖","slug":"稀土掘金2022编程挑战赛-三等奖","link":"#稀土掘金2022编程挑战赛-三等奖","children":[]},{"level":3,"title":"入选“扬帆计划·中央和国家机关大学生实习”","slug":"入选-扬帆计划·中央和国家机关大学生实习","link":"#入选-扬帆计划·中央和国家机关大学生实习","children":[]},{"level":3,"title":"100周年现场志愿者","slug":"_100周年现场志愿者","link":"#_100周年现场志愿者","children":[]},{"level":3,"title":"优秀学生干部、优秀共青团员","slug":"优秀学生干部、优秀共青团员","link":"#优秀学生干部、优秀共青团员","children":[]},{"level":3,"title":"社会工作优秀奖学金","slug":"社会工作优秀奖学金","link":"#社会工作优秀奖学金","children":[]}]},{"level":2,"title":"相关链接","slug":"相关链接","link":"#相关链接","children":[]}],"relativePath":"self/index.md","lastUpdated":1676737739000}'),r={name:"self/index.md"},d=l("",35),c=[d];function h(g,p,n,m,f,u){return o(),a("div",null,c)}const C=e(r,[["render",h]]);export{_ as __pageData,C as default}; +import{_ as e,o,c as a,a as l}from"./app.33820b61.js";const t="/logo.png",i="/assets/2.7aeaaf23.png",s="/assets/1.136ffa4a.png",_=JSON.parse('{"title":"个人介绍","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"技术栈","slug":"技术栈","link":"#技术栈","children":[{"level":3,"title":"前端技术","slug":"前端技术","link":"#前端技术","children":[]},{"level":3,"title":"后端技术","slug":"后端技术","link":"#后端技术","children":[]},{"level":3,"title":"相关技能","slug":"相关技能","link":"#相关技能","children":[]}]},{"level":2,"title":"获得奖项","slug":"获得奖项","link":"#获得奖项","children":[{"level":3,"title":"Microsoft Edge 浏览器开拓者大赛 开拓之星","slug":"microsoft-edge-浏览器开拓者大赛-开拓之星","link":"#microsoft-edge-浏览器开拓者大赛-开拓之星","children":[]},{"level":3,"title":"稀土掘金2022编程挑战赛 三等奖","slug":"稀土掘金2022编程挑战赛-三等奖","link":"#稀土掘金2022编程挑战赛-三等奖","children":[]},{"level":3,"title":"入选“扬帆计划·中央和国家机关大学生实习”","slug":"入选-扬帆计划·中央和国家机关大学生实习","link":"#入选-扬帆计划·中央和国家机关大学生实习","children":[]},{"level":3,"title":"100周年现场志愿者","slug":"_100周年现场志愿者","link":"#_100周年现场志愿者","children":[]},{"level":3,"title":"优秀学生干部、优秀共青团员","slug":"优秀学生干部、优秀共青团员","link":"#优秀学生干部、优秀共青团员","children":[]},{"level":3,"title":"社会工作优秀奖学金","slug":"社会工作优秀奖学金","link":"#社会工作优秀奖学金","children":[]}]},{"level":2,"title":"相关链接","slug":"相关链接","link":"#相关链接","children":[]}],"relativePath":"self/index.md","lastUpdated":1676979063000}'),r={name:"self/index.md"},d=l("",35),c=[d];function h(g,p,n,m,f,u){return o(),a("div",null,c)}const C=e(r,[["render",h]]);export{_ as __pageData,C as default}; diff --git a/assets/works_contribution.md.f1f31ee6.js b/assets/works_contribution.md.13a9eaa9.js similarity index 95% rename from assets/works_contribution.md.f1f31ee6.js rename to assets/works_contribution.md.13a9eaa9.js index e245a4bb..aa27a4c6 100644 --- a/assets/works_contribution.md.f1f31ee6.js +++ b/assets/works_contribution.md.13a9eaa9.js @@ -1 +1 @@ -import{_ as e,o as r,c as a,a as t}from"./app.33820b61.js";const f=JSON.parse('{"title":"社区贡献","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"稀土掘金助手","slug":"稀土掘金助手","link":"#稀土掘金助手","children":[]},{"level":2,"title":"B站粉丝牌助手文档","slug":"b站粉丝牌助手文档","link":"#b站粉丝牌助手文档","children":[]}],"relativePath":"works/contribution.md","lastUpdated":1676737739000}'),n={name:"works/contribution.md"},i=t('

    社区贡献

    稀土掘金助手

    稀土掘金助手: 腾讯云函数部署

    源代码

    B站粉丝牌助手文档

    B站粉丝牌助手文档

    源代码Demo

    ',7),o=[i];function s(h,l,d,c,_,p){return r(),a("div",null,o)}const b=e(n,[["render",s]]);export{f as __pageData,b as default}; +import{_ as e,o as r,c as a,a as t}from"./app.33820b61.js";const f=JSON.parse('{"title":"社区贡献","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"稀土掘金助手","slug":"稀土掘金助手","link":"#稀土掘金助手","children":[]},{"level":2,"title":"B站粉丝牌助手文档","slug":"b站粉丝牌助手文档","link":"#b站粉丝牌助手文档","children":[]}],"relativePath":"works/contribution.md","lastUpdated":1676979063000}'),n={name:"works/contribution.md"},i=t('

    社区贡献

    稀土掘金助手

    稀土掘金助手: 腾讯云函数部署

    源代码

    B站粉丝牌助手文档

    B站粉丝牌助手文档

    源代码Demo

    ',7),o=[i];function s(h,l,d,c,_,p){return r(),a("div",null,o)}const b=e(n,[["render",s]]);export{f as __pageData,b as default}; diff --git a/assets/works_contribution.md.f1f31ee6.lean.js b/assets/works_contribution.md.13a9eaa9.lean.js similarity index 90% rename from assets/works_contribution.md.f1f31ee6.lean.js rename to assets/works_contribution.md.13a9eaa9.lean.js index fdb4dfde..fd98f75e 100644 --- a/assets/works_contribution.md.f1f31ee6.lean.js +++ b/assets/works_contribution.md.13a9eaa9.lean.js @@ -1 +1 @@ -import{_ as e,o as r,c as a,a as t}from"./app.33820b61.js";const f=JSON.parse('{"title":"社区贡献","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"稀土掘金助手","slug":"稀土掘金助手","link":"#稀土掘金助手","children":[]},{"level":2,"title":"B站粉丝牌助手文档","slug":"b站粉丝牌助手文档","link":"#b站粉丝牌助手文档","children":[]}],"relativePath":"works/contribution.md","lastUpdated":1676737739000}'),n={name:"works/contribution.md"},i=t("",7),o=[i];function s(h,l,d,c,_,p){return r(),a("div",null,o)}const b=e(n,[["render",s]]);export{f as __pageData,b as default}; +import{_ as e,o as r,c as a,a as t}from"./app.33820b61.js";const f=JSON.parse('{"title":"社区贡献","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"稀土掘金助手","slug":"稀土掘金助手","link":"#稀土掘金助手","children":[]},{"level":2,"title":"B站粉丝牌助手文档","slug":"b站粉丝牌助手文档","link":"#b站粉丝牌助手文档","children":[]}],"relativePath":"works/contribution.md","lastUpdated":1676979063000}'),n={name:"works/contribution.md"},i=t("",7),o=[i];function s(h,l,d,c,_,p){return r(),a("div",null,o)}const b=e(n,[["render",s]]);export{f as __pageData,b as default}; diff --git a/assets/works_opensource.md.d00905f0.js b/assets/works_opensource.md.04c9693c.js similarity index 98% rename from assets/works_opensource.md.d00905f0.js rename to assets/works_opensource.md.04c9693c.js index 0a0cbd61..676041a1 100644 --- a/assets/works_opensource.md.d00905f0.js +++ b/assets/works_opensource.md.04c9693c.js @@ -1 +1 @@ -import{_ as e,o as r,c as a,a as t}from"./app.33820b61.js";const b=JSON.parse('{"title":"个人作品","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"Vue3+TypeScript后台管理系统","slug":"vue3-typescript后台管理系统","link":"#vue3-typescript后台管理系统","children":[]},{"level":2,"title":"Typein 效率工具集","slug":"typein-效率工具集","link":"#typein-效率工具集","children":[]},{"level":2,"title":"A-SOUL浏览器宠物","slug":"a-soul浏览器宠物","link":"#a-soul浏览器宠物","children":[]},{"level":2,"title":"北京交通大学课程平台功能增强","slug":"北京交通大学课程平台功能增强","link":"#北京交通大学课程平台功能增强","children":[]},{"level":2,"title":"超级剪贴板","slug":"超级剪贴板","link":"#超级剪贴板","children":[]},{"level":2,"title":"超级粘贴","slug":"超级粘贴","link":"#超级粘贴","children":[]},{"level":2,"title":"超级分词","slug":"超级分词","link":"#超级分词","children":[]},{"level":2,"title":"超级连点器","slug":"超级连点器","link":"#超级连点器","children":[]},{"level":2,"title":"PopNotify","slug":"popnotify","link":"#popnotify","children":[]},{"level":2,"title":"UserScripts","slug":"userscripts","link":"#userscripts","children":[]}],"relativePath":"works/opensource.md","lastUpdated":1676737739000}'),i={name:"works/opensource.md"},h=t('

    个人作品

    Vue3+TypeScript后台管理系统

    Vue3+TypeScript后台管理系统

    源代码

    Typein 效率工具集

    Typein 是一个运行在现代浏览器上的拓展插件,它可以帮助你在保持专注的情况下,高效完成各种操作。

    源代码

    宣传视频

    Microsoft Edge Add-on Store

    A-SOUL浏览器宠物

    在浏览器里养一只A-Soul成员当宠物

    源代码

    宣传视频

    北京交通大学课程平台功能增强

    北京交通大学课程平台功能增强脚本,实现信息聚合,附件上传,让你高效处理课程信息。

    源代码

    超级剪贴板

    uTools插件,一款强大的剪贴板管理工具。基于Vue3构建

    源代码

    主页

    超级粘贴

    uTools插件,将剪切板内容直接粘贴为文件。功能基于NodeJS

    源代码

    超级分词

    uTools插件,前台使用Vue3+ElementPlus构建,后台基于Express封装结巴分词并暴露API接口

    超级连点器

    uTools插件,界面使用Vue3+AntDesign构建,功能基于Worker

    PopNotify

    仿 Element UI 的通知卡片。

    源代码

    Demo

    UserScripts

    用户脚本合集,生产力工具、效率工具、自动化脚本

    源代码

    ',34),n=[h];function l(p,o,s,d,c,u){return r(),a("div",null,n)}const g=e(i,[["render",l]]);export{b as __pageData,g as default}; +import{_ as e,o as r,c as a,a as t}from"./app.33820b61.js";const b=JSON.parse('{"title":"个人作品","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"Vue3+TypeScript后台管理系统","slug":"vue3-typescript后台管理系统","link":"#vue3-typescript后台管理系统","children":[]},{"level":2,"title":"Typein 效率工具集","slug":"typein-效率工具集","link":"#typein-效率工具集","children":[]},{"level":2,"title":"A-SOUL浏览器宠物","slug":"a-soul浏览器宠物","link":"#a-soul浏览器宠物","children":[]},{"level":2,"title":"北京交通大学课程平台功能增强","slug":"北京交通大学课程平台功能增强","link":"#北京交通大学课程平台功能增强","children":[]},{"level":2,"title":"超级剪贴板","slug":"超级剪贴板","link":"#超级剪贴板","children":[]},{"level":2,"title":"超级粘贴","slug":"超级粘贴","link":"#超级粘贴","children":[]},{"level":2,"title":"超级分词","slug":"超级分词","link":"#超级分词","children":[]},{"level":2,"title":"超级连点器","slug":"超级连点器","link":"#超级连点器","children":[]},{"level":2,"title":"PopNotify","slug":"popnotify","link":"#popnotify","children":[]},{"level":2,"title":"UserScripts","slug":"userscripts","link":"#userscripts","children":[]}],"relativePath":"works/opensource.md","lastUpdated":1676979063000}'),i={name:"works/opensource.md"},h=t('

    个人作品

    Vue3+TypeScript后台管理系统

    Vue3+TypeScript后台管理系统

    源代码

    Typein 效率工具集

    Typein 是一个运行在现代浏览器上的拓展插件,它可以帮助你在保持专注的情况下,高效完成各种操作。

    源代码

    宣传视频

    Microsoft Edge Add-on Store

    A-SOUL浏览器宠物

    在浏览器里养一只A-Soul成员当宠物

    源代码

    宣传视频

    北京交通大学课程平台功能增强

    北京交通大学课程平台功能增强脚本,实现信息聚合,附件上传,让你高效处理课程信息。

    源代码

    超级剪贴板

    uTools插件,一款强大的剪贴板管理工具。基于Vue3构建

    源代码

    主页

    超级粘贴

    uTools插件,将剪切板内容直接粘贴为文件。功能基于NodeJS

    源代码

    超级分词

    uTools插件,前台使用Vue3+ElementPlus构建,后台基于Express封装结巴分词并暴露API接口

    超级连点器

    uTools插件,界面使用Vue3+AntDesign构建,功能基于Worker

    PopNotify

    仿 Element UI 的通知卡片。

    源代码

    Demo

    UserScripts

    用户脚本合集,生产力工具、效率工具、自动化脚本

    源代码

    ',34),n=[h];function l(p,o,s,d,c,u){return r(),a("div",null,n)}const g=e(i,[["render",l]]);export{b as __pageData,g as default}; diff --git a/assets/works_opensource.md.d00905f0.lean.js b/assets/works_opensource.md.04c9693c.lean.js similarity index 95% rename from assets/works_opensource.md.d00905f0.lean.js rename to assets/works_opensource.md.04c9693c.lean.js index a83c9024..00c9e0a6 100644 --- a/assets/works_opensource.md.d00905f0.lean.js +++ b/assets/works_opensource.md.04c9693c.lean.js @@ -1 +1 @@ -import{_ as e,o as r,c as a,a as t}from"./app.33820b61.js";const b=JSON.parse('{"title":"个人作品","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"Vue3+TypeScript后台管理系统","slug":"vue3-typescript后台管理系统","link":"#vue3-typescript后台管理系统","children":[]},{"level":2,"title":"Typein 效率工具集","slug":"typein-效率工具集","link":"#typein-效率工具集","children":[]},{"level":2,"title":"A-SOUL浏览器宠物","slug":"a-soul浏览器宠物","link":"#a-soul浏览器宠物","children":[]},{"level":2,"title":"北京交通大学课程平台功能增强","slug":"北京交通大学课程平台功能增强","link":"#北京交通大学课程平台功能增强","children":[]},{"level":2,"title":"超级剪贴板","slug":"超级剪贴板","link":"#超级剪贴板","children":[]},{"level":2,"title":"超级粘贴","slug":"超级粘贴","link":"#超级粘贴","children":[]},{"level":2,"title":"超级分词","slug":"超级分词","link":"#超级分词","children":[]},{"level":2,"title":"超级连点器","slug":"超级连点器","link":"#超级连点器","children":[]},{"level":2,"title":"PopNotify","slug":"popnotify","link":"#popnotify","children":[]},{"level":2,"title":"UserScripts","slug":"userscripts","link":"#userscripts","children":[]}],"relativePath":"works/opensource.md","lastUpdated":1676737739000}'),i={name:"works/opensource.md"},h=t("",34),n=[h];function l(p,o,s,d,c,u){return r(),a("div",null,n)}const g=e(i,[["render",l]]);export{b as __pageData,g as default}; +import{_ as e,o as r,c as a,a as t}from"./app.33820b61.js";const b=JSON.parse('{"title":"个人作品","description":"","frontmatter":{"editLink":false},"headers":[{"level":2,"title":"Vue3+TypeScript后台管理系统","slug":"vue3-typescript后台管理系统","link":"#vue3-typescript后台管理系统","children":[]},{"level":2,"title":"Typein 效率工具集","slug":"typein-效率工具集","link":"#typein-效率工具集","children":[]},{"level":2,"title":"A-SOUL浏览器宠物","slug":"a-soul浏览器宠物","link":"#a-soul浏览器宠物","children":[]},{"level":2,"title":"北京交通大学课程平台功能增强","slug":"北京交通大学课程平台功能增强","link":"#北京交通大学课程平台功能增强","children":[]},{"level":2,"title":"超级剪贴板","slug":"超级剪贴板","link":"#超级剪贴板","children":[]},{"level":2,"title":"超级粘贴","slug":"超级粘贴","link":"#超级粘贴","children":[]},{"level":2,"title":"超级分词","slug":"超级分词","link":"#超级分词","children":[]},{"level":2,"title":"超级连点器","slug":"超级连点器","link":"#超级连点器","children":[]},{"level":2,"title":"PopNotify","slug":"popnotify","link":"#popnotify","children":[]},{"level":2,"title":"UserScripts","slug":"userscripts","link":"#userscripts","children":[]}],"relativePath":"works/opensource.md","lastUpdated":1676979063000}'),i={name:"works/opensource.md"},h=t("",34),n=[h];function l(p,o,s,d,c,u){return r(),a("div",null,n)}const g=e(i,[["render",l]]);export{b as __pageData,g as default}; diff --git a/hashmap.json b/hashmap.json index ffe4fb28..68249665 100644 --- a/hashmap.json +++ b/hashmap.json @@ -1 +1 @@ -{"note_css.md":"2c88cba1","works_contribution.md":"f1f31ee6","works_opensource.md":"d00905f0","note_javascript.md":"6a2d95de","article_【2023】青训营 - 前端练习题汇总解析.md":"87c3ec71","article_【字节跳动】前端面试题总结.md":"11aa2b5a","article_【快手】深入理解前端面试题.md":"5f4ef7a3","article_【用友金融】前端面试题总结.md":"69243f39","article_一文读懂事件冒泡与事件捕获.md":"a9dedb6d","article_一文读懂伪类与伪元素.md":"18a4ea39","article_一文读懂函数中this指向问题.md":"d4e27bc7","article_从0实现一个年度报告.md":"4e06b81d","article_浅析defineproperty与proxy实现的双向绑定.md":"f2072102","article_深入javascript数据类型.md":"ed246d99","article_深入vue3源码,看看vue.use后究竟发生了什么?.md":"e6b03974","article_深入理解浏览器缓存机制.md":"be15491a","article_深入理解浏览器运行原理.md":"4b1c1d16","index.md":"e391bcbf","note_ssr.md":"eafce674","project_clipboardmanager_index.md":"c8cba791","article_彻底搞懂对象的数据属性描述符、存储属性描述符.md":"9865de7d","project_clipboardmanager_guide_index.md":"cbb1b2e8","project_clipboardmanager_log_index.md":"4ee5fe53","project_clipboardmanager_vip_index.md":"00c8bdb1","project_smartwordbreak_statement_index.md":"08faf5e0","project_smartwordbreak_index.md":"8198941b","project_smartwordbreak_log_index.md":"3ca84f95","note_front-end engineering.md":"e321faed","project_clipboardmanager_statement_index.md":"6751fd19","article_深入理解proxy与reflect.md":"368d9aed","self_index.md":"5b8fe7b6","note_javascriptenhanced.md":"209d0c05"} +{"article_【2023】青训营 - 前端练习题汇总解析.md":"8d7e9b9c","article_深入理解浏览器缓存机制.md":"e7e22bb1","article_从0实现一个年度报告.md":"7ba24283","article_彻底搞懂对象的数据属性描述符、存储属性描述符.md":"b7a6c275","article_浅析defineproperty与proxy实现的双向绑定.md":"02c8f56e","article_深入javascript数据类型.md":"80fd8af0","article_深入vue3源码,看看vue.use后究竟发生了什么?.md":"cd9b1cff","article_深入理解proxy与reflect.md":"9c5a6cd1","article_深入理解浏览器运行原理.md":"f13b2b23","index.md":"00c51c0e","note_css.md":"a4f3e631","note_javascript.md":"e58e866f","article_一文读懂事件冒泡与事件捕获.md":"c2d9cd1b","note_ssr.md":"5b580a05","note_front-end engineering.md":"939c2eef","project_clipboardmanager_index.md":"fcacbc6c","project_clipboardmanager_log_index.md":"9bd18ae1","project_clipboardmanager_statement_index.md":"fddb5934","project_clipboardmanager_vip_index.md":"8d894bfc","project_smartwordbreak_index.md":"6364a91a","project_smartwordbreak_log_index.md":"02ecbe98","project_smartwordbreak_statement_index.md":"4c33c737","self_index.md":"e7b0b4e0","works_contribution.md":"13a9eaa9","works_opensource.md":"04c9693c","article_【字节跳动】前端面试题总结.md":"8b64abc5","project_clipboardmanager_guide_index.md":"caf90979","article_【快手】深入理解前端面试题.md":"9bd6db9f","article_【用友金融】前端面试题总结.md":"8730c019","article_一文读懂伪类与伪元素.md":"dd034dbf","note_javascriptenhanced.md":"b46ba179","article_一文读懂函数中this指向问题.md":"3025c285"} diff --git a/index.html b/index.html index 2dfebd19..f7e169f2 100644 --- a/index.html +++ b/index.html @@ -8,14 +8,14 @@ - +
    Skip to content

    ZiuChen

    无限进步.

    Infinite Progress...

    🎓

    Electronic Information Major

    电子信息工程

    🎯

    JavaScript & TypeScript

    自学前端 热爱技术

    👆

    See more information

    访问导航栏查看更多信息

    Released under the MIT License.

    - + diff --git a/note/CSS.html b/note/CSS.html index a8cdc288..0907a9dc 100644 --- a/note/CSS.html +++ b/note/CSS.html @@ -8,7 +8,7 @@ - + @@ -492,8 +492,8 @@
    js
    const el = document.querySelector('.item')
     console.log(el.dataset.age) // 18
     console.log(el.dataset.name) // 'ziu'
    -

    Released under the MIT License.

    - +

    Released under the MIT License.

    + diff --git a/note/Front-end Engineering.html b/note/Front-end Engineering.html index eed322b9..82a8687f 100644 --- a/note/Front-end Engineering.html +++ b/note/Front-end Engineering.html @@ -8,7 +8,7 @@ - + @@ -67,7 +67,7 @@ // moduleB.js console.log(moduleA.name) // 在其他模块中调用 -

    CommonJS

    CommonJS是一种规范,当初命名为ServerJS,旨在浏览器以外的地方使用,后为体现其广泛性,改名为CommonJS,简称CJS

    规范 是用来指导 实现的

    • Node 是CommonJS在服务端的代表实现
    • Browserify 是CommonJS在浏览器中的一种实现 (正在被淘汰)
    • WebPack 打包工具具备支持CommonJS的支持和转换

    所以,Node.js对CommonJS进行了支持和实现,让JavaScript在Node上运行时可以实现模块化开发

    • 每个.js文件都是一个单独的模块
    • 每个模块中都包含变量exports module.exports require
    js
    // env.js
    +

    CommonJS

    CommonJS是一种规范,当初命名为ServerJS,旨在浏览器以外的地方使用,后为体现其广泛性,改名为CommonJS,简称CJS

    规范 是用来指导 实现的

    • Node 是CommonJS在服务端的代表实现
    • Browserify 是CommonJS在浏览器中的一种实现 (正在被淘汰)
    • WebPack 打包工具具备支持CommonJS的支持和转换

    所以,Node.js对CommonJS进行了支持和实现,让JavaScript在Node上运行时可以实现模块化开发

    • 每个.js文件都是一个单独的模块
    • 每个模块中都包含变量exports module.exports require
    js
    // env.js
     exports.name = 'Ziu'
     exports.age = 18
     
    js
    // utils.js
    @@ -85,7 +85,7 @@
     
     const { name, age } = require('env.js')
     console.log(name, age) // Ziu 18
    -

    exports的本质

    exportsrequire在Node中的本质

    • exports是一个对象,我们可以在这个对象中添加很多属性,添加的属性则会被导出
      • 在没有向该对象添加任何属性之前,它是一个空对象
    • 当通过require导入时:const env = require('env.js')
      • env这个变量等于env.js中的exports对象
      • 本质上是envexports对象的引用赋值
      • { id: '...', exports: { ... }, loaded: true, ... }
    • 后续即使再次执行require导入模块,模块中的代码也不会重新执行(module.loaded属性)
      • 当从模块中取值时,会从已经加载的exports对象缓存上取值
    js
    // utils.js
    +

    exports的本质

    exportsrequire在Node中的本质

    • exports是一个对象,我们可以在这个对象中添加很多属性,添加的属性则会被导出
      • 在没有向该对象添加任何属性之前,它是一个空对象
    • 当通过require导入时:const env = require('env.js')
      • env这个变量等于env.js中的exports对象
      • 本质上是envexports对象的引用赋值
      • { id: '...', exports: { ... }, loaded: true, ... }
    • 后续即使再次执行require导入模块,模块中的代码也不会重新执行(module.loaded属性)
      • 当从模块中取值时,会从已经加载的exports对象缓存上取值
    js
    // utils.js
     exports.a = 0
     
     // 1s后修改a值
    @@ -113,7 +113,7 @@
       name,
       run
     }
    -

    二者的区别

    既然如此,为什么还要存在exports这个概念呢?

    • 在CommonJS中是没有module.exports的概念的
    • 为了实现模块的导出,Node.js使用的是Module类,每一个模块都是Module的实例,也就是module
    • 所以在Node.js中真正用于导出的并不是exports,而是module.exports
    • module对象中的exports属性是exports对象的一个引用
      • module.exports === exports === utils

    如果module.exports不再引用exports对象了,修改exports对象也就没有意义了

    js
    // utils.js
    +

    二者的区别

    既然如此,为什么还要存在exports这个概念呢?

    • 在CommonJS中是没有module.exports的概念的
    • 为了实现模块的导出,Node.js使用的是Module类,每一个模块都是Module的实例,也就是module
    • 所以在Node.js中真正用于导出的并不是exports,而是module.exports
    • module对象中的exports属性是exports对象的一个引用
      • module.exports === exports === utils

    如果module.exports不再引用exports对象了,修改exports对象也就没有意义了

    js
    // utils.js
     module.exports = {
       name: 'Ziu'
     }
    @@ -122,7 +122,7 @@
     const utils = require('utils.js')
     console.log(utils.name) // Ziu
     console.log(utils.age) // undefined
    -

    当使用module.exports = { ... }后,模块中原有的exports不再被导入识别,导入的内容将变为module.exports指定的对象内容

    require的本质

    require是一个函数,可以帮助我们导入一个文件(模块)中导出的对象

    • 为什么可以省略掉.js后缀,直接使用require('./utils')
    • 为什么可以省略掉index.js,直接使用require('./tools')导入tools/index.js

    这涉及到require在匹配路径后的查找规则:

    分为三种情况:内置模块、自定义路径、包名

    • 导入Node.js内置的模块,如const path = require('path')
      • 直接返回该内置模块 并停止后续的查找
    • 根据路径导入自定义的模块,如const utils = require('./{filename}')
      • 按照路径寻找该模块./ ../ /
      • 如果指定了后缀名,则按照后缀名查找
      • 如果未指定后缀名,则:
        1. 直接查找该文件
        2. 查找{filename}.js文件
        3. 查找{filename}.json文件
        4. 查找{filename}.node文件
      • 如果按照上述方式没找到文件,则{filename}作为路径继续查找
      • 查找目录下的index文件 {filename}/index
        1. 查找{filename}/index.js文件
        2. ··· ···
      • 没找到:报错Cannot find module 'xxx'
    • 包名,如const lodash = require('lodash')
      • 到项目根目录的node_modules中查找
      • node_modules/{package_name}/index.js
      • 当前项目目录的node_modules找不到则继续向上查找,直到查找到根目录的node_modules

    模块的加载过程

    • 模块在被第一次引入时,模块中的JS代码会被运行一次
      • 代码执行顺序与require的位置相关
    • 模块如果被多次引入,会被缓存,最终只加载一次
      • 这是因为每个模块对象module上都有一个属性loaded
      • loaded === false表示该模块尚未被加载
      • 第二次被require引入时会检查该属性是否为true
    • 如果有循环引用,加载顺序如何?
      • 数据结构:图结构(graph)遍历时有深度优先搜索(DFS)、广度优先搜索(BFS)两种算法
      • Node采用的是深度优先算法

    CommonJS的缺点

    • 加载模块是同步加载的
      • 只有等到对应的模块加载完毕,当前模块中的内容才能被执行
      • 当然,在服务器中加载JS文件都是本地文件,加载速度非常快,不会受影响
    • 但是在浏览器中使用CommonJS
      • 需要先从服务器下载JS文件,后加载运行
      • 阻塞JS执行 阻塞页面加载
    • 在WebPack中使用CommonJS
      • CommonJS会被WebPack解析
      • 将CommonJS代码转化为bundle 浏览器可以直接运行

    ESModule

    • ES6 模块采用编译时加载,使得编译时就能确定模块的依赖关系,有助于静态优化
    • CommonJS模块在运行时加载,且必须借助对象加载模块内容

    exportimport用法概览

    ESModule借助exportimport导入导出内容,需要注意的是导入导出的并不是对象

    export定义的是当前模块导出的接口import可以导入来自其他不同模块的接口

    • export default可以设置默认导出对象
    • export { ... }可以统一导出多个内容
    • exportimport都可以使用as关键字重命名导出/导入的接口
    • import * from 'xxx' export * from 'xxx'批量导入/导出
    js
    // utils.js
    +

    当使用module.exports = { ... }后,模块中原有的exports不再被导入识别,导入的内容将变为module.exports指定的对象内容

    require的本质

    require是一个函数,可以帮助我们导入一个文件(模块)中导出的对象

    • 为什么可以省略掉.js后缀,直接使用require('./utils')
    • 为什么可以省略掉index.js,直接使用require('./tools')导入tools/index.js

    这涉及到require在匹配路径后的查找规则:

    分为三种情况:内置模块、自定义路径、包名

    • 导入Node.js内置的模块,如const path = require('path')
      • 直接返回该内置模块 并停止后续的查找
    • 根据路径导入自定义的模块,如const utils = require('./{filename}')
      • 按照路径寻找该模块./ ../ /
      • 如果指定了后缀名,则按照后缀名查找
      • 如果未指定后缀名,则:
        1. 直接查找该文件
        2. 查找{filename}.js文件
        3. 查找{filename}.json文件
        4. 查找{filename}.node文件
      • 如果按照上述方式没找到文件,则{filename}作为路径继续查找
      • 查找目录下的index文件 {filename}/index
        1. 查找{filename}/index.js文件
        2. ··· ···
      • 没找到:报错Cannot find module 'xxx'
    • 包名,如const lodash = require('lodash')
      • 到项目根目录的node_modules中查找
      • node_modules/{package_name}/index.js
      • 当前项目目录的node_modules找不到则继续向上查找,直到查找到根目录的node_modules

    模块的加载过程

    • 模块在被第一次引入时,模块中的JS代码会被运行一次
      • 代码执行顺序与require的位置相关
    • 模块如果被多次引入,会被缓存,最终只加载一次
      • 这是因为每个模块对象module上都有一个属性loaded
      • loaded === false表示该模块尚未被加载
      • 第二次被require引入时会检查该属性是否为true
    • 如果有循环引用,加载顺序如何?
      • 数据结构:图结构(graph)遍历时有深度优先搜索(DFS)、广度优先搜索(BFS)两种算法
      • Node采用的是深度优先算法

    CommonJS的缺点

    • 加载模块是同步加载的
      • 只有等到对应的模块加载完毕,当前模块中的内容才能被执行
      • 当然,在服务器中加载JS文件都是本地文件,加载速度非常快,不会受影响
    • 但是在浏览器中使用CommonJS
      • 需要先从服务器下载JS文件,后加载运行
      • 阻塞JS执行 阻塞页面加载
    • 在WebPack中使用CommonJS
      • CommonJS会被WebPack解析
      • 将CommonJS代码转化为bundle 浏览器可以直接运行

    ESModule

    • ES6 模块采用编译时加载,使得编译时就能确定模块的依赖关系,有助于静态优化
    • CommonJS模块在运行时加载,且必须借助对象加载模块内容

    exportimport用法概览

    ESModule借助exportimport导入导出内容,需要注意的是导入导出的并不是对象

    export定义的是当前模块导出的接口import可以导入来自其他不同模块的接口

    • export default可以设置默认导出对象
    • export { ... }可以统一导出多个内容
    • exportimport都可以使用as关键字重命名导出/导入的接口
    • import * from 'xxx' export * from 'xxx'批量导入/导出
    js
    // utils.js
     export function sum(a, b) {
       return a + b
     }
    @@ -144,7 +144,7 @@
     sum(1, 2) // 3
     sub(2, 3) // -1
     log(name, age, ENV_VARIABLE) // 'Ziu' 18 'Hello, World!'
    -

    需要注意的是,在浏览器中要使用ESModule,需要为<script>标签添加module标记:

    <script src="index.js" type="module"></script>

    • 当浏览器解析到type="module"的JS代码后,会分析模块中导入的ESModule模块
    • 每导入一个ESModule模块,浏览器都会发起一个HTTP请求去加载它
    • 在本地运行时加载不同协议头的文件会遇到跨域问题,需要开启本地Web服务器

    另外,exportimport必须位于模块的顶层,如果位于作用域内会报错,因为这就无法对代码进行静态分析优化了

    export详解

    export有两种导出方式:

    • 命名导出 export const name = 'Ziu' export { v1, v2 } export * from 'xxx'
      • 导出时需要指定名字
      • 导入时也需要知道对应的名字
    • 默认导出 export default AGE = 18
      • 在从其他位置导入时需要为此默认导出指定新的名字
      • 给用户方便:不必阅读文档就可以加载模块

    值的动态绑定

    • ESModule模块通过export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值
    • CommonJS模块输出的是值的缓存,不存在动态更新

    我们援引之前介绍CJS时的案例,将后缀名改为mjs即可在Node中运行ESModule模块代码

    初始获得的a值为0,经过1s后,在utils.mjs中修改了a的值,这时导入utils.mjs模块的其他模块可以获取到a最新的值

    js
    // utils.mjs
    +

    需要注意的是,在浏览器中要使用ESModule,需要为<script>标签添加module标记:

    <script src="index.js" type="module"></script>

    • 当浏览器解析到type="module"的JS代码后,会分析模块中导入的ESModule模块
    • 每导入一个ESModule模块,浏览器都会发起一个HTTP请求去加载它
    • 在本地运行时加载不同协议头的文件会遇到跨域问题,需要开启本地Web服务器

    另外,exportimport必须位于模块的顶层,如果位于作用域内会报错,因为这就无法对代码进行静态分析优化了

    export详解

    export有两种导出方式:

    • 命名导出 export const name = 'Ziu' export { v1, v2 } export * from 'xxx'
      • 导出时需要指定名字
      • 导入时也需要知道对应的名字
    • 默认导出 export default AGE = 18
      • 在从其他位置导入时需要为此默认导出指定新的名字
      • 给用户方便:不必阅读文档就可以加载模块

    值的动态绑定

    • ESModule模块通过export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值
    • CommonJS模块输出的是值的缓存,不存在动态更新

    我们援引之前介绍CJS时的案例,将后缀名改为mjs即可在Node中运行ESModule模块代码

    初始获得的a值为0,经过1s后,在utils.mjs中修改了a的值,这时导入utils.mjs模块的其他模块可以获取到a最新的值

    js
    // utils.mjs
     export let a = 0
     
     // 1s后修改a值
    @@ -191,7 +191,7 @@
     }
     

    传入动态值

    js
    let moduleName = () => ['Home', 'History', 'User'][0]
     import(`./${moduleName()}.js`)
    -

    import.meta

    ES2020引入了import.meta,它仅能在模块内部使用,包含一些模块自身的信息,即模块元信息

    • import.meta.url 返回当前模块的URL路径
      • 浏览器加载ESModule都是通过HTTP发起请求
        • 例如当前模块为fetchData.js,要在模块内引入一个名为data.json的数据:
        • import( new URL('data.json', import.meta.url) )
      • Node.js环境下,该值都是file://协议的链接
    • import.meta.scriptElement
      • 浏览器特有的属性
      • 返回加载模块的<script>标签,相当于document.currentScript

    规范中并未规定import.meta中包含哪些属性,一般包括上面两个属性

    深入理解模块加载

    ESModule的解析过程

    ESModule的解析过程可以分为三个阶段:

    • 构建 Construction
      • 根据地址查找JS文件,并发起HTTP请求下载,将其解析为模块记录 Module Record
    • 实例化 Instatiation
      • 对模块记录进行实例化,并为其分配内存空间
      • 解析ESModule模块的导入和导出语句,将模块指向对应的内存地址
      • 例如export const name = 'Ziu',会将变量name添加到模块环境记录中 Module Enviroment Record
    • 运行 Evaluation
      • 运行代码,计算值,并且将值填充到内存地址中
      • 将导入导出的赋给对应的变量name = 'Ziu'

    ![ESModule解析过程](Front-end Engineering.assets/esmodule-phases.png)

    文章推荐:ES modules: A cartoon deep-dive

    MJS和CJS的区别

    • CommonJS模块输出的是值的拷贝,而ESModule模块输出的是值的引用
      • CJS导出的变量,其值如果在模块内发生变化,外部导入是不会同步更新的,除非导出的是一个取值函数
      • MJS导出变量,外部模块每次访问时都会得到该变量最新的值,即使变量在模块内被修改了
    • CommonJS模块是运行时加载,而ESModule是编译时输出接口
      • CJS是通过对象实现的导入导出,它在运行时才被确定依赖关系和其值
      • MJS则是通过静态定义,在代码运行之前的静态解析阶段即可确定模块的导入导出内容
    • CommonJS模块的require()是同步加载模块,而ESModule模块的import命令是异步加载模块
      • import命令拥有一个独立的模块依赖的解析阶段

    CJS中的循环加载

    设想有以下两文件 a.jsb.js

    js
    // a.js
    +

    import.meta

    ES2020引入了import.meta,它仅能在模块内部使用,包含一些模块自身的信息,即模块元信息

    • import.meta.url 返回当前模块的URL路径
      • 浏览器加载ESModule都是通过HTTP发起请求
        • 例如当前模块为fetchData.js,要在模块内引入一个名为data.json的数据:
        • import( new URL('data.json', import.meta.url) )
      • Node.js环境下,该值都是file://协议的链接
    • import.meta.scriptElement
      • 浏览器特有的属性
      • 返回加载模块的<script>标签,相当于document.currentScript

    规范中并未规定import.meta中包含哪些属性,一般包括上面两个属性

    深入理解模块加载

    ESModule的解析过程

    ESModule的解析过程可以分为三个阶段:

    • 构建 Construction
      • 根据地址查找JS文件,并发起HTTP请求下载,将其解析为模块记录 Module Record
    • 实例化 Instatiation
      • 对模块记录进行实例化,并为其分配内存空间
      • 解析ESModule模块的导入和导出语句,将模块指向对应的内存地址
      • 例如export const name = 'Ziu',会将变量name添加到模块环境记录中 Module Enviroment Record
    • 运行 Evaluation
      • 运行代码,计算值,并且将值填充到内存地址中
      • 将导入导出的赋给对应的变量name = 'Ziu'

    ![ESModule解析过程](Front-end Engineering.assets/esmodule-phases.png)

    文章推荐:ES modules: A cartoon deep-dive

    MJS和CJS的区别

    • CommonJS模块输出的是值的拷贝,而ESModule模块输出的是值的引用
      • CJS导出的变量,其值如果在模块内发生变化,外部导入是不会同步更新的,除非导出的是一个取值函数
      • MJS导出变量,外部模块每次访问时都会得到该变量最新的值,即使变量在模块内被修改了
    • CommonJS模块是运行时加载,而ESModule是编译时输出接口
      • CJS是通过对象实现的导入导出,它在运行时才被确定依赖关系和其值
      • MJS则是通过静态定义,在代码运行之前的静态解析阶段即可确定模块的导入导出内容
    • CommonJS模块的require()是同步加载模块,而ESModule模块的import命令是异步加载模块
      • import命令拥有一个独立的模块依赖的解析阶段

    CJS中的循环加载

    设想有以下两文件 a.jsb.js

    js
    // a.js
     exports.done = false
     const b = require('./b.js')
     console.log('在 a.js 之中,b.done = %j', b.done)
    @@ -212,7 +212,7 @@
      a.js 之中,b.done = true
     a.js 执行完毕
      main.js 之中, a.done=true, b.done=true
    -

    总结:

    • CJS的模块导出是输出值的拷贝,而不是引用,值的变化不是动态的,而是会被缓存的
    • 循环加载时,CJS模块导出的值是当前已经执行部分代码产生的结果的值,而不是模块代码完全执行完后的最终值

    MJS中的循环加载

    ESModule的导入和导出与CommonJS有本质不同:

    js
    // a.mjs
    +

    总结:

    • CJS的模块导出是输出值的拷贝,而不是引用,值的变化不是动态的,而是会被缓存的
    • 循环加载时,CJS模块导出的值是当前已经执行部分代码产生的结果的值,而不是模块代码完全执行完后的最终值

    MJS中的循环加载

    ESModule的导入和导出与CommonJS有本质不同:

    js
    // a.mjs
     import { bar } from './b.mjs'
     console.log('a.mjs')
     console.log(bar)
    @@ -222,7 +222,7 @@
     console.log('b.mjs')
     console.log(foo)
     export let bar = 'bar'
    -

    执行a.mjs后发现报错了:ReferenceError: Cannot access 'foo' before initialization,变量foo未定义

    • MJS模块在代码执行前会进行静态分析
    • 分析a.mjs的依赖关系时,发现其依赖了b.mjs
    • 于是加载b.mjs并解析它的依赖关系
    • 解析b.mjs的过程中,发现它又依赖了a.mjs
    • 这时引擎不会再去加载a.mjs 而是认为a.mjs这个模块的Module Record已经存在了
    • 继续向下执行,执行到console.log(foo)时发现foo未定义 抛出错误

    要实现预期效果,可以将foobar改写为取值函数,这时执行就不会报错了:

    js
    // a.mjs
    +

    执行a.mjs后发现报错了:ReferenceError: Cannot access 'foo' before initialization,变量foo未定义

    • MJS模块在代码执行前会进行静态分析
    • 分析a.mjs的依赖关系时,发现其依赖了b.mjs
    • 于是加载b.mjs并解析它的依赖关系
    • 解析b.mjs的过程中,发现它又依赖了a.mjs
    • 这时引擎不会再去加载a.mjs 而是认为a.mjs这个模块的Module Record已经存在了
    • 继续向下执行,执行到console.log(foo)时发现foo未定义 抛出错误

    要实现预期效果,可以将foobar改写为取值函数,这时执行就不会报错了:

    js
    // a.mjs
     import { bar } from './b.mjs'
     console.log('a.mjs')
     console.log(bar())
    @@ -261,8 +261,8 @@
     const p1 = 'abc/cba'
     const p2 = '../why/kobe/james.txt'
     console.log(path.join(p1, p2)) // \\abc\\why\\kobe\\james.txt
    -
    • path.resolve 将多个路径片段解析、拼接为一个绝对路径
      • 从右往左处理传入的路径序列,每个路径依次被解析,直到构造完成一个绝对路径
      • 如果在处理完所有给定path的段之后,还没有生成绝对路径,则使用当前工作目录
      • 生成的路径被规范化并删除尾部斜杠,零长度path段被忽略
      • 如果没有传递path段,则path.resolve()将返回当前工作目录的绝对路径

    初识Webpack

    path模块在webpack的使用中有较大作用,所以预先介绍了一下,下面正式进入Webpack的学习

    • Webpack能够帮助我们进行模块化开发
    • 高级特性提升开发效率和代码安全性、可维护性,如 ES6+ TypeScript SASS Less 等都需要构建工具
    • 实时文件监听(开发热更新)、代码压缩合并等

    Released under the MIT License.

    - +
    • path.resolve 将多个路径片段解析、拼接为一个绝对路径
      • 从右往左处理传入的路径序列,每个路径依次被解析,直到构造完成一个绝对路径
      • 如果在处理完所有给定path的段之后,还没有生成绝对路径,则使用当前工作目录
      • 生成的路径被规范化并删除尾部斜杠,零长度path段被忽略
      • 如果没有传递path段,则path.resolve()将返回当前工作目录的绝对路径

    初识Webpack

    path模块在webpack的使用中有较大作用,所以预先介绍了一下,下面正式进入Webpack的学习

    • Webpack能够帮助我们进行模块化开发
    • 高级特性提升开发效率和代码安全性、可维护性,如 ES6+ TypeScript SASS Less 等都需要构建工具
    • 实时文件监听(开发热更新)、代码压缩合并等

    Released under the MIT License.

    + diff --git a/note/JavaScript.html b/note/JavaScript.html index 2dc6409d..86a074c3 100644 --- a/note/JavaScript.html +++ b/note/JavaScript.html @@ -8,14 +8,14 @@ - + - - + + diff --git a/note/JavaScriptEnhanced.html b/note/JavaScriptEnhanced.html index d23db625..4b51303b 100644 --- a/note/JavaScriptEnhanced.html +++ b/note/JavaScriptEnhanced.html @@ -8,7 +8,7 @@ - + @@ -2021,8 +2021,8 @@ setTimeout(() => { eventBus.off('navClick', callBack) // 移除某个事件的某次回调 }, 5000) -

    Released under the MIT License.

    - +
    + diff --git a/note/SSR.html b/note/SSR.html index d826b10c..4e2e7d27 100644 --- a/note/SSR.html +++ b/note/SSR.html @@ -8,7 +8,7 @@ - + @@ -27,8 +27,8 @@ "nuxt": "^3.2.0" } } -

    针对postinstall中执行的nuxi prepare脚本,官方文档有如下解释:

    The prepare command creates a .nuxt directory in your application and generates types. This can be useful in a CI environment or as a postinstall command in your package.json.

    执行该脚本后,将在项目根目录创建.nuxt文件夹

    配置 Configuration

    runtimeConfig 与 appConfig

    针对他们的比较,官方文档提供了一个表格可以参阅:

    FeatureruntimeConfigapp.config
    Client SideHydratedBundled
    Environment Variables✅ Yes❌ No
    Reactive✅ Yes✅ Yes
    Types support✅ Partial✅ Yes
    Configuration per Request❌ No✅ Yes
    Hot Module Replacement❌ No✅ Yes
    Non primitive JS types❌ No✅ Yes

    runtimeconfig-vs-appconfig

    区分Client和Server环境

    Nuxt为我们扩展了Node的process对象,并为我们在浏览器环境提供了process对象:

    页面与组件 View and Component

    Nuxt会自动为我们:注册组件、注册页面路由,约定>配置

    Nuxt3 内置组件

    Nuxt3 框架提供了一些内置的组件,常用的如下:

    创建页面

    文件目录即路由,,可以手动创建 也可以通过命令行快速创建页面

    路由中间件

    Nuxt提供了一个可定制的路由中间件,用来监听路由的导航,包括:局部和全局监听

    路由验证 Validate

    Nuxt支持对每个页面路由进行验证,可以通过definePageMeta中的validate数学对路由进行验证

    页面布局 Layout

    Layout布局是页面的包装器,可以将多个页面共性的东西抽取到Layout布局中

    例如:每个页面的页眉和页脚,这些具有共性的组件,我们可以写到一个Layout布局中

    本质上是Vue3的<slot>组件

    渲染模式

    浏览器和服务器都可以解释JavaScript代码,都可以将Vue.js组件呈现为HTML元素,此过程称为渲染

    而Nuxt3支持多种渲染模式

    - +

    针对postinstall中执行的nuxi prepare脚本,官方文档有如下解释:

    The prepare command creates a .nuxt directory in your application and generates types. This can be useful in a CI environment or as a postinstall command in your package.json.

    执行该脚本后,将在项目根目录创建.nuxt文件夹

    配置 Configuration

    runtimeConfig 与 appConfig

    针对他们的比较,官方文档提供了一个表格可以参阅:

    FeatureruntimeConfigapp.config
    Client SideHydratedBundled
    Environment Variables✅ Yes❌ No
    Reactive✅ Yes✅ Yes
    Types support✅ Partial✅ Yes
    Configuration per Request❌ No✅ Yes
    Hot Module Replacement❌ No✅ Yes
    Non primitive JS types❌ No✅ Yes

    runtimeconfig-vs-appconfig

    区分Client和Server环境

    Nuxt为我们扩展了Node的process对象,并为我们在浏览器环境提供了process对象:

    页面与组件 View and Component

    Nuxt会自动为我们:注册组件、注册页面路由,约定>配置

    Nuxt3 内置组件

    Nuxt3 框架提供了一些内置的组件,常用的如下:

    创建页面

    文件目录即路由,,可以手动创建 也可以通过命令行快速创建页面

    路由中间件

    Nuxt提供了一个可定制的路由中间件,用来监听路由的导航,包括:局部和全局监听

    路由验证 Validate

    Nuxt支持对每个页面路由进行验证,可以通过definePageMeta中的validate数学对路由进行验证

    页面布局 Layout

    Layout布局是页面的包装器,可以将多个页面共性的东西抽取到Layout布局中

    例如:每个页面的页眉和页脚,这些具有共性的组件,我们可以写到一个Layout布局中

    本质上是Vue3的<slot>组件

    渲染模式

    浏览器和服务器都可以解释JavaScript代码,都可以将Vue.js组件呈现为HTML元素,此过程称为渲染

    而Nuxt3支持多种渲染模式

    + diff --git a/project/ClipboardManager/guide/index.html b/project/ClipboardManager/guide/index.html index e6bf3716..bc90f9ea 100644 --- a/project/ClipboardManager/guide/index.html +++ b/project/ClipboardManager/guide/index.html @@ -8,7 +8,7 @@ - + @@ -29,8 +29,8 @@ "match": ["image", { "type": "file", "regex": ".(?:jpg|jpeg|png)$" }], "command": "redirect:上传到图床" } -

    这个功能除了可以匹配图片,还可以将符合正则的图片文件匹配上,在匹配上的历史记录上展示上传到图床按钮,携带数据跳转到图床插件,一键上传。

    需要注意的是,因为自定义功能按钮实现的是携带数据跳转不同插件,所以redirect后的内容并不应该是普通关键字(普通关键字仅能作为插件入口,而不能携带数据),而应该是文本/图片/文件或文件夹

    在未来的版本更新中,超级剪贴板将开放更多自定义功能给高级用户,帮助你更高效率的管理、使用剪贴板。

    - +

    这个功能除了可以匹配图片,还可以将符合正则的图片文件匹配上,在匹配上的历史记录上展示上传到图床按钮,携带数据跳转到图床插件,一键上传。

    需要注意的是,因为自定义功能按钮实现的是携带数据跳转不同插件,所以redirect后的内容并不应该是普通关键字(普通关键字仅能作为插件入口,而不能携带数据),而应该是文本/图片/文件或文件夹

    在未来的版本更新中,超级剪贴板将开放更多自定义功能给高级用户,帮助你更高效率的管理、使用剪贴板。

    + diff --git a/project/ClipboardManager/index.html b/project/ClipboardManager/index.html index f938d9ea..958c4b57 100644 --- a/project/ClipboardManager/index.html +++ b/project/ClipboardManager/index.html @@ -8,14 +8,14 @@ - + -
    Skip to content
    On this page

    🔰 开始使用

    首次安装需要设置“跟随主程序同时启动”

    • ✅ 监听剪贴板并持续将新内容更新到本地磁盘 数据读写完全本地化
    • ✅ 快速收藏/转存/分词/复制/删除/打开文件&目标文件夹
    • ✅ 功能按钮 定义无限可能 OCR识别 百度搜索 百度识图 统计文本字数 颜色管理 识别图片中二维码 上传到图床 翻译
    • 鼠标左键 复制并粘贴 鼠标右键 仅复制
    • ✅ 按下Shift空格进入多选模式 连续选择多条内容合并复制 支持跨标签合并复制/粘贴
    • ✅ 键盘 选中历史记录,按下回车直接粘贴
    • ✅ 键盘 切换分类 Tab键连续切换分类
    • ✅ 使用 Ctrl/Alt+数字键 快速粘贴
    • ✅ 插件内输入任意字母或数字自动聚焦搜索框 支持使用空格同时检索多个关键词
    • 智慧分词 快速拖选指定内容 超级粘贴 直接转存为文件
    • ✅ 优雅的界面动效与交互 跟随系统的深色模式
    • ✅ 优秀的剪贴板监听性能 强大的自定义功能按钮 自搭建多端同步 ···

    📚 安装方式

    催更群 769115389 Github

    Released under the MIT License.

    - +
    Skip to content
    On this page

    🔰 开始使用

    首次安装需要设置“跟随主程序同时启动”

    • ✅ 监听剪贴板并持续将新内容更新到本地磁盘 数据读写完全本地化
    • ✅ 快速收藏/转存/分词/复制/删除/打开文件&目标文件夹
    • ✅ 功能按钮 定义无限可能 OCR识别 百度搜索 百度识图 统计文本字数 颜色管理 识别图片中二维码 上传到图床 翻译
    • 鼠标左键 复制并粘贴 鼠标右键 仅复制
    • ✅ 按下Shift空格进入多选模式 连续选择多条内容合并复制 支持跨标签合并复制/粘贴
    • ✅ 键盘 选中历史记录,按下回车直接粘贴
    • ✅ 键盘 切换分类 Tab键连续切换分类
    • ✅ 使用 Ctrl/Alt+数字键 快速粘贴
    • ✅ 插件内输入任意字母或数字自动聚焦搜索框 支持使用空格同时检索多个关键词
    • 智慧分词 快速拖选指定内容 超级粘贴 直接转存为文件
    • ✅ 优雅的界面动效与交互 跟随系统的深色模式
    • ✅ 优秀的剪贴板监听性能 强大的自定义功能按钮 自搭建多端同步 ···

    📚 安装方式

    催更群 769115389 Github

    Released under the MIT License.

    + diff --git a/project/ClipboardManager/log/index.html b/project/ClipboardManager/log/index.html index f41dc70b..4b6f8115 100644 --- a/project/ClipboardManager/log/index.html +++ b/project/ClipboardManager/log/index.html @@ -8,14 +8,14 @@ - + -
    Skip to content
    On this page

    更新日志

    v2.0.5

    2023-02-19

    • fix: 修复插件启动时WebDav上传失败报错的问题
    • fix: 修复插件启动时会员用户登录联网失败的问题

    v2.0.4

    2023-02-13

    • feat: 支持修改代码高亮主题、样式与是否启用
    • feat: 右下角常驻当前选中条目的更新日期
    • feat: 页面滚动条样式优化
    • fix: 修复错误识别文本内容为网址的问题
    • fix: 修复删除条目后插件卡死的问题
    • fix: 修复某些情况下数据不再向下展示的问题

    v2.0.3

    2023-02-10

    • feat: 按住Ctrl/Command点击文本/链接 可以直接预览/跳转
    • feat: 按住Ctrl/Command点击图片 可以直接全局预览
    • feat: 按住Ctrl/Command点击文件 可以打开其所在文件夹
    • feat: 调整预览页展开样式
    • fix: 多选状态无法通过点击鼠标添加选项
    • fix: 某些情况下预览页无法执行Ctrl+C部分复制

    v2.0.2

    2023-02-10

    • fix: 更新到新版后首次进入白屏问题
    • fix: 新设备首次进入插件数据库路径读取问题
    • fix: 优化联网失败的弹窗逻辑
    • fix: 普通用户图标颜色异常

    v2.0.1

    2023-02-10

    • feat: 工具栏按钮顺序调整 会员用户添加金色标识
    • fix: 切换分类时出现明显卡顿
    • fix: 未登录用户进入用户中心白屏
    • fix: 添加网络问题导致登录验证失败的弹窗提醒

    v2.0.0

    2023-02-07

    • feat: 界面焕新 简洁高效
    • feat: 支持WebDav自动同步功能
    • feat: 支持预览页代码高亮
    • feat: 支持自定义分类卡片的顺序
    • feat: 支持识别文本内容为色值、链接等
    • feat: 支持左右键切换导航
    • feat: 支持关闭剪贴板图片记录
    • feat: 支持手动设置偏好主题
    • fix: 清空数据库保留收藏内容
    • fix: 滚动到底部触发懒加载失败
    • refactor: 组件重构 优化大列表运行时性能
    • refactor: 本地读写性能优化

    v1.4.7

    2022-11-03

    • feat: 设置页支持使用ESC返回上一级
    • fix: 移除了启动监听程序时对MacOS的特殊判断
    • fix: 移除了缺少监听程序时的通知报错

    v1.4.6

    2022-11-01

    • feat: 调整设置页图标与界面按钮细节
    • fix: 会员用户由于数据同步导致的插件白屏问题
    • fix: 多选复制时条目排序被颠倒

    v1.4.5

    2022-10-10

    • feat: 调整过期天数列表 最长支持31天
    • feat: 设置页添加handler安装引导
    • fix: 清空数据时内存数据未清空
    • fix: 多端同步时内存数据未更新
    • fix: 开发者模式下listener错误挂载

    v1.4.4

    2022-09-26

    • fix: 修复重复粘贴的问题

    v1.4.3

    2022-09-25

    • feat: 增加空格快捷键 按下连续多选的功能
    • feat: 多选状态下移动鼠标不再激活列表条目
    • feat: 支持展示剪贴板监听程序状态
    • fix: 删除某条历史记录时不再返回顶部
    • fix: 多选图片无法合并复制
    • fix: 内置按钮颜色管理关键字错误
    • fix: 设置页下拉框过长时被卡片遮挡
    • fix: 设置页滚动到底部触发懒加载

    v1.4.2

    2022-09-21

    • chore: 移除了插件内的二进制文件 恢复旧的监听机制 性能问题有待解决

    v1.4.1

    2022-09-21

    • fix: 修复了新的监听机制在 Mac 下无法正确获取剪贴板更新事件的问题

    v1.4.0

    2022-09-20

    插件能够正确在Linux上运行 离不开 小千 不厌其烦的测试与调试 💖

    感谢每一位为超级剪贴板提出过建议、参与测试与调试的用户

    • feat: 支持自定义数据库路径/存储条数/过期时间/展示在主界面的按钮
    • feat: 功能按钮支持自定义 创造属于你自己的功能按钮
    • feat: 添加了9个内置的自定义功能按钮
    • feat: 增加了更优雅的弹窗与提示界面
    • feat: 预览页更宽了 支持预览图片
    • feat: 导航栏图标样式修改
    • fix: 解决了CPU占用高、浏览大图卡顿的性能问题
    • fix: 从后台进入插件自动清空搜索框
    • refactor: 改变了监听剪贴板的方式 性能更优
    • refactor: 引入了ElementPlus组件库与图标库

    v1.3.4

    2022-09-19

    • feat: 移除插件内收藏Tab
    • feat: 点击收藏按钮后将携带数据跳转至备忘快贴
    • refactor: 优化代码执行逻辑 移除冗余代码

    v1.3.3

    2022-09-16

    • feat: 提高主色在深色模式下的对比度 改善长文本表现
    • feat: 添加快存功能按钮 配合超级粘贴插件实现快速转存
    • feat: 支持在预览页展示全部功能按钮
    • feat: 重要版本更新自动展示通知卡片
    • fix: 修正多选快捷键Shift影响检索输入的问题
    • fix: 检索词更新后 未自动激活首条记录

    v1.3.2

    2022-09-15

    • feat: 鼠标悬停展示具体日期、完整数据
    • feat: 调整历史记录上限为800条
    • fix: 修复鼠标置于功能按钮时上下键失效的问题
    • fix: 调整大图片判定尺寸

    v1.3.1

    2022-09-12

    • feat: 支持通过历史记录列表进入分词
    • feat: 减小插件体积 对智慧分词的支持改为插件跳转

    v1.3.0

    2022-09-09

    • feat: 添加多选功能 支持跨标签合并文本/图片/文件
    • feat: 支持通过按下Shift进入多选功能 支持按住Shift快速选择
    • feat: 支持使用Ctrl+CEnter快捷合并复制/粘贴
    • feat: 添加智慧分词功能 可对文本进行分割提取
    • feat: 长文本以蓝色高亮显示 不再提供查看全部按钮
    • feat: 优化界面动效

    v1.2.3

    2022-09-08

    • fix: 修复了检索内容时搜索记录不准确的问题

    v1.2.2

    2022-09-07

    • feat: 搜索框支持使用空格分词以同时检索多个关键词
    • fix: 修复了剪贴板数据记录遗漏的问题
    • fix: 收藏内容不再计入到条数限制中
    • fix: 修复了非预期的搜索框聚焦行为
    • fix: 预览页的按钮改为固定在顶部

    v1.2.1

    2022-09-05

    • feat: 支持通过功能按钮进入任意数据的预览页面
    • feat: 支持通过功能按钮打开文件所在目录
    • feat: 添加取消收藏功能按钮
    • feat: 搜索框支持展开/收起 输入任意内容展开并聚焦搜索
    • feat: 侧栏预览页添加复制全部智慧分词按钮
    • feat: 功能按钮改为使用图标展示
    • feat: 优化了界面样式
    • refactor: 清理定时器 优化插件性能

    v1.2.0

    2022-09-04

    • feat: 添加右侧操作栏 支持复制/收藏/删除操作
    • feat: 添加标签页收藏 支持在此页面管理所有收藏
    • feat: 调整侧栏宽度 调整界面样式细节

    v1.1.7

    2022-08-30

    • fix: 定时器检查剪贴板,修复了不记录剪贴板的问题

    v1.1.6

    2022-08-27

    • feat: 添加Alt+数字键Ctrl+数字键快速选择功能
    • feat: 调整界面样式 调整查看全部位置 移除图片背景色 增加动效
    • feat: 搜索框增加检索条数展示
    • fix: 改善插件读取图片的性能

    v1.1.5

    2022-08-25

    • fix: 提高剪贴板读取频率,避免高频复制时丢数据的情况

    v1.1.4

    2022-08-20

    • feat: 增加清空搜索框的按钮
    • feat: 优化插件内按下ESC的功能: 退出完整预览/清空搜索框
    • feat: 进入插件自动选中框内全部文本
    • fix: Mac在分离窗口状态左键会粘贴到搜索框 #13

    v1.1.3

    2022-08-19

    • feat: 调整界面在深色模式下的表现样式
    • fix: 在侧栏全部数据中使用Ctrl+C复制部分文本失效
    • fix: Mac下使用Ctrl+C复制单条记录失效
    • fix: 通过换行符个数区分超长文本
    • fix: 窗口分离下鼠标单击导致粘贴到搜索框
    • chore: 原插件名剪贴板改为超级剪贴板

    v1.1.2

    2022-08-18

    • feat: 执行复制后只隐藏主界面而不退出插件到后台
    • feat: 搜索时不再区分大小写
    • fix: 文本内容会出现异常首行缩进
    • fix: 图片展示在列表中的时候 右侧多出一个图块
    • fix: 移除鼠标hover时数据底部的色块

    v1.1.1

    2022-08-17

    • fix: 复制超大图片进入插件时崩溃

    v1.1.0

    2022-08-16

    • feat: 支持使用 键切换选中记录
    • feat: 支持使用 Ctrl+C 复制选中记录
    • feat: 支持使用 Enter 复制选中记录并粘贴

    v1.0.4

    2022-08-16

    • feat: 进入插件自动回到顶部、切换至全部分类
    • feat: 监听到键盘事件自动聚焦到搜索框
    • feat: 调整鼠标hover动画与历史记录的active样式
    • fix: 使用Tab切换导航失效
    • fix: 超长图片显示越界

    v1.0.3

    2022-08-16

    • fix: 路径分隔符导致写入错误的数据文件

    v1.0.2

    2022-08-15

    • fix: Mac下由权限导致的无法写入数据

    v1.0.1

    2022-08-15

    • feat: 区分鼠标点击行为:左键复制并粘贴,右键仅复制
    • feat: 适配深色模式
    • feat: 移除了右侧的查看更多按钮
    • feat: 单次展示的条数增加到了15条
    • feat: 增加条数限制500条 增加存储日期限制14天
    • feat: 增加了多平台支持
    • fix: 执行粘贴后主输入框未隐藏
    • refactor: Vue3重构

    v1.0.0

    2022-08-14

    • release: v1.0.0发布

    Released under the MIT License.

    - +
    Skip to content
    On this page

    更新日志

    v2.0.6

    2023-02-22

    • fix: 优化列表展示性能
    • fix: 优化本地读写稳定性 修复数据损坏导致的白屏问题
    • fix: 优化代码高亮依赖缓存 避免多次请求下载

    v2.0.5

    2023-02-19

    • fix: 修复插件启动时WebDav上传失败报错的问题
    • fix: 修复插件启动时会员用户登录联网失败的问题

    v2.0.4

    2023-02-13

    • feat: 支持修改代码高亮主题、样式与是否启用
    • feat: 右下角常驻当前选中条目的更新日期
    • feat: 页面滚动条样式优化
    • fix: 修复错误识别文本内容为网址的问题
    • fix: 修复删除条目后插件卡死的问题
    • fix: 修复某些情况下数据不再向下展示的问题

    v2.0.3

    2023-02-10

    • feat: 按住Ctrl/Command点击文本/链接 可以直接预览/跳转
    • feat: 按住Ctrl/Command点击图片 可以直接全局预览
    • feat: 按住Ctrl/Command点击文件 可以打开其所在文件夹
    • feat: 调整预览页展开样式
    • fix: 多选状态无法通过点击鼠标添加选项
    • fix: 某些情况下预览页无法执行Ctrl+C部分复制

    v2.0.2

    2023-02-10

    • fix: 更新到新版后首次进入白屏问题
    • fix: 新设备首次进入插件数据库路径读取问题
    • fix: 优化联网失败的弹窗逻辑
    • fix: 普通用户图标颜色异常

    v2.0.1

    2023-02-10

    • feat: 工具栏按钮顺序调整 会员用户添加金色标识
    • fix: 切换分类时出现明显卡顿
    • fix: 未登录用户进入用户中心白屏
    • fix: 添加网络问题导致登录验证失败的弹窗提醒

    v2.0.0

    2023-02-07

    • feat: 界面焕新 简洁高效
    • feat: 支持WebDav自动同步功能
    • feat: 支持预览页代码高亮
    • feat: 支持自定义分类卡片的顺序
    • feat: 支持识别文本内容为色值、链接等
    • feat: 支持左右键切换导航
    • feat: 支持关闭剪贴板图片记录
    • feat: 支持手动设置偏好主题
    • fix: 清空数据库保留收藏内容
    • fix: 滚动到底部触发懒加载失败
    • refactor: 组件重构 优化大列表运行时性能
    • refactor: 本地读写性能优化

    v1.4.7

    2022-11-03

    • feat: 设置页支持使用ESC返回上一级
    • fix: 移除了启动监听程序时对MacOS的特殊判断
    • fix: 移除了缺少监听程序时的通知报错

    v1.4.6

    2022-11-01

    • feat: 调整设置页图标与界面按钮细节
    • fix: 会员用户由于数据同步导致的插件白屏问题
    • fix: 多选复制时条目排序被颠倒

    v1.4.5

    2022-10-10

    • feat: 调整过期天数列表 最长支持31天
    • feat: 设置页添加handler安装引导
    • fix: 清空数据时内存数据未清空
    • fix: 多端同步时内存数据未更新
    • fix: 开发者模式下listener错误挂载

    v1.4.4

    2022-09-26

    • fix: 修复重复粘贴的问题

    v1.4.3

    2022-09-25

    • feat: 增加空格快捷键 按下连续多选的功能
    • feat: 多选状态下移动鼠标不再激活列表条目
    • feat: 支持展示剪贴板监听程序状态
    • fix: 删除某条历史记录时不再返回顶部
    • fix: 多选图片无法合并复制
    • fix: 内置按钮颜色管理关键字错误
    • fix: 设置页下拉框过长时被卡片遮挡
    • fix: 设置页滚动到底部触发懒加载

    v1.4.2

    2022-09-21

    • chore: 移除了插件内的二进制文件 恢复旧的监听机制 性能问题有待解决

    v1.4.1

    2022-09-21

    • fix: 修复了新的监听机制在 Mac 下无法正确获取剪贴板更新事件的问题

    v1.4.0

    2022-09-20

    插件能够正确在Linux上运行 离不开 小千 不厌其烦的测试与调试 💖

    感谢每一位为超级剪贴板提出过建议、参与测试与调试的用户

    • feat: 支持自定义数据库路径/存储条数/过期时间/展示在主界面的按钮
    • feat: 功能按钮支持自定义 创造属于你自己的功能按钮
    • feat: 添加了9个内置的自定义功能按钮
    • feat: 增加了更优雅的弹窗与提示界面
    • feat: 预览页更宽了 支持预览图片
    • feat: 导航栏图标样式修改
    • fix: 解决了CPU占用高、浏览大图卡顿的性能问题
    • fix: 从后台进入插件自动清空搜索框
    • refactor: 改变了监听剪贴板的方式 性能更优
    • refactor: 引入了ElementPlus组件库与图标库

    v1.3.4

    2022-09-19

    • feat: 移除插件内收藏Tab
    • feat: 点击收藏按钮后将携带数据跳转至备忘快贴
    • refactor: 优化代码执行逻辑 移除冗余代码

    v1.3.3

    2022-09-16

    • feat: 提高主色在深色模式下的对比度 改善长文本表现
    • feat: 添加快存功能按钮 配合超级粘贴插件实现快速转存
    • feat: 支持在预览页展示全部功能按钮
    • feat: 重要版本更新自动展示通知卡片
    • fix: 修正多选快捷键Shift影响检索输入的问题
    • fix: 检索词更新后 未自动激活首条记录

    v1.3.2

    2022-09-15

    • feat: 鼠标悬停展示具体日期、完整数据
    • feat: 调整历史记录上限为800条
    • fix: 修复鼠标置于功能按钮时上下键失效的问题
    • fix: 调整大图片判定尺寸

    v1.3.1

    2022-09-12

    • feat: 支持通过历史记录列表进入分词
    • feat: 减小插件体积 对智慧分词的支持改为插件跳转

    v1.3.0

    2022-09-09

    • feat: 添加多选功能 支持跨标签合并文本/图片/文件
    • feat: 支持通过按下Shift进入多选功能 支持按住Shift快速选择
    • feat: 支持使用Ctrl+CEnter快捷合并复制/粘贴
    • feat: 添加智慧分词功能 可对文本进行分割提取
    • feat: 长文本以蓝色高亮显示 不再提供查看全部按钮
    • feat: 优化界面动效

    v1.2.3

    2022-09-08

    • fix: 修复了检索内容时搜索记录不准确的问题

    v1.2.2

    2022-09-07

    • feat: 搜索框支持使用空格分词以同时检索多个关键词
    • fix: 修复了剪贴板数据记录遗漏的问题
    • fix: 收藏内容不再计入到条数限制中
    • fix: 修复了非预期的搜索框聚焦行为
    • fix: 预览页的按钮改为固定在顶部

    v1.2.1

    2022-09-05

    • feat: 支持通过功能按钮进入任意数据的预览页面
    • feat: 支持通过功能按钮打开文件所在目录
    • feat: 添加取消收藏功能按钮
    • feat: 搜索框支持展开/收起 输入任意内容展开并聚焦搜索
    • feat: 侧栏预览页添加复制全部智慧分词按钮
    • feat: 功能按钮改为使用图标展示
    • feat: 优化了界面样式
    • refactor: 清理定时器 优化插件性能

    v1.2.0

    2022-09-04

    • feat: 添加右侧操作栏 支持复制/收藏/删除操作
    • feat: 添加标签页收藏 支持在此页面管理所有收藏
    • feat: 调整侧栏宽度 调整界面样式细节

    v1.1.7

    2022-08-30

    • fix: 定时器检查剪贴板,修复了不记录剪贴板的问题

    v1.1.6

    2022-08-27

    • feat: 添加Alt+数字键Ctrl+数字键快速选择功能
    • feat: 调整界面样式 调整查看全部位置 移除图片背景色 增加动效
    • feat: 搜索框增加检索条数展示
    • fix: 改善插件读取图片的性能

    v1.1.5

    2022-08-25

    • fix: 提高剪贴板读取频率,避免高频复制时丢数据的情况

    v1.1.4

    2022-08-20

    • feat: 增加清空搜索框的按钮
    • feat: 优化插件内按下ESC的功能: 退出完整预览/清空搜索框
    • feat: 进入插件自动选中框内全部文本
    • fix: Mac在分离窗口状态左键会粘贴到搜索框 #13

    v1.1.3

    2022-08-19

    • feat: 调整界面在深色模式下的表现样式
    • fix: 在侧栏全部数据中使用Ctrl+C复制部分文本失效
    • fix: Mac下使用Ctrl+C复制单条记录失效
    • fix: 通过换行符个数区分超长文本
    • fix: 窗口分离下鼠标单击导致粘贴到搜索框
    • chore: 原插件名剪贴板改为超级剪贴板

    v1.1.2

    2022-08-18

    • feat: 执行复制后只隐藏主界面而不退出插件到后台
    • feat: 搜索时不再区分大小写
    • fix: 文本内容会出现异常首行缩进
    • fix: 图片展示在列表中的时候 右侧多出一个图块
    • fix: 移除鼠标hover时数据底部的色块

    v1.1.1

    2022-08-17

    • fix: 复制超大图片进入插件时崩溃

    v1.1.0

    2022-08-16

    • feat: 支持使用 键切换选中记录
    • feat: 支持使用 Ctrl+C 复制选中记录
    • feat: 支持使用 Enter 复制选中记录并粘贴

    v1.0.4

    2022-08-16

    • feat: 进入插件自动回到顶部、切换至全部分类
    • feat: 监听到键盘事件自动聚焦到搜索框
    • feat: 调整鼠标hover动画与历史记录的active样式
    • fix: 使用Tab切换导航失效
    • fix: 超长图片显示越界

    v1.0.3

    2022-08-16

    • fix: 路径分隔符导致写入错误的数据文件

    v1.0.2

    2022-08-15

    • fix: Mac下由权限导致的无法写入数据

    v1.0.1

    2022-08-15

    • feat: 区分鼠标点击行为:左键复制并粘贴,右键仅复制
    • feat: 适配深色模式
    • feat: 移除了右侧的查看更多按钮
    • feat: 单次展示的条数增加到了15条
    • feat: 增加条数限制500条 增加存储日期限制14天
    • feat: 增加了多平台支持
    • fix: 执行粘贴后主输入框未隐藏
    • refactor: Vue3重构

    v1.0.0

    2022-08-14

    • release: v1.0.0发布

    Released under the MIT License.

    + diff --git a/project/ClipboardManager/statement/index.html b/project/ClipboardManager/statement/index.html index 6056556d..28476d34 100644 --- a/project/ClipboardManager/statement/index.html +++ b/project/ClipboardManager/statement/index.html @@ -8,14 +8,14 @@ - + -
    Skip to content
    On this page

    Q&A

    为什么偶尔CPU占用特别高? 为什么预览图片时插件卡顿?

    这是由超级剪贴板监听剪贴板内容更新的机制决定的,为了不漏数据,超级剪贴板的监听策略为每300ms读取一次剪贴板内容并与上一次读取到的内容作比较。如果剪贴板当前位置是一张大图片,那么插件会反复读取这张图片,导致大量计算被用在了无意义的读取与对比上。

    插件市场中相同原理的同类插件的处理方法是:

    • 轮询比较两次剪贴板内容,如果检查到当前剪贴板内容数据量较大,则降低轮询时间间隔。
      • 这避免了读取大图片/长文本时的高占用,然而这很容易导致漏数据
    • 轮询比较两次剪贴板内容,由用户自定义轮询时间
      • 用户设置的轮询间隔时间长,读取大图片/长文本时不会导致高占用,但很容易漏数据。
      • 用户设置的轮询间隔时间较短,则又会造成高占用

    v1.4.0版本更新中,超级剪贴板换用了clipboard-event库监听剪贴板更新事件,这种方式性能更优,不需要反复读取剪贴板内容来做比较,而只需要在检查到剪贴板更新事件时通知插件读取一次剪贴板即可,完全解决了CPU占用高、浏览图片卡顿的问题。

    然而该库包含了二进制文件,这触发了uTools插件市场的安全限制而无法上架。所以自v1.4.2起,插件不再内置监听剪贴板更新事件的二进制文件,用户要使用低占用、高性能的剪贴板监听方案,可以自行下载并将其移动到剪贴板数据库文件所在目录,详见如何手动安装clipboard-event-handler,插件会自动判断使用新的抑或是旧的方案监听剪贴板更新。同时,自v1.4.3起,你可以在设置页查看当前剪贴板监听程序的运行状态。

    为什么官方的剪贴板插件没有CPU占用高这个问题?

    官方的剪贴板内容更新事件监听函数也是从一个二进制文件引出的,这个二进制文件跟随主程序启动,不受剪贴板插件的打开或关闭的影响。

    启动报错, 读取剪切板出错

    请尝试以下方法:

    1. 清空本地数据库文件
    2. 格式化uTools内的插件数据
    3. 完全退出插件后重启插件

    如果上述方法都无法解决你的问题,欢迎论坛回帖或加入QQ群交流具体情况

    为什么剪贴板记录会丢失?

    一般是由于插件退出后台运行导致的, 插件需要保持后台运行才能记录剪贴板, 请检查:

    • 是否正确设置了插件跟随主程序启动
    • 是否手动清理或关闭了后台插件 (在分离模式下关闭插件 使用clear命令 在插件列表退出插件)
    • 是否存在高频复制的操作 (高频复制可能会漏掉记录)

    我对这个插件的安全性有担忧, 插件偷窃我的隐私怎么办?

    首先, 我写这个插件不是为了获取你的隐私的, 我对你的隐私没有兴趣, 这一点你完全可以放心;

    其次uTools官方在插件上架前会对代码进行审查, 如果插件有高危行为, 那也不会过审;

    再其次, uTools大部分用户是程序员, 如果我真的在代码里藏了"毒", 那他们也有办法发现, 如果你真的对你的隐私十分关心, 可以选择从开源仓库下载代码自行构建

    我不懂代码, 我也不会构建, 但是我担心你的插件会窃取我的隐私

    我在贡献教程中详细说明了如何构建, JavaScript也并不是一门很高深的语言, 祝你能早日入门, 构建出安全的版本供自己使用, 学习的过程中遇到任何问题, 也欢迎随时与我交流 😄

    开源版本和插件市场版本的区别?

    开源版本后续将只提供必要的BUG修复, 不再添加新功能

    • 开源版本: 包含完整的基本功能, 可以自行构建开源版本, 通过安装离线插件方式使用
    • 市场版本: 包含后续更新的新功能插件会员功能, 可以直接从插件应用市场安装

    为什么不开源了, 为什么要开始收费?

    目前由我个人维护的开源版本已经趋于稳定, 可以满足绝大部分场景的需求

    • 代码开源的出发点不是为了让不愿付费的人白嫖开发者的劳动, 而是为开发提供更多的经验和思路, 开源的代码已经启发了一些开发者上架了自己的剪贴板插件应用
    • 开发和维护插件需要时间和精力, 插件付费可以鼓励我更积极的更新
    • 目前插件内已有的基本功能都不会转为收费, 可以放心使用

    Released under the MIT License.

    - +
    Skip to content
    On this page

    Q&A

    为什么偶尔CPU占用特别高? 为什么预览图片时插件卡顿?

    这是由超级剪贴板监听剪贴板内容更新的机制决定的,为了不漏数据,超级剪贴板的监听策略为每300ms读取一次剪贴板内容并与上一次读取到的内容作比较。如果剪贴板当前位置是一张大图片,那么插件会反复读取这张图片,导致大量计算被用在了无意义的读取与对比上。

    插件市场中相同原理的同类插件的处理方法是:

    • 轮询比较两次剪贴板内容,如果检查到当前剪贴板内容数据量较大,则降低轮询时间间隔。
      • 这避免了读取大图片/长文本时的高占用,然而这很容易导致漏数据
    • 轮询比较两次剪贴板内容,由用户自定义轮询时间
      • 用户设置的轮询间隔时间长,读取大图片/长文本时不会导致高占用,但很容易漏数据。
      • 用户设置的轮询间隔时间较短,则又会造成高占用

    v1.4.0版本更新中,超级剪贴板换用了clipboard-event库监听剪贴板更新事件,这种方式性能更优,不需要反复读取剪贴板内容来做比较,而只需要在检查到剪贴板更新事件时通知插件读取一次剪贴板即可,完全解决了CPU占用高、浏览图片卡顿的问题。

    然而该库包含了二进制文件,这触发了uTools插件市场的安全限制而无法上架。所以自v1.4.2起,插件不再内置监听剪贴板更新事件的二进制文件,用户要使用低占用、高性能的剪贴板监听方案,可以自行下载并将其移动到剪贴板数据库文件所在目录,详见如何手动安装clipboard-event-handler,插件会自动判断使用新的抑或是旧的方案监听剪贴板更新。同时,自v1.4.3起,你可以在设置页查看当前剪贴板监听程序的运行状态。

    为什么官方的剪贴板插件没有CPU占用高这个问题?

    官方的剪贴板内容更新事件监听函数也是从一个二进制文件引出的,这个二进制文件跟随主程序启动,不受剪贴板插件的打开或关闭的影响。

    启动报错, 读取剪切板出错

    请尝试以下方法:

    1. 清空本地数据库文件
    2. 格式化uTools内的插件数据
    3. 完全退出插件后重启插件

    如果上述方法都无法解决你的问题,欢迎论坛回帖或加入QQ群交流具体情况

    为什么剪贴板记录会丢失?

    一般是由于插件退出后台运行导致的, 插件需要保持后台运行才能记录剪贴板, 请检查:

    • 是否正确设置了插件跟随主程序启动
    • 是否手动清理或关闭了后台插件 (在分离模式下关闭插件 使用clear命令 在插件列表退出插件)
    • 是否存在高频复制的操作 (高频复制可能会漏掉记录)

    我对这个插件的安全性有担忧, 插件偷窃我的隐私怎么办?

    首先, 我写这个插件不是为了获取你的隐私的, 我对你的隐私没有兴趣, 这一点你完全可以放心;

    其次uTools官方在插件上架前会对代码进行审查, 如果插件有高危行为, 那也不会过审;

    再其次, uTools大部分用户是程序员, 如果我真的在代码里藏了"毒", 那他们也有办法发现, 如果你真的对你的隐私十分关心, 可以选择从开源仓库下载代码自行构建

    我不懂代码, 我也不会构建, 但是我担心你的插件会窃取我的隐私

    我在贡献教程中详细说明了如何构建, JavaScript也并不是一门很高深的语言, 祝你能早日入门, 构建出安全的版本供自己使用, 学习的过程中遇到任何问题, 也欢迎随时与我交流 😄

    开源版本和插件市场版本的区别?

    开源版本后续将只提供必要的BUG修复, 不再添加新功能

    • 开源版本: 包含完整的基本功能, 可以自行构建开源版本, 通过安装离线插件方式使用
    • 市场版本: 包含后续更新的新功能插件会员功能, 可以直接从插件应用市场安装

    为什么不开源了, 为什么要开始收费?

    目前由我个人维护的开源版本已经趋于稳定, 可以满足绝大部分场景的需求

    • 代码开源的出发点不是为了让不愿付费的人白嫖开发者的劳动, 而是为开发提供更多的经验和思路, 开源的代码已经启发了一些开发者上架了自己的剪贴板插件应用
    • 开发和维护插件需要时间和精力, 插件付费可以鼓励我更积极的更新
    • 目前插件内已有的基本功能都不会转为收费, 可以放心使用

    Released under the MIT License.

    + diff --git a/project/ClipboardManager/vip/index.html b/project/ClipboardManager/vip/index.html index 11ec950c..d5d3393f 100644 --- a/project/ClipboardManager/vip/index.html +++ b/project/ClipboardManager/vip/index.html @@ -8,14 +8,14 @@ - + -
    Skip to content
    On this page

    插件会员

    TIP

    超级剪贴板是一款 “随心所欲” 的软件。您可以永久免费使用它。

    但是,如果您真的喜欢它,您可以付费支持它的发展。作为答谢,您将获得更多更方便的功能。这取决于您,如果您不想,也没关系。谢谢你,祝你有美好的一天!☀️

    会员权益

    • 插件会员
      • WebDav数据多端同步 已上线
      • 支持保存2000条历史记录 已上线
      • 不限制历史记录过期时间 已上线
      • 文本内容增强, 按住Ctrl/Command点击文本/链接 可以直接预览/跳转 已上线
      • 图片预览增强, 按住Ctrl/Command点击图片 可以直接预览 已上线
      • 文件预览增强, 按住Ctrl/Command点击文件 可以打开其所在文件夹 已上线
      • 自定义分类排序 已上线
      • 预览页代码高亮 已上线
      • 关闭剪贴板图片记录 已上线
      • 插件使用统计 已上线
      • ...
    • uTools会员
      • 插件使用统计 已上线

    会员定价

    WARNING

    • 插件会员为大版本买断制,购买后即可享用当前版本(2.x)后续所有更新的会员内容
    • 插件会员为虚拟商品,购买后不支持退款
    • 插件会员的价格是浮动的,随着功能和权益的增加,不排除涨价的可能
    • 购买插件会员后如果出现相关问题,欢迎加入QQ群反馈

    插件会员定价8元,登录uTools账号后点击插件工具栏中个人中心图标进入购买页面

    购买后可使用会员功能,不购买不影响基本功能的使用,希望大家多多理解,按需购买

    WebDav同步功能

    WARNING

    如果剪贴板数据体积过大,可能出现同步时间过长、同步失败等问题

    建议及时删除保存在超级剪贴板内的图片,或关闭记录图片到剪贴板

    插件会员支持通过WebDav同步剪贴板数据

    获取服务器地址 账号 密钥后,仅需在插件内的设置页面添加WebDav配置后,

    每次本地数据库发生变化,都会将最新数据同步到同步到服务器(须开启插件内的自动同步 否则需要手动同步)

    WebDav

    • 如果配置了WebDav 则每天第一次进入插件时会自动从服务器拉取最新数据
    • 如果设置了自动同步 每次本地数据变化将自动同步本地数据到服务器
      • 插件会缓存云端数据文件的ETag 如果云端数据有更新 则采用云端数据覆盖本地数据
      • 数据文件的上传和下载都开启了gzip以节省流量与带宽
      • 清空本地数据库的同时也会触发云端文件清空
      • 可以选择关闭图片记录 以降低同步的数据文件体积 提高同步效率
    • 插件仅在每次启动时主动从云端拉取数据 云端数据的更新不会自动同步到本地
    • 可以通过点击工具栏按钮主动拉取云端数据到本地或上传数据到云端

    相关链接:

    代码高亮功能

    插件使用Shiki作为代码高亮库,为了压缩插件体积、提高代码执行效率,其相关依赖都将从CDN动态加载

    支持在设置页修改代码高亮的主题、可选语言、CDN地址,设置的首个语言为展开预览后的默认语言

    HighLight

    • 默认CDN地址: https://unpkg.com/shiki@0.14.1/
    • 默认主题: one-dark-pro
    • 默认语言: javascript css html json markdown php python ruby shellscript sql java c cpp csharp go

    更多可用主题/语言,见Github仓库:Shiki

    更多内容

    疑难解答

    Released under the MIT License.

    - +
    Skip to content
    On this page

    插件会员

    TIP

    超级剪贴板是一款 “随心所欲” 的软件。您可以永久免费使用它。

    但是,如果您真的喜欢它,您可以付费支持它的发展。作为答谢,您将获得更多更方便的功能。这取决于您,如果您不想,也没关系。谢谢你,祝你有美好的一天!☀️

    会员权益

    • 插件会员
      • WebDav数据多端同步 已上线
      • 支持保存2000条历史记录 已上线
      • 不限制历史记录过期时间 已上线
      • 文本内容增强, 按住Ctrl/Command点击文本/链接 可以直接预览/跳转 已上线
      • 图片预览增强, 按住Ctrl/Command点击图片 可以直接预览 已上线
      • 文件预览增强, 按住Ctrl/Command点击文件 可以打开其所在文件夹 已上线
      • 自定义分类排序 已上线
      • 预览页代码高亮 已上线
      • 关闭剪贴板图片记录 已上线
      • 插件使用统计 已上线
      • ...
    • uTools会员
      • 插件使用统计 已上线

    会员定价

    WARNING

    • 插件会员为大版本买断制,购买后即可享用当前版本(2.x)后续所有更新的会员内容
    • 插件会员为虚拟商品,购买后不支持退款
    • 插件会员的价格是浮动的,随着功能和权益的增加,不排除涨价的可能
    • 购买插件会员后如果出现相关问题,欢迎加入QQ群反馈

    插件会员定价8元,登录uTools账号后点击插件工具栏中个人中心图标进入购买页面

    购买后可使用会员功能,不购买不影响基本功能的使用,希望大家多多理解,按需购买

    WebDav同步功能

    WARNING

    如果剪贴板数据体积过大,可能出现同步时间过长、同步失败等问题

    建议及时删除保存在超级剪贴板内的图片,或关闭记录图片到剪贴板

    插件会员支持通过WebDav同步剪贴板数据

    获取服务器地址 账号 密钥后,仅需在插件内的设置页面添加WebDav配置后,

    每次本地数据库发生变化,都会将最新数据同步到同步到服务器(须开启插件内的自动同步 否则需要手动同步)

    WebDav

    • 如果配置了WebDav 则每天第一次进入插件时会自动从服务器拉取最新数据
    • 如果设置了自动同步 每次本地数据变化将自动同步本地数据到服务器
      • 插件会缓存云端数据文件的ETag 如果云端数据有更新 则采用云端数据覆盖本地数据
      • 数据文件的上传和下载都开启了gzip以节省流量与带宽
      • 清空本地数据库的同时也会触发云端文件清空
      • 可以选择关闭图片记录 以降低同步的数据文件体积 提高同步效率
    • 插件仅在每次启动时主动从云端拉取数据 云端数据的更新不会自动同步到本地
    • 可以通过点击工具栏按钮主动拉取云端数据到本地或上传数据到云端

    相关链接:

    代码高亮功能

    插件使用Shiki作为代码高亮库,为了压缩插件体积、提高代码执行效率,其相关依赖都将从CDN动态加载

    支持在设置页修改代码高亮的主题、可选语言、CDN地址,设置的首个语言为展开预览后的默认语言

    HighLight

    • 默认CDN地址: https://unpkg.com/shiki@0.14.1/
    • 默认主题: one-dark-pro
    • 默认语言: javascript css html json markdown php python ruby shellscript sql java c cpp csharp go

    更多可用主题/语言,见Github仓库:Shiki

    更多内容

    疑难解答

    Released under the MIT License.

    + diff --git a/project/SmartWordBreak/index.html b/project/SmartWordBreak/index.html index 72ae4486..095d781c 100644 --- a/project/SmartWordBreak/index.html +++ b/project/SmartWordBreak/index.html @@ -8,14 +8,14 @@ - + -
    Skip to content
    On this page
    logo

    ✨ 智慧分词,快速提取文本关键词。

    ⭐ 插件发布页🌎 Q&A🚚 更新日志

    🔰 开始使用

    服务器不会保留处理的数据, 但请避免使用此功能处理敏感数据

    • ✅ 支持选中文本后通过超级面板直接进入分词
    • ✅ 支持直接读取剪贴板文本分词
    • ✅ 支持单选/拖拽/跨段落快速拖选
    • ✅ 支持一键合并复制/粘贴/翻译/搜索
    • ✅ 普通用户有每日免费额度 每日0:00重置
    • ✅ 优雅、迅速的动效与交互 适配深色模式
    • ✅ 可以通过插件内入口获取更多额度
    • ✅ 与超级剪贴板插件集成,一次购买 多处使用

    📚 安装方式

    Released under the MIT License.

    - +
    Skip to content
    On this page
    logo

    ✨ 智慧分词,快速提取文本关键词。

    ⭐ 插件发布页🌎 Q&A🚚 更新日志

    🔰 开始使用

    服务器不会保留处理的数据, 但请避免使用此功能处理敏感数据

    • ✅ 支持选中文本后通过超级面板直接进入分词
    • ✅ 支持直接读取剪贴板文本分词
    • ✅ 支持单选/拖拽/跨段落快速拖选
    • ✅ 支持一键合并复制/粘贴/翻译/搜索
    • ✅ 普通用户有每日免费额度 每日0:00重置
    • ✅ 优雅、迅速的动效与交互 适配深色模式
    • ✅ 可以通过插件内入口获取更多额度
    • ✅ 与超级剪贴板插件集成,一次购买 多处使用

    📚 安装方式

    Released under the MIT License.

    + diff --git a/project/SmartWordBreak/log/index.html b/project/SmartWordBreak/log/index.html index b4441beb..0c1140ae 100644 --- a/project/SmartWordBreak/log/index.html +++ b/project/SmartWordBreak/log/index.html @@ -8,14 +8,14 @@ - + -
    Skip to content
    On this page

    更新日志

    v1.0.5

    2022-12-17

    • feat: 限免活动 每日免费额度调整为99 移除充值入口
    • fix: 修复历史记录显示问题

    v1.0.4

    2022-09-25

    • feat: 分词上限提高到了1000个字符
    • feat: token支持本地缓存

    v1.0.3

    2022-09-19

    • feat: 增加历史记录功能
    • fix: 移除了在tag外按下鼠标拖选的功能

    v1.0.2

    2022-09-13

    • feat: 支持跨段快速拖选
    • feat: 分词页添加了搜索粘贴功能
    • feat: 优化换行符在分词页的表现 支持包含换行符拖选

    v1.0.1

    2022-09-13

    • feat: 增加了拖选过程中的动效
    • feat: 调整了按钮样式与颜色
    • fix: 移除了碍事的toast

    v1.0.0

    2022-09-11

    • release: v1.0.0发布

    Released under the MIT License.

    - +
    Skip to content
    On this page

    更新日志

    v1.0.5

    2022-12-17

    • feat: 限免活动 每日免费额度调整为99 移除充值入口
    • fix: 修复历史记录显示问题

    v1.0.4

    2022-09-25

    • feat: 分词上限提高到了1000个字符
    • feat: token支持本地缓存

    v1.0.3

    2022-09-19

    • feat: 增加历史记录功能
    • fix: 移除了在tag外按下鼠标拖选的功能

    v1.0.2

    2022-09-13

    • feat: 支持跨段快速拖选
    • feat: 分词页添加了搜索粘贴功能
    • feat: 优化换行符在分词页的表现 支持包含换行符拖选

    v1.0.1

    2022-09-13

    • feat: 增加了拖选过程中的动效
    • feat: 调整了按钮样式与颜色
    • fix: 移除了碍事的toast

    v1.0.0

    2022-09-11

    • release: v1.0.0发布

    Released under the MIT License.

    + diff --git a/project/SmartWordBreak/statement/index.html b/project/SmartWordBreak/statement/index.html index 32e6c414..b019a1e9 100644 --- a/project/SmartWordBreak/statement/index.html +++ b/project/SmartWordBreak/statement/index.html @@ -8,14 +8,14 @@ - + -
    Skip to content
    On this page

    Q&A

    • Q: 为什么要收费
    • A: 此功能需要服务器资源, 而服务器资源有限, 故暂时只开放部分的免费资源给大家使用, 普通用户每日有部分免费额度, 额度每日0:00重置

    • Q: 我支付了,但是没有收到额度
    • A: 支付成功后,插件会自动获取最新用户信息,如果信息没有自动更新,请尝试退出插件后重新进入,如果仍未收到额度,请加入QQ群 769115389并联系我,我会尽快核实并为你解决

    • Q: 我之前赞赏过,可以有优惠吗
    • A: 2022年9月13日0:00前,赞赏过我的uTools用户,请发送:
      • UUID(超级分词插件内展示)
      • 赞赏金额
      • 赞赏时间
      • 支付截图
    • 到邮箱ZiuChen@outlook.com,邮箱主题为:申请超级分词赞赏额度,我将在核实后为你提供赞赏金额+15%的额度,感谢你的支持!💖。

    Released under the MIT License.

    - +
    Skip to content
    On this page

    Q&A

    • Q: 为什么要收费
    • A: 此功能需要服务器资源, 而服务器资源有限, 故暂时只开放部分的免费资源给大家使用, 普通用户每日有部分免费额度, 额度每日0:00重置

    • Q: 我支付了,但是没有收到额度
    • A: 支付成功后,插件会自动获取最新用户信息,如果信息没有自动更新,请尝试退出插件后重新进入,如果仍未收到额度,请加入QQ群 769115389并联系我,我会尽快核实并为你解决

    • Q: 我之前赞赏过,可以有优惠吗
    • A: 2022年9月13日0:00前,赞赏过我的uTools用户,请发送:
      • UUID(超级分词插件内展示)
      • 赞赏金额
      • 赞赏时间
      • 支付截图
    • 到邮箱ZiuChen@outlook.com,邮箱主题为:申请超级分词赞赏额度,我将在核实后为你提供赞赏金额+15%的额度,感谢你的支持!💖。

    Released under the MIT License.

    + diff --git a/self/index.html b/self/index.html index 36a1d49d..30f525f4 100644 --- a/self/index.html +++ b/self/index.html @@ -8,14 +8,14 @@ - + -
    Skip to content
    On this page

    个人介绍

    logo

    北京交通大学(BeijingJiaoTong University)电子信息工程学院本科在读

    • 熟悉ES6特性, 有前端领域开发经验, 能独立完成基础的前端开发工作;
    • 熟练使用Vue框架及相关工具开发应用, 阅读过部分Vue源码, 了解Vue响应式实现原理;
    • 掌握NodeJS基本使用, 能够基于NodeJS编写开发工具或搭建Web服务;
    • 了解Webpack基本配置和使用, 有Webpack Vite等前端工程化工具使用经验;
    • 了解Typescript, 有Typescript的项目使用经历;
    • 良好的Git操作, 清晰的Commit提交, 保证代码质量;
    • 对前端学习抱有热情, 有良好的学习能力, 能够快速学习掌握新知识;

    技术栈

    前端技术

    Vue Router Vuex Pinia Element Plus Echart WangEditor

    Sass/Less Axios Ajax ...

    后端技术

    相关技能

    文档处理:

    Microsoft Word Microsoft PowerPoint Microsoft Excel

    平面设计:

    Adobe PhotoShop Adobe Lightroom

    影音制作:

    DaVinci Resolve Studio Adobe Premiere Adobe After Effects

    专业软件:

    MATLAB ICEDA Multisim Keil uVision5

    获得奖项

    Microsoft Edge 浏览器开拓者大赛 开拓之星

    稀土掘金2022编程挑战赛 三等奖

    入选“扬帆计划·中央和国家机关大学生实习”

    100周年现场志愿者

    优秀学生干部、优秀共青团员

    社会工作优秀奖学金

    相关链接

    Github哔哩哔哩稀土掘金CSDNGitee

    Released under the MIT License.

    - +
    Skip to content
    On this page

    个人介绍

    logo

    北京交通大学(BeijingJiaoTong University)电子信息工程学院本科在读

    • 熟悉ES6特性, 有前端领域开发经验, 能独立完成基础的前端开发工作;
    • 熟练使用Vue框架及相关工具开发应用, 阅读过部分Vue源码, 了解Vue响应式实现原理;
    • 掌握NodeJS基本使用, 能够基于NodeJS编写开发工具或搭建Web服务;
    • 了解Webpack基本配置和使用, 有Webpack Vite等前端工程化工具使用经验;
    • 了解Typescript, 有Typescript的项目使用经历;
    • 良好的Git操作, 清晰的Commit提交, 保证代码质量;
    • 对前端学习抱有热情, 有良好的学习能力, 能够快速学习掌握新知识;

    技术栈

    前端技术

    Vue Router Vuex Pinia Element Plus Echart WangEditor

    Sass/Less Axios Ajax ...

    后端技术

    相关技能

    文档处理:

    Microsoft Word Microsoft PowerPoint Microsoft Excel

    平面设计:

    Adobe PhotoShop Adobe Lightroom

    影音制作:

    DaVinci Resolve Studio Adobe Premiere Adobe After Effects

    专业软件:

    MATLAB ICEDA Multisim Keil uVision5

    获得奖项

    Microsoft Edge 浏览器开拓者大赛 开拓之星

    稀土掘金2022编程挑战赛 三等奖

    入选“扬帆计划·中央和国家机关大学生实习”

    100周年现场志愿者

    优秀学生干部、优秀共青团员

    社会工作优秀奖学金

    相关链接

    Github哔哩哔哩稀土掘金CSDNGitee

    Released under the MIT License.

    + diff --git a/works/contribution.html b/works/contribution.html index a3fe5365..620ffe66 100644 --- a/works/contribution.html +++ b/works/contribution.html @@ -8,14 +8,14 @@ - + -
    Skip to content
    On this page

    社区贡献

    稀土掘金助手

    稀土掘金助手: 腾讯云函数部署

    源代码

    B站粉丝牌助手文档

    B站粉丝牌助手文档

    源代码Demo

    Released under the MIT License.

    - +
    Skip to content
    On this page

    社区贡献

    稀土掘金助手

    稀土掘金助手: 腾讯云函数部署

    源代码

    B站粉丝牌助手文档

    B站粉丝牌助手文档

    源代码Demo

    Released under the MIT License.

    + diff --git a/works/opensource.html b/works/opensource.html index 7590085e..30ad8db5 100644 --- a/works/opensource.html +++ b/works/opensource.html @@ -8,14 +8,14 @@ - + -
    Skip to content
    On this page

    个人作品

    Vue3+TypeScript后台管理系统

    Vue3+TypeScript后台管理系统

    源代码

    Typein 效率工具集

    Typein 是一个运行在现代浏览器上的拓展插件,它可以帮助你在保持专注的情况下,高效完成各种操作。

    源代码

    宣传视频

    Microsoft Edge Add-on Store

    A-SOUL浏览器宠物

    在浏览器里养一只A-Soul成员当宠物

    源代码

    宣传视频

    北京交通大学课程平台功能增强

    北京交通大学课程平台功能增强脚本,实现信息聚合,附件上传,让你高效处理课程信息。

    源代码

    超级剪贴板

    uTools插件,一款强大的剪贴板管理工具。基于Vue3构建

    源代码

    主页

    超级粘贴

    uTools插件,将剪切板内容直接粘贴为文件。功能基于NodeJS

    源代码

    超级分词

    uTools插件,前台使用Vue3+ElementPlus构建,后台基于Express封装结巴分词并暴露API接口

    超级连点器

    uTools插件,界面使用Vue3+AntDesign构建,功能基于Worker

    PopNotify

    仿 Element UI 的通知卡片。

    源代码

    Demo

    UserScripts

    用户脚本合集,生产力工具、效率工具、自动化脚本

    源代码

    Released under the MIT License.

    - +
    Skip to content
    On this page

    个人作品

    Vue3+TypeScript后台管理系统

    Vue3+TypeScript后台管理系统

    源代码

    Typein 效率工具集

    Typein 是一个运行在现代浏览器上的拓展插件,它可以帮助你在保持专注的情况下,高效完成各种操作。

    源代码

    宣传视频

    Microsoft Edge Add-on Store

    A-SOUL浏览器宠物

    在浏览器里养一只A-Soul成员当宠物

    源代码

    宣传视频

    北京交通大学课程平台功能增强

    北京交通大学课程平台功能增强脚本,实现信息聚合,附件上传,让你高效处理课程信息。

    源代码

    超级剪贴板

    uTools插件,一款强大的剪贴板管理工具。基于Vue3构建

    源代码

    主页

    超级粘贴

    uTools插件,将剪切板内容直接粘贴为文件。功能基于NodeJS

    源代码

    超级分词

    uTools插件,前台使用Vue3+ElementPlus构建,后台基于Express封装结巴分词并暴露API接口

    超级连点器

    uTools插件,界面使用Vue3+AntDesign构建,功能基于Worker

    PopNotify

    仿 Element UI 的通知卡片。

    源代码

    Demo

    UserScripts

    用户脚本合集,生产力工具、效率工具、自动化脚本

    源代码

    Released under the MIT License.

    +