你在工作中,有没有遇到过每个一个页面,然后我们每个页面的title都是要设置不同的标题?
接下来我们手写一个自定义hooks 来解放我们的双手。
我们先进行梳理需求。
- 我们可以刚刚进页面的时候初始化一个title。
- 我们有可能在组件卸载的时候恢复到原来的title。
我们需求梳理清楚了,就可以进行代码的编写了。 代码如下:
import { useEffect, useRef } from 'react';
/**
* 获取当前环境是否是浏览器环境
* @returns boolean
*/
function getIsBrowser(): boolean {
const isBrowser = !!(
typeof window !== 'undefined' &&
window.document &&
window.document.createElement
);
return isBrowser;
}
interface Options {
restoreOnUnmount?: boolean;
}
/**
* @param title
* @param options
*/
function useTitle(title: string, options: Options = { restoreOnUnmount: false }) {
// 我们需要先拿到原来的title 进行保存起来 我们要判断当前环境是不是浏览器
const isBrowser = getIsBrowser();
const titleRef = useRef(isBrowser ? document.title : '');
useEffect(() => {
document.title = title;
},
[title]);
// 组件卸载
useEffect(
() => () => {
if (options.restoreOnUnmount) {
document.title = titleRef.current;
}
},
[],
);
}
export default function IndexPage() {
// 使用
useTitle('11111');
return (
<div>
</div>
);
}
既然我们都使用hooks 比如有一些操作是可以进行在进行封装的,比如我们封装的每个hooks可能在组件卸载的时候进行做一些操作
完整版本
import { useEffect, useRef, useState } from 'react';
/**
* 卸载hooks
*/
function useUnload(fn: () => void) {
if (typeof fn !== 'function') {
console.error(`你传的fn类型如下: ${typeof fn}`);
return;
};
const fnRef = useRef(fn);
useEffect(() => () => { fnRef.current() }, []);
};
/**
* 获取当前环境是否是浏览器环境
* @returns boolean
*/
function getIsBrowser(): boolean {
const isBrowser = !!(
typeof window !== 'undefined' &&
window.document &&
window.document.createElement
);
return isBrowser;
}
interface Options {
restoreOnUnmount?: boolean;
}
/**
* @param title
* @param options
*/
function useTitle(title: string, options: Options = { restoreOnUnmount: false }) {
// 我们需要先拿到原来的title 进行保存起来 我们要判断当前环境是不是浏览器
const isBrowser = getIsBrowser();
const titleRef = useRef(isBrowser ? document.title : '');
useEffect(() => {
document.title = title;
},
[title]);
useUnload(() => {
if (options.restoreOnUnmount) {
document.title = titleRef.current;
}
});
};