nextjs 动态修改浏览器title

1,276 阅读1分钟

需求背景:根据每次打开列表详情的标题修改浏览器的标签的title。
react版本:18
next版本:14.1.0

以下是官网的2种方式,nextjs官网generateMetadata定位

import { Metadata } from 'next'

// either Static metadata
export const metadata: Metadata = {
  title: '...',
}
 
// or Dynamic metadata
export async function generateMetadata({ params }) {
  return {
    title: '...',
  }
}

静态修改浏览器标签title

import { Metadata } from 'next'
// 使用时需要注意页面要多套一层,在page.tsx的同级新建page.client.tsx
// 在page.tsx中引入
import PageClient from "./page.client";

export const metadata: Metadata = {
  title: '...',
}

export default async function Page() {
  return <PageClient />;
}

动态修改浏览器标签title(官网是在generateMetadata放了请求),以下是请求放在page里面

// 记录一下,下次遇到这种需求可以直接 cv
import PageClient from "./page.client";

// 定义元数据类型
interface MetaData {
  title: string;
  description?: string;
}

class metaTitle {
  private events: { [eventName: string]: Array<(data: MetaData) => void> } = {};

  // 订阅
  on(eventName: string, callback: (data: MetaData) => void) {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }
    this.events[eventName].push(callback);
  }

  // 取消订阅
  off(eventName: string, callback: (data: MetaData) => void) {
    if (this.events[eventName]) {
      const eventIndex = this.events[eventName].indexOf(callback);
      if (eventIndex !== -1) {
        this.events[eventName].splice(eventIndex, 1);
      }
    }
  }

  // 发布
  emit(eventName: string, data: MetaData) {
    if (this.events[eventName]) {
      this.events[eventName].forEach((callback: (arg: MetaData) => void) => {
        callback(data);
      });
    }
  }

  // 设置元数据,数据类型明确
  setMetaData(data: MetaData) {
    this.emit('metatitle', data);
  }

  // 获取元数据,使用Promise封装异步逻辑
  getMetaData(): Promise<MetaData> {
    return new Promise((resolve) => {
      const callback = (data: MetaData) => {
        resolve(data);
        this.off('metatitle', callback);
      };
      this.on('metatitle', callback);
    });
  }
}
 
const eventMetaTitle = new metaTitle();

export async function generateMetadata() {
  return await eventMetaTitle.getMetaData();
}

export default async function Page(props: { searchParams: { id: string; }; }) {
  const { data } = await fetch(`https://.../${props.searchParams.id}`).then((res) => res.json());
  eventMetaTitle.setMetaData({
    title: `title-${data.title}`,
    description: data?.description || ""
  })
  return <PageClient data={data} />;
}

这里说一下nextjs文档一定要看英文的,中文更新太慢了有一些废弃了的没有更新到