react中使用复制的功能

在react中使用最新的navigator.clipboard.writeText(url)方法来实现复制的功能

javascript 复制代码
import React, { FC, useRef, useMemo } from 'react'
import { Space, Button, Typography, Input, Tooltip, message, Popover } from 'antd'
import type { InputRef } from 'antd'
import { LeftOutlined, CopyOutlined, QrcodeOutlined } from '@ant-design/icons'
import { useNavigate, useParams } from 'react-router-dom'
import QRCode from 'qrcode.react'
import useGetPageInfo from '../../../hooks/useGetPageInfo'
import styles from './StatHeader.module.scss'

const { Title } = Typography

/**
 * 统计页头部组件
 * 负责展示问卷标题、返回按钮、分享链接/二维码以及编辑入口
 */
const StatHeader: FC = () => {
  // 获取路由跳转函数
  const nav = useNavigate()
  // 获取路由参数中的问卷 ID
  const { id } = useParams()

  // 使用自定义 Hook 获取问卷页面信息(标题、是否已发布)
  const { title, isPublished } = useGetPageInfo()

  // 创建一个 ref 来引用链接输入框,用于获取 URL 值(虽然这里直接拼接了,但保留了通过 DOM 获取的逻辑)
  const urlInputRef = useRef<InputRef>(null)

  /**
   * 复制链接到剪贴板的异步函数
   * 使用现代 Clipboard API 实现
   */
  async function copy() {
    const elem = urlInputRef.current
    if (elem == null) return
    
    // 从输入框元素中获取 URL 值
    // 注意:这里使用了可选链操作符,防止 elem.input 为 undefined
    const url = elem.input?.value || ''
    
    try {
      // 调用浏览器原生 API 写入剪贴板
      await navigator.clipboard.writeText(url)
      message.success('拷贝成功')
    } catch (err) {
      // 捕获并处理写入失败的情况(如权限被拒、非安全上下文等)
      message.error('拷贝失败')
      console.error('Failed to copy: ', err)
    }
  }

  // 使用 useMemo 进行性能优化:仅当 id 或 isPublished 变化时重新计算
  // 目的:避免每次渲染都重新创建复杂的 JSX 元素(包含 Input, Button, QRCode),减少重渲染开销
  const LinkAndQRCodeElem = useMemo(() => {
    // 如果问卷未发布,则不显示分享组件
    if (!isPublished) return null

    // 拼接问卷的访问 URL (基于 C 端访问规则)
    // 注意:此处为本地开发环境地址,生产环境需替换为正式域名
    const url = `http://localhost:3000/question/${id}`

    // 定义二维码弹窗的内容组件
    const QRCodeElem = (
      <div style={{ textAlign: 'center' }}>
        {/* 使用 qrcode.react 库生成二维码,指定大小为 150px */}
        <QRCode value={url} size={150} />
      </div>
    )

    // 返回包含链接输入框、复制按钮和二维码按钮的工具栏
    return (
      <Space>
        {/* 只读输入框显示链接 */}
        <Input 
          value={url} 
          style={{ width: '300px' }} 
          ref={urlInputRef} 
        />
        
        {/* 复制链接按钮,带 Tooltip 提示 */}
        <Tooltip title="拷贝链接">
          <Button 
            icon={<CopyOutlined />} 
            onClick={copy} // 点击触发复制逻辑
          />
        </Tooltip>
        
        {/* 二维码弹窗按钮 */}
        <Popover content={QRCodeElem}>
          <Button icon={<QrcodeOutlined />} />
        </Popover>
      </Space>
    )
  }, [id, isPublished]) // 依赖数组:只有当问卷 ID 或发布状态改变时才重新执行

  return (
    <div className={styles['header-wrapper']}>
      <div className={styles.header}>
        {/* 左侧:返回按钮和问卷标题 */}
        <div className={styles.left}>
          <Space>
            <Button 
              type="link" 
              icon={<LeftOutlined />} 
              onClick={() => nav(-1)} // 点击返回上一页
            >
              返回
            </Button>
            <Title level={3} style={{ margin: 0 }}>{title}</Title>
          </Space>
        </div>
        
        {/* 中间:链接与二维码分享区域(仅在发布后显示) */}
        <div className={styles.main}>{LinkAndQRCodeElem}</div>
        
        {/* 右侧:编辑问卷入口 */}
        <div className={styles.right}>
          <Button 
            type="primary" 
            onClick={() => nav(`/question/edit/${id}`)} // 跳转到编辑页面
          >
            编辑问卷
          </Button>
        </div>
      </div>
    </div>
  )
}

export default StatHeader
相关推荐
不一样的少年_2 小时前
【性能监控】别只做工具人了!手把手带你写一个前端性能检测SDK
前端·javascript·监控
AI炼金师2 小时前
Chrome 中的 Claude 入门指南
前端·chrome
德迅云安全—珍珍2 小时前
2025 年 Chrome 浏览器 0Day 漏洞全面分析:八大高危漏洞遭利用
前端·chrome
wanderful_2 小时前
Javascript笔记分享-流程控制(超级超级详细!!!)
javascript·笔记·流程控制·实战案例·新手友好
qq_463408422 小时前
React Native跨平台技术在开源鸿蒙中开发一个具有全文搜索功能的组件,使用useMemo或useCallback来优化性能
react native·react.js·开源
子洋2 小时前
AI Agent 设计模式 - ReAct 模式
前端·人工智能·后端
木童6622 小时前
Docker 容器化 Web 服务全流程实践(含网络深度场景)
前端·网络·docker
长安牧笛2 小时前
制作本地美食测评评分工具,输入美食名称,口味,价格,自动生成评分,帮助消费者选择美食。
javascript
Aftery的博客2 小时前
Uniapp-vue实现语言功能切换(多语言)
javascript·vue.js·uni-app