3. 目标平台与源平台分析

说实话,很多做了两三年前端的同学,写 HTML 还是靠肌肉记忆。div 一把梭,class 满天飞,表单 validation 全靠后端骂人。但你要做界面移植,HTML 的功底直接决定了你移植的质量和速度。

我当年从 jQuery 时代转到 React 时,第一个项目就是移植一个老旧的 ERP 系统。那时候我才发现,真正懂 HTML 的人,移植出来的代码干净得像教科书;不懂的人,移植完就是一堆 div 套 div 的意大利面。嗯,今天我们就来把这碗面煮明白。

3.1 文档结构:骨架得正

一个标准的 HTML 文档,说白了就四个部分:DOCTYPE、html、head、body。少一个,浏览器就得猜你的意图。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>页面标题</title>
</head>
<body>
    <!-- 可见内容写这里 -->
</body>
</html>
我曾经踩过的坑: 少写了 <meta charset="UTF-8">,结果页面在 IE 下中文全变乱码。排查了半小时,最后发现是字符集没声明。这种低级错误,一次就够了。

viewport 这个 meta 在移动端移植时尤其重要。没有它,你的页面在手机上会缩成芝麻大。我建议你养成习惯,新建 HTML 文件就把这段骨架敲进去,别偷懒。

3.2 常用标签:别只会用 div

很多同学写页面,从头到尾就是 div。div 套 div,class 名起得比论文标题还长。其实 HTML5 给了你很多现成的语义标签,用对了,代码可读性直接翻倍。

标签 用途 我常用的场景
<header> 页眉/头部 导航栏、Logo、搜索框
<nav> 导航区域 主导航、面包屑
<main> 页面主体 每个页面只用一次
<article> 独立内容块 博客文章、新闻条目
<section> 通用分区 按主题划分内容
<aside> 侧边栏/补充 广告、相关链接
<footer> 页脚 版权、联系方式

你想想看,如果整个页面都是 div,屏幕阅读器怎么知道哪里是导航、哪里是正文?语义化标签不只是给开发者看的,更是给机器看的。

小技巧: 移植老系统时,我习惯先用语义标签搭好骨架,再往里填内容。这样结构清晰,后面改样式也方便。

3.3 语义化 HTML:不只是为了好看

语义化 HTML 说白了就是「见名知意」。看到 <nav> 就知道是导航,看到 <button> 就知道能点。这听起来简单,但实际项目中能做到的人不多。

我记得有一次帮一个团队做无障碍改造,他们的页面全是 <div onclick="..."> 模拟按钮。结果键盘用户根本没法操作,Tab 键按烂了都选不到。后来全部改成 <button>,问题迎刃而解。

语义化的好处有三个:

  • 可访问性: 屏幕阅读器能正确解读页面结构
  • SEO: 搜索引擎更青睐语义清晰的页面
  • 可维护性: 同事接手你的代码,不用猜这个 div 是干嘛的

举个实际例子。下面这段代码,哪个更好?

<!-- 反面教材 -->
<div class="nav-item" onclick="goHome()">首页</div>

<!-- 正确写法 -->
<a href="/">首页</a>

第二个写法,浏览器原生支持右键新标签打开、支持 SEO 爬虫抓取、支持键盘操作。第一个写法,除了看起来像导航,啥也不是。

核心原则: 能用原生 HTML 元素实现的功能,就别用 div+JS 模拟。这是界面移植中最容易忽略、也最容易出问题的地方。

3.4 表单与输入控件:用户交互的起点

表单是界面移植的重灾区。为什么?因为每个系统的表单逻辑都不一样,而且往往伴随着复杂的验证和联动。

先看一个标准的表单结构:

<form action="/submit" method="POST">
    <label for="username">用户名:</label>
    <input type="text" id="username" name="username" required>

    <label for="email">邮箱:</label>
    <input type="email" id="email" name="email">

    <label for="password">密码:</label>
    <input type="password" id="password" name="password" minlength="6">

    <label for="gender">性别:</label>
    <select id="gender" name="gender">
        <option value="male">男</option>
        <option value="female">女</option>
    </select>

    <label>
        <input type="checkbox" name="agree"> 同意用户协议
    </label>

    <button type="submit">注册</button>
</form>

这里面有几个关键点,我一个个说。

3.4.1 label 与 input 的关联

很多新手写表单,label 和 input 各写各的,完全没关系。正确的做法是用 for 属性指向 input 的 id,或者直接把 input 嵌套在 label 里面。

为什么要这么做?因为点击 label 时,对应的 input 会自动获得焦点。这对移动端用户特别友好——手指不用精确点到那个小框框上。

3.4.2 type 属性的妙用

HTML5 给 input 加了很多新 type,我建议你多用:

type 作用 移动端效果
email 邮箱格式验证 弹出 @ 键盘
tel 电话号码 弹出数字键盘
url URL 格式验证 弹出 .com 键盘
number 数字输入 弹出数字键盘
date 日期选择器 弹出原生日期控件
range 滑块选择 触摸滑动
我的习惯: 移植表单时,先把所有 input 的 type 改成最合适的值。比如手机号用 tel,邮箱用 email。这样不用写一行 JS,用户体验就提升一大截。

3.4.3 表单验证:前端后端都要做

很多人觉得前端验证可有可无,反正后端会拦。但你想过没有,用户填了十分钟表单,点提交后页面刷新,告诉你「邮箱格式不对」——这体验得多糟糕。

HTML5 内置的验证属性已经很强大了:

  • required:必填项
  • minlength / maxlength:字符长度限制
  • min / max:数值范围
  • pattern:正则表达式验证

举个例子:

<input type="text" pattern="[0-9]{11}" title="请输入11位手机号">

这样用户输入非数字或长度不对时,浏览器会弹出提示。当然,前端验证只是辅助,后端验证才是底线。这个原则在界面移植中同样适用。

3.5 本章知识体系

下面这张图,是我做界面移植时脑子里始终绷着的一根弦。HTML 基础不牢,后面所有工作都是空中楼阁。

HTML 基础回顾 · 知识体系 HTML 基础 文档结构 常用标签 语义化 HTML 表单与控件 DOCTYPE meta / title header / nav / main article / section 可访问性 SEO 优化 可维护性 label / input 验证属性 💡 核心思路: 界面移植不是复制粘贴,而是用正确的 HTML 结构重新组织内容。

这张图把本章的知识点串起来了。你仔细看,四个分支其实是有顺序的:先搭文档结构,再选常用标签,然后考虑语义化,最后处理表单。每一步都踩实了,移植出来的页面才经得起推敲。

总结一句话: HTML 不是「写出来能跑就行」的东西。它是你整个项目的根基。根基歪了,后面 CSS 和 JS 再牛也救不回来。