最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用HTML+JavaScript實現(xiàn)可編輯表格的方法

 更新時間:2026年01月14日 09:29:56   作者:bjzhang75  
可編輯表格是數(shù)據(jù)管理系統(tǒng)中的重要組件,它將數(shù)據(jù)展示與編輯功能融為一體,使用戶能夠直接在表格界面中修改數(shù)據(jù)內容,本文將介紹如何使用 HTML、CSS 和 JavaScript 實現(xiàn)一個可編輯表格,需要的朋友可以參考下

一、可編輯表格

可編輯表格是數(shù)據(jù)管理系統(tǒng)中的重要組件,它將數(shù)據(jù)展示與編輯功能融為一體,使用戶能夠直接在表格界面中修改數(shù)據(jù)內容。通過純前端技術實現(xiàn)的可編輯表格,無需復雜的后端支持即可提供流暢的數(shù)據(jù)編輯體驗,特別適用于數(shù)據(jù)錄入、修改等場景。本文將介紹如何使用 HTML、CSS 和 JavaScript 實現(xiàn)一個可編輯表格。

二、效果演示

本系統(tǒng)采用簡潔的三段式布局:頂部為表格標題區(qū)域,中間為主要的表格編輯區(qū)域,底部為狀態(tài)欄區(qū)域。用戶可以直接在表格單元格中編輯數(shù)據(jù),通過鍵盤快捷鍵進行導航,實時查看數(shù)據(jù)變化狀態(tài)。

三、系統(tǒng)分析

1、頁面結構

頁面包含三個主要區(qū)域:表格頭部、表格編輯區(qū)域和狀態(tài)欄。

1.1、表格編輯區(qū)域

表格編輯區(qū)域是整個應用的核心,包含一個可滾動的表格,表格中的每個單元格都支持直接編輯。

<div class="table-wrapper" id="tableWrapper">
  <table class="data-table" id="dataTable">
    <thead>
    <tr>
      <th data-column="id" style="width: 80px;">ID</th>
      <th data-column="name" style="width: 100px;">姓名</th>
      <th data-column="email" style="width: 180px;">郵箱</th>
      <th data-column="phone" style="width: 120px;">電話</th>
      <th data-column="department" style="width: 100px;">部門</th>
      <th data-column="salary" style="width: 100px;">薪資</th>
      <th data-column="status" style="width: 80px;">狀態(tài)</th>
    </tr>
    </thead>
    <tbody id="tableBody"></tbody>
  </table>
</div>

1.2、狀態(tài)欄區(qū)域

狀態(tài)欄區(qū)域顯示表格統(tǒng)計信息、編輯模式提示和鍵盤快捷鍵說明。

<div class="status-bar">
  <div class="nav-info">
    <span id="recordInfo">共 0 條記錄</span>
    <span>編輯模式</span>
  </div>
  <div class="status-message" id="statusMessage"></div>
  <div class="shortcuts">
    <span class="shortcut">Tab</span> 下一個
    <span class="shortcut">↑↓</span> 上下導航
  </div>
</div>

2、核心功能實現(xiàn)

2.1定義全局變量

originalData 用于保存表格的初始數(shù)據(jù),currentData 用于存儲當前表格的實時數(shù)據(jù),selectedRows 用于跟蹤當前選中的行。

let originalData = [
  {id: 1, name: '張三', email: 'zhangsan@example.com', phone: '13800138000', department: '技術部', salary: 15000, status: '在職'},
  {id: 2, name: '李四', email: 'lisi@example.com', phone: '13900139000', department: '銷售部', salary: 12000, status: '在職'},
  // ...
];

let currentData = [...originalData];
let selectedRows = new Set();

2.2渲染表格

renderTable() 函數(shù)負責根據(jù) currentData 中的數(shù)據(jù)動態(tài)生成表格界面,每個單元格都包含一個輸入框或選擇框,支持直接編輯。

function renderTable() {
  const tbody = document.getElementById('tableBody');
  tbody.innerHTML = '';

  currentData.forEach((row, rowIndex) => {
    const tr = document.createElement('tr');
    tr.dataset.rowIndex = rowIndex;
    if (selectedRows.has(rowIndex)) tr.classList.add('selected');

    const columns = [
      { key: 'id', cls: 'id-input', input: 'text' },
      { key: 'name', cls: '', input: 'text' },
      { key: 'email', cls: '', input: 'text' },
      { key: 'phone', cls: '', input: 'text' },
      { key: 'department', cls: '', input: 'text' },
      { key: 'salary', cls: 'number-input', input: 'text' }
    ];

    columns.forEach(col => {
      const td = document.createElement('td');
      td.innerHTML = `<input type="${col.input}" class="always-edit ${col.cls}" value="${row[col.key]}" onchange="updateCell(${rowIndex}, '${col.key}', this.value)" onfocus="selectCell(${rowIndex}, '${col.key}', this.value)">`;
      tr.appendChild(td);
    });
    // 狀態(tài)列
    const statusTd = document.createElement('td');
    const statusOptions = ['在職', '離職'];
    statusTd.innerHTML = `<select class="status-select" onchange="updateCell(${rowIndex}, 'status', this.value)" onfocus="selectCell(${rowIndex}, 'status', this.value)">
                ${statusOptions.map(option => `<option value="${option}" ${row.status === option ? 'selected' : ''}>${option}</option>`).join('')}
              </select>`;
    tr.appendChild(statusTd);

    tbody.appendChild(tr);
  });
}

2.3更新單元格數(shù)據(jù)

updateCell() 函數(shù)處理單元格數(shù)據(jù)更新,包括數(shù)據(jù)驗證和狀態(tài)提示。

function updateCell(rowIndex, column, value) {
  const originalValue = currentData[rowIndex][column];
  if (column === 'id' || column === 'salary') value = parseInt(value) || 0;

  if (value !== originalValue) {
    if (column === 'id') {
      const newId = parseInt(value);
      const existingIds = currentData.map(row => row.id).filter((id, index) => index !== rowIndex);
      if (existingIds.includes(newId)) {
        showStatusMessage('錯誤:ID已存在!', 'error');
        renderTable();
        return;
      }
    }
    currentData[rowIndex][column] = value;
    const rowId = currentData[rowIndex].id;
    showStatusMessage(`ID ${rowId}: 已更新 ${column} = ${value}`, 'success');
  }
}

2.4鍵盤導航功能

系統(tǒng)實現(xiàn)了完整的鍵盤導航功能,支持 Tab 鍵、方向鍵和 Ctrl+S 快捷鍵。

document.addEventListener('keydown', function(event) {
  if ((event.ctrlKey || event.metaKey) && event.key === 's') {
    // Ctrl+S 保存
    event.preventDefault();
    if (window.currentEditRow !== undefined &&
      window.currentEditColumn !== undefined &&
      window.currentEditValue !== undefined) {
      const activeElement = document.activeElement;
      const newValue = activeElement.value;
      updateCell(window.currentEditRow, window.currentEditColumn, newValue);
    }
  } else if (['ArrowUp', 'ArrowDown', 'Tab'].includes(event.key)) {
    // 鍵盤導航
    if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'SELECT') {
      event.preventDefault();
      if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
        handleArrowNavigation(event.key);
      } else if (event.key === 'Tab') {
        handleTabNavigation(event.shiftKey);
      }
    }
  }
});

四、擴展建議

  • 數(shù)據(jù)持久化:增加保存和加載功能,將表格數(shù)據(jù)保存到本地存儲或服務器
  • 數(shù)據(jù)導入導出:支持從CSV、Excel文件導入數(shù)據(jù),或將表格數(shù)據(jù)導出為多種格式
  • 批量操作:支持多選行進行批量編輯、刪除等操作
  • 排序和篩選:增加列排序和數(shù)據(jù)篩選功能
  • 撤銷重做:實現(xiàn)編輯歷史記錄,支持撤銷和重做操作

五、完整代碼

git地址:https://gitee.com/ironpro/hjdemo/blob/master/table-edit/index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>可編輯表格</title>
  <style>
      * {
          margin: 0;
          padding: 0;
          box-sizing: border-box;
      }
      body {
          background-color: #f5f7fa;
          min-height: 100vh;
          padding: 20px;
          overflow: hidden;
      }
      .container {
          max-width: 1400px;
          margin: 0 auto;
          background: white;
          border-radius: 15px;
          box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
          height: calc(100vh - 40px);
          display: flex;
          flex-direction: column;
      }
      .header {
          background: #ffffff;
          color: #333;
          padding: 15px 20px;
          display: flex;
          justify-content: space-between;
          align-items: center;
          flex-shrink: 0;
          border-bottom: 1px solid #e1e5eb;
      }
      .header h1 {
          font-size: 18px;
          font-weight: 500;
      }
      .table-wrapper {
          flex: 1;
          overflow: auto;
          position: relative;
          padding-bottom: 5px;
      }
      .table-wrapper::-webkit-scrollbar {
          width: 6px;
          height: 6px;
      }
      .table-wrapper::-webkit-scrollbar-track {
          background: #f1f5f9;
      }
      .table-wrapper::-webkit-scrollbar-thumb {
          background: #cbd5e1;
          border-radius: 3px;
      }
      .table-wrapper::-webkit-scrollbar-thumb:hover {
          background: #94a3b8;
      }
      .data-table {
          width: 100%;
          border-collapse: collapse;
          font-size: 13px;
          table-layout: fixed;
      }
      .data-table thead {
          position: sticky;
          top: 0;
          z-index: 10;
      }
      .data-table thead::after {
          content: "";
          position: absolute;
          left: 0;
          right: 0;
          bottom: 0;
          height: 1px;
          background: #d1d5db;
          z-index: 11;
      }
      .data-table th {
          background: #f8fafc;
          color: #374151;
          padding: 12px 10px;
          text-align: left;
          font-weight: 500;
          cursor: pointer;
          user-select: none;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
          border-right: 1px solid #d1d5db;
      }
      .data-table th:hover {
          background: #f1f5f9;
      }
      .data-table td {
          padding: 0;
          border: 1px solid #d1d5db;
          border-top: none;
          border-left: none;
          position: relative;
          height: 40px;
          overflow: hidden;
      }
      .data-table tbody tr:last-child td {
          border-bottom: 1px solid #d1d5db;
      }
      .data-table th:last-child, .data-table td:last-child {
          border-right: none;
      }
      .data-table tr:nth-child(even) {
          background: #f9fafb;
      }
      .data-table tr:hover {
          background: #f1f5f9 !important;
      }
      .data-table tr.selected {
          background: #dbeafe !important;
      }
      .always-edit {
          width: 100%;
          height: 100%;
          border: none;
          padding: 10px;
          font-size: 13px;
          font-family: inherit;
          background: transparent;
          outline: none;
          cursor: text;
      }
      .always-edit:focus {
          background: white;
          box-shadow: inset 0 0 0 1px #3b82f6;
          z-index: 5;
          position: relative;
      }
      .id-input {
          text-align: center;
          font-weight: 500;
          color: #4b5563;
      }
      .status-active {
          color: #10b981;
          font-weight: 500;
      }
      .status-inactive {
          color: #ef4444;
          font-weight: 500;
      }
      .status-select {
          width: 100%;
          height: 100%;
          border: none;
          padding: 10px;
          font-size: 13px;
          font-family: inherit;
          background: transparent;
          outline: none;
          cursor: pointer;
      }
      .status-select:focus {
          background: white;
          box-shadow: inset 0 0 0 1px #3b82f6;
      }
      .number-input {
          text-align: right;
      }
      .status-bar {
          background: #f8fafc;
          padding: 10px 20px;
          border-top: 1px solid #e1e5eb;
          display: flex;
          justify-content: space-between;
          align-items: center;
          font-size: 12px;
          color: #64748b;
          flex-shrink: 0;
      }
      .nav-info {
          display: flex;
          gap: 15px;
          align-items: center;
      }
      .shortcuts {
          display: flex;
          gap: 10px;
      }
      .shortcut {
          background: #e2e8f0;
          padding: 3px 7px;
          border-radius: 3px;
          font-size: 11px;
          font-family: monospace;
      }
      .status-message {
          flex: 1;
          margin: 0 20px;
          color: #3b82f6;
          font-weight: 500;
          transition: opacity 0.3s;
      }
      .status-message.success {
          color: #10b981;
      }
      .status-message.error {
          color: #ef4444;
      }
  </style>
</head>
<body>
<div class="container">
  <div class="header">
    <h1>可編輯表格</h1>
  </div>
  <div class="table-wrapper" id="tableWrapper">
    <table class="data-table" id="dataTable">
      <thead>
      <tr>
        <th data-column="id" style="width: 80px;">ID</th>
        <th data-column="name" style="width: 100px;">姓名</th>
        <th data-column="email" style="width: 180px;">郵箱</th>
        <th data-column="phone" style="width: 120px;">電話</th>
        <th data-column="department" style="width: 100px;">部門</th>
        <th data-column="salary" style="width: 100px;">薪資</th>
        <th data-column="status" style="width: 80px;">狀態(tài)</th>
      </tr>
      </thead>
      <tbody id="tableBody"></tbody>
    </table>
  </div>

  <div class="status-bar">
    <div class="nav-info">
      <span id="recordInfo">共 0 條記錄</span>
      <span>編輯模式</span>
    </div>
    <div class="status-message" id="statusMessage"></div>
    <div class="shortcuts">
      <span class="shortcut">Tab</span> 下一個
      <span class="shortcut">↑↓</span> 上下導航
    </div>
  </div>
</div>

<script>
  let originalData = [
    {id: 1, name: '張三', email: 'zhangsan@example.com', phone: '13800138000', department: '技術部', salary: 15000, status: '在職'},
    {id: 2, name: '李四', email: 'lisi@example.com', phone: '13900139000', department: '銷售部', salary: 12000, status: '在職'},
    // ...
  ];

  let currentData = [...originalData];
  let selectedRows = new Set();

  function renderTable() {
    const tbody = document.getElementById('tableBody');
    tbody.innerHTML = '';

    currentData.forEach((row, rowIndex) => {
      const tr = document.createElement('tr');
      tr.dataset.rowIndex = rowIndex;
      if (selectedRows.has(rowIndex)) tr.classList.add('selected');

      const columns = [
        { key: 'id', cls: 'id-input', input: 'text' },
        { key: 'name', cls: '', input: 'text' },
        { key: 'email', cls: '', input: 'text' },
        { key: 'phone', cls: '', input: 'text' },
        { key: 'department', cls: '', input: 'text' },
        { key: 'salary', cls: 'number-input', input: 'text' }
      ];

      columns.forEach(col => {
        const td = document.createElement('td');
        td.innerHTML = `<input type="${col.input}" class="always-edit ${col.cls}" value="${row[col.key]}"
                  onchange="updateCell(${rowIndex}, '${col.key}', this.value)"
                  onfocus="selectCell(${rowIndex}, '${col.key}', this.value)">`;
        tr.appendChild(td);
      });
      // 狀態(tài)列
      const statusTd = document.createElement('td');
      const statusOptions = ['在職', '離職'];
      statusTd.innerHTML = `<select class="status-select" onchange="updateCell(${rowIndex}, 'status', this.value)" onfocus="selectCell(${rowIndex}, 'status', this.value)">
                  ${statusOptions.map(option => `<option value="${option}" ${row.status === option ? 'selected' : ''}>${option}</option>`).join('')}
                </select>`;
      tr.appendChild(statusTd);
      tbody.appendChild(tr);
    });
  }

  function updateCell(rowIndex, column, value) {
    const originalValue = currentData[rowIndex][column];
    if (column === 'id' || column === 'salary') value = parseInt(value) || 0;

    if (value !== originalValue) {
      if (column === 'id') {
        const newId = parseInt(value);
        const existingIds = currentData.map(row => row.id).filter((id, index) => index !== rowIndex);
        if (existingIds.includes(newId)) {
          showStatusMessage('錯誤:ID已存在!', 'error');
          renderTable();
          return;
        }
      }
      currentData[rowIndex][column] = value;
      const rowId = currentData[rowIndex].id;
      showStatusMessage(`ID ${rowId}: 已更新 ${column} = ${value}`, 'success');
    }
  }

  function selectCell(rowIndex, column, value) {
    selectRow(rowIndex);
    window.currentEditColumn = column;
    window.currentEditValue = value;
  }

  function selectRow(rowIndex) {
    document.querySelectorAll('tr').forEach(tr => tr.classList.remove('selected'));
    selectedRows.clear();
    selectedRows.add(rowIndex);
    const tr = document.querySelector(`tr[data-row-index="${rowIndex}"]`);
    if (tr) tr.classList.add('selected');
    window.currentEditRow = rowIndex;
  }

  function updateRecordInfo() {
    document.getElementById('recordInfo').textContent = `共 ${currentData.length} 條記錄`;
  }

  function showStatusMessage(message, type = 'info') {
    const statusMessageEl = document.getElementById('statusMessage');
    statusMessageEl.textContent = message;
    statusMessageEl.className = `status-message ${type}`;
    setTimeout(() => {
      if (statusMessageEl.textContent === message) {
        statusMessageEl.textContent = '';
        statusMessageEl.className = 'status-message';
      }
    }, 5000);
  }
  // 鍵盤事件處理
  document.addEventListener('keydown', function(event) {
    if ((event.ctrlKey || event.metaKey) && event.key === 's') {
      // Ctrl+S 保存
      event.preventDefault();
      if (window.currentEditRow !== undefined &&
        window.currentEditColumn !== undefined &&
        window.currentEditValue !== undefined) {
        const activeElement = document.activeElement;
        const newValue = activeElement.value;
        updateCell(window.currentEditRow, window.currentEditColumn, newValue);
      }
    } else if (['ArrowUp', 'ArrowDown', 'Tab'].includes(event.key)) {
      // 鍵盤導航
      if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'SELECT') {
        event.preventDefault();
        if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
          handleArrowNavigation(event.key);
        } else if (event.key === 'Tab') {
          handleTabNavigation(event.shiftKey);
        }
      }
    }
  });
  // Tab鍵導航
  function handleTabNavigation(isShiftKey) {
    if (window.currentEditRow === undefined || window.currentEditColumn === undefined) return;
    const currentRow = window.currentEditRow;
    const currentColumn = window.currentEditColumn;
    const totalRows = currentData.length;
    const totalColumns = 7;
    const columnOrder = ['id', 'name', 'email', 'phone', 'department', 'salary', 'status'];
    const currentColumnIndex = columnOrder.indexOf(currentColumn);

    let nextRow = currentRow;
    let nextColumnIndex = currentColumnIndex;
    if (isShiftKey) { // Shift+Tab: 向前導航
      nextColumnIndex--;
      if (nextColumnIndex < 0) {
        nextRow--;
        if (nextRow < 0) nextRow = totalRows - 1;
        nextColumnIndex = totalColumns - 1;
      }
    } else { // Tab: 向后導航
      nextColumnIndex++;
      if (nextColumnIndex >= totalColumns) {
        nextRow++;
        if (nextRow >= totalRows) nextRow = 0;
        nextColumnIndex = 0;
      }
    }
    const nextColumn = columnOrder[nextColumnIndex];
    focusCell(nextRow, nextColumn);
  }
  // 上下箭頭導航
  function handleArrowNavigation(direction) {
    if (window.currentEditRow === undefined || window.currentEditColumn === undefined) return;
    const currentRow = window.currentEditRow;
    let newRow = currentRow;
    const totalRows = currentData.length;
    if (direction === 'ArrowUp' && currentRow > 0) {
      newRow = currentRow - 1;
    } else if (direction === 'ArrowDown' && currentRow < totalRows - 1) {
      newRow = currentRow + 1;
    }
    if (newRow !== currentRow) {
      focusCell(newRow, window.currentEditColumn);
    }
  }
  // 聚焦到指定單元格
  function focusCell(row, column) {
    window.currentEditRow = row;
    window.currentEditColumn = column;
    selectRow(row);
    const tr = document.querySelector(`tr[data-row-index="${row}"]`);
    if (tr) {
      const columnOrder = ['id', 'name', 'email', 'phone', 'department', 'salary', 'status'];
      const columnIndex = columnOrder.indexOf(column);
      const inputs = tr.querySelectorAll('input, select');
      if (inputs[columnIndex]) {
        inputs[columnIndex].focus();
        if (inputs[columnIndex].tagName === 'INPUT' || inputs[columnIndex].tagName === 'TEXTAREA') {
          inputs[columnIndex].select();
        }
        ensureElementVisible(inputs[columnIndex]);
      }
    }
  }
  // 確保元素在視窗中可見
  function ensureElementVisible(element) {
    const tableWrapper = document.getElementById('tableWrapper');
    const rect = element.getBoundingClientRect();
    const wrapperRect = tableWrapper.getBoundingClientRect();
    // 獲取表頭高度(考慮sticky屬性)
    const headerHeight = document.querySelector('.data-table thead').offsetHeight;
    if (rect.bottom > wrapperRect.bottom) {
      const scrollAmount = rect.bottom - wrapperRect.bottom;
      tableWrapper.scrollTop += scrollAmount + 10;
    } else if (rect.top < wrapperRect.top + headerHeight) {
      // 向上滾動時考慮表頭高度
      const scrollAmount = (wrapperRect.top + headerHeight) - rect.top;
      tableWrapper.scrollTop -= scrollAmount + 10;
    }
  }
  document.addEventListener('DOMContentLoaded', function() {
    renderTable();
    updateRecordInfo();
  });
</script>
</body>
</html>

以上就是使用HTML+JavaScript實現(xiàn)可編輯表格的方法的詳細內容,更多關于HTML+JS可編輯表格的資料請關注腳本之家其它相關文章!

相關文章

  • 微信小程序實現(xiàn)多行文字超出部分省略號顯示功能

    微信小程序實現(xiàn)多行文字超出部分省略號顯示功能

    這篇文章主要介紹了微信小程序實現(xiàn)多行文字 超出部分省略號顯示功能,比如設置只顯示2行,超出部分省略號顯示,本文通過實例代碼給大家介紹,需要的朋友可以參考下
    2019-10-10
  • js實現(xiàn)分頁功能

    js實現(xiàn)分頁功能

    這篇文章主要為大家詳細介紹了js實現(xiàn)分頁功能,頁面查詢實現(xiàn)分頁功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • js實現(xiàn)將選中內容分享到新浪或騰訊微博

    js實現(xiàn)將選中內容分享到新浪或騰訊微博

    這篇文章主要介紹了js實現(xiàn)將選中內容分享到新浪或騰訊微博,需要的朋友可以參考下
    2015-12-12
  • javascript簡單實現(xiàn)等比例縮小圖片的方法

    javascript簡單實現(xiàn)等比例縮小圖片的方法

    這篇文章主要介紹了javascript簡單實現(xiàn)等比例縮小圖片的方法,涉及javascript針對頁面元素屬性的讀取、運算及設置相關技巧,需要的朋友可以參考下
    2016-07-07
  • 微信公眾號授權登錄的超詳細步驟

    微信公眾號授權登錄的超詳細步驟

    微信公眾號授權登錄的使用最為常見,當然只是一些會只有登錄,所以選擇點擊授權登,下面這篇文章主要給大家介紹了微信公眾號授權登錄的超詳細步驟,需要的朋友可以參考下
    2022-12-12
  • 根據(jù)分辯率調用不同的CSS.

    根據(jù)分辯率調用不同的CSS.

    根據(jù)分辯率調用不同的CSS....
    2007-01-01
  • 微信小程序頁面導航介紹及使用詳解

    微信小程序頁面導航介紹及使用詳解

    這篇文章主要為大家詳細介紹一下微信小程序實現(xiàn)頁面導航的幾種方法以及幫助大家掌握微信小程序如何進行傳遞參數(shù),感興趣的朋友可以了解一下
    2022-08-08
  • 利用JS實現(xiàn)在線域名DNS查詢工具

    利用JS實現(xiàn)在線域名DNS查詢工具

    本文介紹了本項目中域名DNS查詢工具的功能實現(xiàn),使用Vue組織交互狀態(tài),通過DoH查詢DNS記錄,并將結果整理成可展示的表格數(shù)據(jù),核心功能包括輸入規(guī)范化、查詢觸發(fā)、結果渲染等,并詳細描述了前端和后端的處理邏輯,需要的朋友可以參考下
    2026-03-03
  • 原生JS實現(xiàn)簡單放大鏡效果

    原生JS實現(xiàn)簡單放大鏡效果

    這篇文章主要為大家詳細介紹了原生JS實現(xiàn)簡單放大鏡效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • js Event對象的5種坐標

    js Event對象的5種坐標

    使用鼠標事件經(jīng)常碰到這樣的需求,比如獲取鼠標相對于事件源的位置,鼠標相對于事件源對象父元素的位置
    2011-09-09

最新評論

永康市| 阜城县| 行唐县| 洪洞县| 炉霍县| 多伦县| 宁陕县| 连江县| 定远县| 镇坪县| 南乐县| 虹口区| 微山县| 柳林县| 汪清县| 凯里市| 澄江县| 马关县| 眉山市| 四川省| 县级市| 灌阳县| 富民县| 鹤壁市| 常山县| 时尚| 双鸭山市| 金溪县| 安达市| 娱乐| 双江| 黔南| 南部县| 昌乐县| 玉田县| 武威市| 北流市| 乌鲁木齐市| 昆明市| 漳州市| 汽车|