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
相关产品推荐
相关产品推荐

