You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React/ReactTS中如何初始化输入文本内的链接以实现预览?

React TS 实现文本输入框的链接提取与预览方案

一、核心类型定义

先定义TS类型规范数据结构,保证类型安全:

// 基于link-preview-js返回结果的类型定义
type LinkPreviewData = {
  url: string;
  title?: string;
  description?: string;
  image?: string;
  siteName?: string;
};

// 链接处理工具的返回类型
type LinkProcessResult = {
  isValid: boolean;
  previewData?: LinkPreviewData;
  error?: string;
};

二、专用链接处理工具函数

封装类似FileReader的专用处理方法,负责链接验证、提取与预览数据获取:

import { getLinkPreview } from 'link-preview-js';

// 验证URL合法性(利用URL构造函数的异常捕获)
const validateUrl = (url: string): boolean => {
  try {
    // 补全协议(适配无协议的域名输入,比如www.example.com)
    const formattedUrl = url.startsWith('http') ? url : `https://${url}`;
    new URL(formattedUrl);
    return true;
  } catch (err) {
    return false;
  }
};

// 从文本中提取所有合法链接
const extractValidLinks = (text: string): string[] => {
  // 匹配URL的正则(支持带/不带协议的链接)
  const urlRegex = /(https?:\/\/[^\s]+|www\.[^\s]+)/g;
  const matches = text.match(urlRegex) || [];
  return matches.filter(link => validateUrl(link));
};

// 专用链接预览处理类,类似FileReader的读取逻辑
class LinkPreviewHandler {
  static async processLink(url: string): Promise<LinkProcessResult> {
    try {
      const formattedUrl = url.startsWith('http') ? url : `https://${url}`;
      if (!validateUrl(formattedUrl)) {
        return { isValid: false, error: '无效的链接格式' };
      }
      const previewData = await getLinkPreview(formattedUrl);
      return { isValid: true, previewData };
    } catch (err) {
      return { isValid: false, error: '获取链接预览失败' };
    }
  }
}

三、React TS 组件实现

整合输入框、链接提取与预览展示:

import { useState, useEffect } from 'react';

const LinkPreviewInput = () => {
  const [inputText, setInputText] = useState<string>('');
  const [currentPreview, setCurrentPreview] = useState<LinkPreviewData | null>(null);

  // 监听输入文本变化,提取并处理链接
  useEffect(() => {
    const fetchPreview = async () => {
      const validLinks = extractValidLinks(inputText);
      if (validLinks.length > 0) {
        // 取第一个有效链接生成预览(可按需扩展为多链接预览)
        const result = await LinkPreviewHandler.processLink(validLinks[0]);
        if (result.isValid && result.previewData) {
          setCurrentPreview(result.previewData);
        } else {
          setCurrentPreview(null);
        }
      } else {
        setCurrentPreview(null);
      }
    };

    // 防抖处理,避免频繁请求
    const timer = setTimeout(fetchPreview, 500);
    return () => clearTimeout(timer);
  }, [inputText]);

  return (
    <div style={{ maxWidth: '600px', margin: '20px auto' }}>
      <input
        type="text"
        value={inputText}
        onChange={(e) => setInputText(e.target.value)}
        placeholder="输入文本或粘贴链接..."
        style={{ width: '100%', padding: '10px', fontSize: '16px' }}
      />

      {/* 链接预览区域 */}
      {currentPreview && (
        <div style={{ marginTop: '20px', border: '1px solid #eee', borderRadius: '8px', padding: '15px' }}>
          {currentPreview.image && (
            <img 
              src={currentPreview.image} 
              alt={currentPreview.title || '预览图'} 
              style={{ width: '100%', height: '200px', objectFit: 'cover', borderRadius: '4px', marginBottom: '10px' }}
            />
          )}
          <h3 style={{ margin: '0 0 8px 0' }}>{currentPreview.title || currentPreview.url}</h3>
          <p style={{ color: '#666', margin: '0 0 8px 0' }}>{currentPreview.description}</p>
          <span style={{ color: '#999', fontSize: '14px' }}>{currentPreview.siteName}</span>
        </div>
      )}
    </div>
  );
};

export default LinkPreviewInput;

四、关键说明

  • URL补全逻辑:针对用户输入的无协议链接(如www.example.com),自动补全https://后再验证与请求预览
  • 防抖处理:避免用户输入过程中频繁触发预览请求,优化性能
  • 错误处理:通过URL构造函数的异常捕获判断链接合法性,同时处理link-preview-js的请求失败场景
  • 扩展性:可修改extractValidLinks逻辑,支持提取多个链接并生成多预览卡片

内容的提问来源于stack exchange,提问作者AVT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 21:50:37