跳到主要内容

Docusaurus2 使用 Algolia DocSearch

· 阅读需 1 分钟
TransonQ
Front-end Engineer

指引​

链接: 使用 Algolia DocSearch 官方指引

链接: 申请 DocSearch

提交后大约 1-2 天内会收到 反馈邮件, 通知注册成功. 然后登录到 个人中心

AlgoliaDocSearch-1

AlgoliaDocSearch-2

AlgoliaDocSearch-3

配置​

docusaurus.config.js
algolia: {
// The application ID provided by Algolia
appId: '',
// Public API key: it is safe to commit it
apiKey: '',
// algolia application name
indexName: '',
// ... ...
},

AlgoliaDocSearch-4

vite部署线上报MIME类型错误

· 阅读需 1 分钟
TransonQ
Front-end Engineer

错误如下​

Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "application/octet-stream".  Strict MIME type checking is enforced for module scripts per HTML spec.

配置文件解决​

注意: 添加头的方法在 amplify.yml 可能有用, 但是主要是看你构建目录是否正确, 亚马逊配置如果目录不对, 有时候可以构建成功! Vite 默认构建目录是 dist , CRA默认构建目录是 build

使用“customHeaders”属性配置了所有 JavaScript 文件的 MIME 类型为“application/javascript”。

vite-amplify-error.png

nginx解决​

types {
application/javascript js;
}

还找到这个解决方法

sudo vi /etc/nginx/mime.types

找到或者补充这一行

application/javascript js

在末尾添加

application/javascript js mjs

重启nginx

sudo nginx -s reload

Apache 服务器解决​

AddType application/javascript .js

vscode中自定义peacock插件

· 阅读需 2 分钟
TransonQ
Front-end Engineer

安装​

扩展市场: peacock

配置​

因为一般都有自己喜欢的主题, 我使用的是暗色主题 Ayu,所以默认配置是把侧边栏,状态栏,标题栏都换了颜色, 有点扎眼, 不过由于右下角的remote标志是比较亮的颜色, 所以就配置成底部状态栏颜色区分,就比较舒服了.

peacock-setting-1.png

只设置状态栏​

peacock-setting-2.png

配置预设颜色​

peacock-setting-3.png

 "peacock.favoriteColors": [
{
"name": "漩涡鸣人",
"value": "#ff8906"
},
{
"name": "宇智波佐助",
"value": "#6246ea"
},
{
"name": "春野樱",
"value": "#fec7d7"
},
{
"name": "旗木卡卡西",
"value": "#078080"
},
{
"name": "日向雏田",
"value": "#bae8e8"
},
{
"name": "Node Green",
"value": "#215732"
},
{
"name": "雾霾蓝",
"value": "#232946"
},
{
"name": "尘埃灰",
"value": "#72757e"
},
{
"name": "森林绿",
"value": "#00473e"
},
{
"name": "星空黑",
"value": "#0f0e17"
},
{
"name": "原野绿",
"value": "#215732"
},
],

设置成功​

peacock-setting-4.png

window.location

· 阅读需 6 分钟
TransonQ
Front-end Engineer

window.location对象是一个包含当前页面URL信息的对象。

{
"href": "https://transon.netlify.app/blog/2023-05-24-download-blob#typescript-%E7%89%88%E6%9C%AC",
"protocol": "https:",
"host": "transon.netlify.app",
"hostname": "transon.netlify.app",
"port": "",
"pathname": "/blog/2023-05-24-download-blob",
"search": "",
"hash": "#typescript-%E7%89%88%E6%9C%AC",
"origin": "https://transon.netlify.app",
assign:()=>{},
reload:()=>{},
replace:()=>{},
"ancestorOrigins": {},
}

1. .href​

href属性返回当前页面的URL地址,可以读取和设置。例如:

// 获取当前页面的URL地址
var url = window.location.href;
console.log(url);

// 通过设置href属性来重定向页面
window.location.href = "http://www.example.com";

2. .protocol​

protocol属性返回当前页面的协议名称(例如http:或https:),可以读取和设置。例如:

// 获取当前页面的协议名称
var protocol = window.location.protocol;
console.log(protocol);

// 通过设置protocol属性来切换协议
window.location.protocol = "https:";

3. .host​

host属性返回当前页面的主机名和端口号(例如www.example.com:8080),可以读取和设置。例如:

// 获取当前页面的主机名和端口号
var host = window.location.host;
console.log(host);

// 通过设置host属性来修改主机名和端口号
window.location.host = "www.example.com:8080";

4. .hostname​

hostname属性返回当前页面的主机名(例如www.example.com),可以读取和设置。例如:

// 获取当前页面的主机名
var hostname = window.location.hostname;
console.log(hostname);

// 通过设置hostname属性来修改主机名
window.location.hostname = "www.example.com";

5. .port​

port属性返回当前页面的端口号(例如8080),可以读取和设置。例如:

// 获取当前页面的端口号
var port = window.location.port;
console.log(port);

// 通过设置port属性来修改端口号
window.location.port = "8080";

6. .pathname​

pathname属性返回当前页面的路径(例如/index.html),可以读取和设置。例如:

// 获取当前页面的路径
var pathname = window.location.pathname;
console.log(pathname);

// 通过设置pathname属性来修改路径
window.location.pathname = "/newpage.html";

search属性返回当前页面的查询字符串部分(例如?id=123&name=John),可以读取和设置。例如:

// 获取当前页面的查询字符串部分
var search = window.location.search;
console.log(search);

//通过设置search属性来添加查询参数
window.location.search = "?id=123&name=John";

8. .hash​

hash属性返回当前页面的锚点部分(例如#section1),可以读取和设置。例如:

// 获取当前页面的锚点部分
var hash = window.location.hash;
console.log(hash);

// 通过设置hash属性来跳转到指定的锚点
window.location.hash = "#section2";

9. .origin​

origin属性返回当前页面的域名(包括协议和端口号),例如http://www.example.com:8080。该属性只读。例如:

// 获取当前页面的域名(包括协议和端口号)
var origin = window.location.origin;
console.log(origin);

10. .assign(url)​

assign()方法会将当前窗口重定向到指定的URL地址,可以用来实现页面跳转。例如:

// 将当前页面重定向到指定的URL地址
window.location.assign("http://www.example.com");

11. .reload()​

reload()方法会重新加载当前页面,可以用来实现页面刷新。例如:

// 刷新当前页面
window.location.reload();

12. .replace(url)​

replace()方法会将当前窗口的URL地址替换为指定的URL地址,可以用来实现页面跳转。它与assign()方法的区别在于,replace()方法不会将新的URL地址添加到浏览器的历史记录中,因此用户不能使用“后退”按钮返回该URL地址之前的页面。例如:

// 将当前页面的URL地址替换为指定的URL地址
window.location.replace("http://www.example.com");

13. .ancestorOrigins​

window.location.ancestorOrigins属性返回一个DOMString列表,其中包含了当前页面所有祖先页面的域名(协议+主机名+端口号)。

如果当前页面在一个iframe或嵌套的子页面中,则这个列表会包含所有祖先页面的域名。如果当前页面不在iframe或嵌套的子页面中,则这个列表为空。

这个属性只读,不支持设置。以下是一个示例代码:

// 获取当前页面所有祖先页面的域名
var ancestorOrigins = window.location.ancestorOrigins;

// 遍历所有祖先页面的域名
for (var i = 0; i < ancestorOrigins.length; i++) {
console.log(ancestorOrigins[i]);
}

如果当前页面在一个iframe或嵌套的子页面中,以上代码会输出所有祖先页面的域名。如果当前页面不在iframe或嵌套的子页面中,则输出一个空列表。

需要注意的是,window.location.ancestorOrigins属性只在一些较新的浏览器中支持,如果你的代码需要在老旧的浏览器中运行,建议先判断一下是否支持该属性再使用。

以上就是window.location对象的常用属性及其用法。这些属性可以让我们方便地获取和设置页面的URL信息,从而实现各种功能,例如重定向、切换协议、修改查询参数等等。

blob 下载函数

· 阅读需 2 分钟
TransonQ
Front-end Engineer

JavaScript 版本​

function downloadBlob(blob, filename) {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
URL.revokeObjectURL(url);
}, 0);
}
  • 这个函数接收两个参数,第一个参数是一个Blob对象,第二个参数是要下载的文件名。
  • 该函数使用createObjectURL方法将Blob对象转换为URL,然后创建一个a标签并设置其href属性为该URL,download属性为文件名。
  • 接着将a标签添加到DOM中,并模拟用户点击该a标签来触发下载。
  • 最后,我们需要等待浏览器完成下载后,从DOM中移除a标签,并使用revokeObjectURL方法释放该URL。

TypeScript 版本​

function downloadBlob(blob: Blob, filename: string): void {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
URL.revokeObjectURL(url);
}, 0);
}

这个函数跟上面的代码是一样的,只是加上了类型注解。第一个参数是一个Blob对象,类型为Blob,第二个参数是要下载的文件名,类型为字符串。函数的返回值为void,因为我们只是触发了浏览器的下载操作,并没有返回任何值。

React项目中使用Google reCAPTCHA

· 阅读需 2 分钟
TransonQ
Front-end Engineer

一. 注册密钥​

首先,你需要在 Google reCAPTCHA 网站(https://www.google.com/recaptcha/admin/create)上注册并获取 API 密钥。完成注册后,你将获得一个 siteKey 和一个 secretKey,这些信息将用于在前端和后端验证 reCAPTCHA 响应。

二. 安装 reCAPTCHA 包​

npm
npm install react-google-recaptcha
yarn
yarn add react-google-recaptcha

三. 使用​

部分代码示意
import ReCAPTCHA from 'react-google-recaptcha'

const { REACT_APP_RECAPTCHA_KEY } = process.env // siteKey 配置进环境变量, 通常测试环境和正式环境是不一样的
...

const recaptchaRef = useRef(null) // 可以获取到 recaptcha 自带的方法
/**
* 验证用户是否完成了验证码测试的方法 execute:
* recaptchaRef.current.execute()
*
* 服务重新启动的方法 reset:
* recaptchaRef.current.reset();
*/

const [isVertified, setIsVertified] = useState(false) // 是否已经验证
const [recaptcha, setRecaptcha] = useState('') // 验证码存储, 如果遇到不想更新视图的场景, 考虑使用 useRef 储存

const onChange = (value) => {
// 拿到用户点击后的验证码, 通常需要后端接收这个验证码, 所以其一般是请求体的某个字段值
if (value) {
setIsVertified(true)
setRecaptcha(value)
}
}

...
return (
<>
<ReCAPTCHA
ref={recaptchaRef}
// size="invisible"
sitekey={REACT_APP_RECAPTCHA_KEY}
onChange={onChange}
/>
<Button disabled={!isVertified}>
Submit
</Button>
</>
)


react 实用工具UI库

· 阅读需 1 分钟
TransonQ
Front-end Engineer

React Hot Toast​

yarn add react-hot-toast
App.jsx
function App(){
return <><Toaster position="bottom-center"/></>
}
hotToast.ts
import { toast } from 'react-hot-toast'
type optionProps = {
error?: boolean
}

const color = {
critical: 'rgba(216, 44, 13, 1)', // --p-action-critical 错误色
default: 'rgba(32, 33, 35, 1)', // --p-surface-dark 默认黑色
}

export const hotToast = (msg: string, options?: optionProps) => {
toast(msg, {
style: {
borderRadius: '4px',
background: !options?.error ? color.default : color.critical,
color: '#fff',
},
})
}

使用
hotToast("提示信息")
hotToast("错误信息",{error:true})

Sonner​

yarn add sonner

用法同React Hot Toast

React Wrap Balancer​

yarn add react-wrap-balancer
使用方法
import Balancer from 'react-wrap-balancer'

// ...

<h1>
<Balancer>My Title</Balancer>
</h1>
多个组件可以共享逻辑
import { Provider } from 'react-wrap-balancer'

// ...

<Provider>
<App/>
</Provider>

MacOS停止制定端口的进程

· 阅读需 1 分钟
TransonQ
Front-end Engineer

前段时间升级了vscode之后, 发现升级或者在开发服务器未关闭的情况下,重启vscode没有停止对应端口的进程,导致一个现象就是:开发服务器未关闭重启vscode端口被莫名占用。

找到了两个命令查询对应端口占用的进程:

lsof -i :3000

macos-lsof

停止进程
kill -9 10956

useDebounceFn

· 阅读需 1 分钟
TransonQ
Front-end Engineer

useDebounceFn​

import { debounce } from 'lodash'
import { useMemo } from 'react'
import { useUnmount } from 'react-use'
import { useLatest } from './useLatest'

type DebounceOptions = {
// 间隔时间
wait?: number
leading?: boolean
trailing?: boolean
maxWait?: number
}

type useDebounceFnRetrunProps = {
run: () => void
cancel: () => void
flush: () => void
}

// ahooks 参数相同, 用法相同
export const useDebounceFn = (
fn: Function,
options?: DebounceOptions
): useDebounceFnRetrunProps => {
const fnRef = useLatest(fn)

const wait = options?.wait ?? 1000

const debounced = useMemo(
() =>
debounce(
(...args) => {
return fnRef.current(...args)
},
wait,
options
),
// 不能加依赖, 否则可能导致死循环
// eslint-disable-next-line
[]
)

useUnmount(() => {
debounced.cancel()
})

return {
run: debounced,
cancel: debounced.cancel,
flush: debounced.flush,
}
}

useLatest​

import { useRef } from 'react'

export function useLatest<T>(value: T) {
const ref = useRef(value)
ref.current = value

return ref
}