URL 验证

在输入框中判断用户输入是否为有效网址

问题

在输入框中如何判断输入的是一个正确的网址?

解答

方法一:使用 URL 构造函数(推荐)

function isValidURL(string) {
  try {
    // URL 构造函数会对无效 URL 抛出错误
    new URL(string);
    return true;
  } catch (err) {
    return false;
  }
}

// 测试
console.log(isValidURL('https://example.com'));      // true
console.log(isValidURL('http://localhost:3000'));    // true
console.log(isValidURL('ftp://files.example.com'));  // true
console.log(isValidURL('not a url'));                // false
console.log(isValidURL('example.com'));              // false(缺少协议)

方法二:限制 HTTP/HTTPS 协议

function isValidHttpURL(string) {
  try {
    const url = new URL(string);
    // 只允许 http 和 https 协议
    return url.protocol === 'http:' || url.protocol === 'https:';
  } catch (err) {
    return false;
  }
}

// 测试
console.log(isValidHttpURL('https://example.com'));     // true
console.log(isValidHttpURL('ftp://files.example.com')); // false
console.log(isValidHttpURL('javascript:alert(1)'));     // false

方法三:使用正则表达式

function isValidURLByRegex(string) {
  const pattern = new RegExp(
    '^(https?:\\/\\/)?' +                    // 协议(可选)
    '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+' + // 域名
    '[a-z]{2,}|' +                           // 顶级域名
    '((\\d{1,3}\\.){3}\\d{1,3}))' +          // 或 IP 地址
    '(\\:\\d+)?' +                           // 端口(可选)
    '(\\/[-a-z\\d%_.~+]*)*' +                // 路径(可选)
    '(\\?[;&a-z\\d%_.~+=-]*)?' +             // 查询参数(可选)
    '(\\#[-a-z\\d_]*)?$',                    // 锚点(可选)
    'i'
  );
  return pattern.test(string);
}

// 测试
console.log(isValidURLByRegex('https://example.com/path?q=1')); // true
console.log(isValidURLByRegex('example.com'));                   // true
console.log(isValidURLByRegex('not a url'));                     // false

方法四:结合 input 元素原生验证

<input type="url" id="urlInput" placeholder="请输入网址">
<button onclick="validate()">验证</button>

<script>
function validate() {
  const input = document.getElementById('urlInput');
  
  if (input.validity.valid) {
    console.log('有效的 URL');
  } else {
    console.log('无效的 URL');
  }
}

// 或者用 JavaScript 创建临时 input 验证
function isValidURLByInput(string) {
  const input = document.createElement('input');
  input.type = 'url';
  input.value = string;
  return input.checkValidity();
}
</script>

实际应用示例

<!DOCTYPE html>
<html>
<body>
  <input type="text" id="urlInput" placeholder="输入网址">
  <span id="status"></span>

  <script>
    const input = document.getElementById('urlInput');
    const status = document.getElementById('status');

    function isValidHttpURL(string) {
      try {
        const url = new URL(string);
        return url.protocol === 'http:' || url.protocol === 'https:';
      } catch {
        return false;
      }
    }

    // 实时验证
    input.addEventListener('input', (e) => {
      const value = e.target.value;
      
      if (!value) {
        status.textContent = '';
        return;
      }

      if (isValidHttpURL(value)) {
        status.textContent = '✓ 有效';
        status.style.color = 'green';
      } else {
        status.textContent = '✗ 无效';
        status.style.color = 'red';
      }
    });
  </script>
</body>
</html>

关键点

  • 优先使用 URL 构造函数:原生 API,无需维护正则,浏览器兼容性好
  • 注意协议限制:URL 构造函数接受任意协议,实际场景通常只需 http/https
  • 正则表达式灵活但复杂:可自定义规则,但难以覆盖所有边界情况
  • input[type=“url”] 要求协议:原生验证必须包含协议前缀
  • 防范安全风险:过滤 javascript: 等危险协议,避免 XSS 攻击