如何在表单中根据用户输入的网站链接自动填充网站标题字段
实现方案
步骤1:修改原有表单,给输入框加专属ID
方便后续JS获取元素,修改后表单代码如下:
<form method="POST" action="{{ route('storeCompany') }}"> @csrf <label>{{ __('Website URL') }}</label> <!-- 给URL输入框加id --> <input type="text" id="website_url" name="url" value="{{ old('url') }}" placeholder="{{ __('http://example.com') }}" class="form-control" required="required"> <label>{{ __('Website Title') }}</label> <!-- 给标题输入框加id --> <input type="text" id="website_name" name="name" value="{{ old('name') }}" placeholder="{{ __('Example Ltd') }}" class="form-control" required="required"> <input type="submit" name="sbNewReviewItem" class="btn btn-block btn-primary" value="{{ __('Submit New Company') }}"> </form>
步骤2:新增后端接口用于获取网站标题
由于浏览器跨域限制,无法直接在前端请求第三方站点内容,需要后端做代理请求解析标题:
2.1 添加路由
在routes/web.php中新增路由:
Route::get('/api/get-website-title', [\App\Http\Controllers\WebsiteController::class, 'getTitle'])->name('getWebsiteTitle');
2.2 编写控制器逻辑
新建app/Http/Controllers/WebsiteController.php,代码如下:
<?php namespace App\Http\Controllers; use GuzzleHttp\Client; use Illuminate\Http\Request; use DOMDocument; class WebsiteController extends Controller { public function getTitle(Request $request) { $request->validate([ 'url' => 'required|url|starts_with:http,https' ]); try { // 发起请求,设置5秒超时避免阻塞 $client = new Client(['timeout' => 5]); $response = $client->get($request->input('url')); $html = (string)$response->getBody(); // 解析HTML提取title $dom = new DOMDocument(); // 屏蔽HTML不规范的警告 libxml_use_internal_errors(true); $dom->loadHTML($html); libxml_clear_errors(); $titleNodes = $dom->getElementsByTagName('title'); if ($titleNodes->length > 0) { $title = trim($titleNodes->item(0)->nodeValue); return response()->json(['title' => $title]); } return response()->json(['title' => ''], 404); } catch (\Exception $e) { return response()->json(['title' => ''], 500); } } }
步骤3:添加前端JS实现自动填充
在表单所在页面底部加入以下JS代码,实现监听URL输入、请求接口、自动填充标题的逻辑:
<script> // 防抖函数,避免输入过程中频繁发请求 function debounce(func, wait = 300) { let timeout; return function(...args) { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, args), wait); } } const urlInput = document.getElementById('website_url'); const nameInput = document.getElementById('website_name'); // 标记用户是否手动修改过标题,避免自动填充覆盖用户手动输入的内容 let userModifiedName = false; // 监听标题输入框的修改事件 nameInput.addEventListener('input', () => { userModifiedName = true; }); // 监听URL输入框的输入事件,加防抖 urlInput.addEventListener('input', debounce(async () => { const url = urlInput.value.trim(); // 非合法URL不发起请求 if (!url || !url.startsWith('http')) { return; } // 如果用户没手动改过标题,才发起自动填充请求 if (!userModifiedName) { try { const res = await fetch(`/api/get-website-title?url=${encodeURIComponent(url)}`); if (res.ok) { const data = await res.json(); if (data.title) { nameInput.value = data.title; } } } catch (err) { // 请求失败不做处理,保留原有占位符即可 } } })); // 监听URL输入框失焦事件,重置修改标记(如果用户重新修改URL,允许再次自动填充) urlInput.addEventListener('focus', () => { userModifiedName = false; }); </script>
注意事项
- 后端请求设置了5秒超时,避免遇到响应慢的站点导致服务阻塞
- 仅当用户没有手动修改过标题时才会自动填充,不会覆盖用户手动输入的内容
- 用户重新修改URL时会自动重置标记,允许再次触发自动填充
- 可以根据需要调整防抖的等待时长,避免输入过程中发起过多无效请求
内容的提问来源于stack exchange,提问作者user13691227
相关产品推荐
相关产品推荐

