Skip to content

HTML结构

HTML结构

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>标准HTML结构示例</title>
    
    <!-- 网站图标 -->
    <link rel="icon" href="favicon.ico">

    <!-- 引入外部CSS -->
    <link rel="stylesheet" href="styles.css">
	<!-- 引入外部JS 会引起HTML加载阻塞,但是如果是bootstrap之类的框架,必须放在前边-->
    <script src="script.js"></script>
    <!-- 内联CSS -->
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f9f9f9;
            margin: 0;
            padding: 20px;
        }
        h1 {
            color: #333;
        }
    </style>
</head>
<body>

    <header>
        <h1>这是一个标准HTML页面</h1>
    </header>

    <main>
        <p>这里是页面的主要内容。</p>
        <button id="btn">点我</button>
    </main>

    <footer>
        <p>© 2025 示例公司</p>
    </footer>

    <!-- 引入外部JS -->
    <script src="script.js"></script>

    <!-- 内联JS -->
    <script>
        document.getElementById('btn').addEventListener('click', function() {
            alert('按钮被点击了!');
        });
    </script>
</body>
</html>

如果直接把 <script> 放在 <head> 里,页面在加载 JS 的时候会阻塞 HTML 的解析(浏览器会先执行 JS,才继续渲染页面)。

html
<head>
    <script src="script.js"></script>
</head>

优化方式

  • 使用 defer(推荐): 脚本会在 HTML 解析完毕后才执行,适合大部分情况。

    html
    <head>
        <script src="script.js" defer></script>
    </head>
  • 使用 async: 脚本会异步下载并执行,不保证执行顺序(适合一些独立、不依赖其他代码的脚本,比如广告/统计)。

    html
    <head>
        <script src="script.js" async></script>
    </head>

传统做法 很多时候把 <script> 放在 </body> 前,避免阻塞渲染:

html
<body>
    ...
    <script src="script.js"></script>
</body>

Bootstrap的使用

html
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" />
    <title>水果管理</title>
    <!-- 可选择引入 Bootstrap(可去掉或换成自己样式) -->
    <link th:href="@{https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css}" rel="stylesheet">
    <script th:src="@{https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js}"></script>
</head>
<body class="bg-light">
<div class="container py-4">

    <h1 class="mb-4">水果管理</h1>

    <!-- 新增表单(可以改为 modal,如果喜欢) -->
    <div class="card mb-4">
        <div class="card-header">添加新水果</div>
        <div class="card-body">
            <form th:action="@{/fruit/add}" method="post" class="row g-2">
                <div class="col-md-3">
                    <input class="form-control" name="name" placeholder="名称 (例如:苹果)" required>
                </div>
                <div class="col-md-2">
                    <input class="form-control" name="price" placeholder="价格" type="number" step="0.01" required>
                </div>
                <div class="col-md-2">
                    <input class="form-control" name="count" placeholder="库存" type="number" min="0" required>
                </div>
                <div class="col-md-3">
                    <input class="form-control" name="remark" placeholder="备注(可选)">
                </div>
                <div class="col-md-2">
                    <button type="submit" class="btn btn-primary w-100">添加</button>
                </div>
            </form>
        </div>
    </div>

    <!-- 列表 -->
    <div class="card">
        <div class="card-header d-flex justify-content-between align-items-center">
            <span>水果列表</span>
            <form th:action="@{/fruit/list}" method="get" class="d-flex" style="max-width: 420px;">
                <input name="keyword" th:value="${keyword}" class="form-control form-control-sm me-2" placeholder="按名称搜索">
                <button class="btn btn-sm btn-outline-secondary" type="submit">搜索</button>
            </form>
        </div>

        <div class="table-responsive">
            <table class="table table-hover mb-0">
                <thead class="table-light">
                <tr>
                    <th>ID</th>
                    <th>名称</th>
                    <th>价格</th>
                    <th>库存</th>
                    <th>备注</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                <!-- 遍历 fruits 列表 -->
                <tr th:each="f : ${fruits}">
                    <td th:text="${f.id}">1</td>
                    <td th:text="${f.name}">苹果</td>
                    <td th:text="${#numbers.formatDecimal(f.price, 1, 'COMMA', 2, 'POINT')}">1.00</td>
                    <td th:text="${f.count}">10</td>
                    <td th:text="${f.remark}">新鲜</td>
                    <td>
                        <!-- 编辑:跳转到带 id 的编辑页面,后台构建对应的 fruit 放入 model -->
                        <a th:href="@{/fruit/edit(id=${f.id})}" class="btn btn-sm btn-outline-primary me-1">编辑</a>

                        <!-- 删除:点击确认后访问删除接口 -->
                        <a href="javascript:void(0);"
                           th:onclick="'if(confirm(\'确认删除:【' + ${f.name} + '】?\')) location.href=\'' + @{/fruit/delete(id=${f.id})} + '\';'"
                           class="btn btn-sm btn-outline-danger">删除</a>
                    </td>
                </tr>

                <!-- 如果列表为空 -->
                <tr th:if="${fruits == null or #lists.isEmpty(fruits)}">
                    <td colspan="6" class="text-center text-muted">暂无数据</td>
                </tr>
                </tbody>
            </table>
        </div>
    </div>

    <!-- 编辑表单(当后台返回一个 'fruit' 对象时显示) -->
    <div th:if="${fruit != null}" class="card mt-4">
        <div class="card-header">编辑水果(ID: <span th:text="${fruit.id}">0</span>)</div>
        <div class="card-body">
            <form th:action="@{/fruit/update}" method="post" class="row g-2">
                <!-- id 隐藏 -->
                <input type="hidden" name="id" th:value="${fruit.id}">
                <div class="col-md-3">
                    <input class="form-control" name="name" th:value="${fruit.name}" required>
                </div>
                <div class="col-md-2">
                    <input class="form-control" name="price" type="number" step="0.01" th:value="${fruit.price}" required>
                </div>
                <div class="col-md-2">
                    <input class="form-control" name="count" type="number" min="0" th:value="${fruit.count}" required>
                </div>
                <div class="col-md-3">
                    <input class="form-control" name="remark" th:value="${fruit.remark}">
                </div>
                <div class="col-md-2 d-flex gap-1">
                    <button class="btn btn-success w-100" type="submit">保存修改</button>
                    <a th:href="@{/fruit/list}" class="btn btn-outline-secondary w-100">取消</a>
                </div>
            </form>
        </div>
    </div>

</div>

<!-- 简单脚本(Bootstrap 已包含) -->
<script>
    // 如果你希望使用 POST 删除(更安全),可以通过 fetch 发起请求并刷新页面
    function doDeletePost(url) {
        if (!confirm('确认删除?')) return;
        fetch(url, {method: 'POST'}).then(r => location.reload());
    }
</script>
</body>
</html>

form表单按钮类型

html
<form action="addFruit" method="post">
    <!-- 水果名称 -->
    <div class="mb-3">
      <label class="form-label">水果名称:</label>
      <input type="text" class="form-control" name="fname">
    </div>
    <!-- 价格 -->
    <div class="mb-3">
      <label class="form-label">价格:</label>
      <input type="number" class="form-control" name="price" >
    </div>
    <!-- 库存数量 -->
    <div class="mb-3">
      <label class="form-label">库存数量:</label>
      <input type="number" class="form-control" name="count">
    </div>
    <!-- 备注 -->
    <div class="mb-3">
      <label class="form-label">备注:</label>
      <input type="text" class="form-control" name="remark">
    </div>
    <!-- 操作按钮 -->
    <div class="d-flex justify-content-between">
      <button type="submit" class="btn btn-success">保存</button>
      <button onclick="handleJumpList()" type="button">取消</button>
    </div>
</form>
<script>
  const handleJumpList = () => {
    // 方式2:如果你使用的是后端路由,比如 Spring Boot 的 /fruit/list
    window.location.href = '/fruit/fruitList';
  }
</script>
html
<form th:action="@{/updateFruit}" method="post" th:object="${fruit}">
  <!-- 隐藏id -->
  <input type="hidden" name="id" th:value="*{id}">

  <label>水果名称:</label>
  <input type="text" name="fname" th:value="*{fname}" required>
  <br>

  <label>价格:</label>
  <input type="number" name="price" th:value="*{price}" step="0.1" required>
  <br>

  <label>库存数量:</label>
  <input type="number" name="count" th:value="*{count}" required>
  <br>

  <label>备注:</label>
  <input type="text" name="remark" th:value="*{remark}">
  <br>

  <button type="submit">保存修改</button>
  <!--取消默认提交功能-->
  <button onclick="handleJumpList()" type="button">取消</button>
</form>
<script>
    function handleJumpList(){
      // 方式1:直接跳转到某个页面
      window.location.href = '/fruit/fruitList.html'; // 改成你的列表页路径

      // 方式2:如果你使用的是后端路由,比如 Spring Boot 的 /fruit/list
      // window.location.href = '/fruit/list';
    }
</script>

CSS闪烁样式

方式1:

html
<svg t="1758857706414" class="icon-blick path" viewBox="0 0 1092 1024" version="1.1">
    <path ></path>
    <title>浪涌开关动作</title>
    <path></path>
</svg>
css
.icon-blick path {
  animation: blink 1s infinite;
}

// 定义闪烁动画
@keyframes blink {
  0% {
    opacity: 1;
    fill: #efb336; /* 初始颜色 */
  }
  50% {
    opacity: 0.2;
    fill: #ffd36a; /* 变亮一点 */
  }
  100% {
    opacity: 1;
    fill: #efb336;
  }
}

方式2:

css
// 绿灯
.green-light-on {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background-color: #00ff00;
    box-shadow: 0 0 15px #00ff00;
}
// 灰灯
.gray-light-on {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background-color: #afaeae;
}
@keyframes blinkYellow {

    0%,
    100% {
        background-color: #ffcc00;
        box-shadow: 0 0 10px #ffcc00;
    }

    50% {
        background-color: #996600;
        box-shadow: none;
    }
}
// 黄灯闪烁
.yellow-light {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background-color: #ffcc00;
    box-shadow: 0 0 10px #ffcc00;
    animation: blinkYellow 1s infinite;
}

动态Class切换

html
你这个需求在前端里就是一个动态 class 切换。常见写法:
<svg :class="device.online ? 'icon-blick path' : 'icon-static path'">
  <!-- ... -->
</svg>

// 或
<svg :class="['path', device.online ? 'icon-blick' : 'icon-static']">
  <!-- ... -->
</svg>