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

前端SSE封裝與實(shí)戰(zhàn)用法完全指南

 更新時(shí)間:2026年04月27日 08:58:53   作者:HUDASHEN  
SSE是一種用于實(shí)現(xiàn)服務(wù)器主動(dòng)向客戶端推送數(shù)據(jù)的技術(shù),也被稱為事件流,下面這篇文章主要介紹了前端SSE封裝與實(shí)戰(zhàn)用法的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在前端實(shí)時(shí)通信領(lǐng)域,WebSocket是大家最熟悉的方案,但它存在連接雙向性、協(xié)議復(fù)雜等特點(diǎn),并非所有場(chǎng)景都適用。而Server-Sent Events(SSE)作為一種輕量級(jí)的單向?qū)崟r(shí)通信技術(shù),專為“服務(wù)器向客戶端推送數(shù)據(jù)”場(chǎng)景設(shè)計(jì),具有兼容性好、協(xié)議簡(jiǎn)單、資源占用低等優(yōu)勢(shì),在消息通知、實(shí)時(shí)日志、數(shù)據(jù)監(jiān)控等場(chǎng)景中極具價(jià)值。

本文將聚焦前端視角,從SSE核心概念出發(fā),手把手教你封裝一個(gè)高可用的SSE工具類,并結(jié)合實(shí)際場(chǎng)景講解用法,幫你快速落地SSE技術(shù)。

一、SSE核心概念速覽

SSE是HTML5標(biāo)準(zhǔn)的一部分,定義了一種服務(wù)器向客戶端推送實(shí)時(shí)數(shù)據(jù)的機(jī)制。其核心特點(diǎn)如下:

  • 單向通信:僅支持服務(wù)器向客戶端推送數(shù)據(jù),客戶端無(wú)法通過(guò)SSE向服務(wù)器發(fā)送數(shù)據(jù)(若需雙向通信,可搭配AJAX/ Fetch補(bǔ)充)。

  • 基于HTTP協(xié)議:無(wú)需像WebSocket那樣握手升級(jí)協(xié)議,直接復(fù)用HTTP連接,兼容性更強(qiáng)(IE不支持,可通過(guò)polyfill兼容)。

  • 自動(dòng)重連:瀏覽器原生SSE對(duì)象自帶重連機(jī)制,斷開(kāi)連接后會(huì)自動(dòng)嘗試重連(默認(rèn)間隔3秒,可配置)。

  • 文本協(xié)議:推送的數(shù)據(jù)格式為UTF-8文本,支持自定義消息類型,需遵循特定格式規(guī)范。

補(bǔ)充:SSE與WebSocket適用場(chǎng)景對(duì)比

- 選SSE:消息通知、實(shí)時(shí)日志、股價(jià)更新等單向推送場(chǎng)景,追求輕量、低資源占用。

- 選WebSocket:聊天、協(xié)同編輯等雙向通信場(chǎng)景,需要高頻交互。

二、SSE原生API用法與痛點(diǎn)

在封裝前,先了解瀏覽器原生SSE API的基礎(chǔ)用法,明確封裝的必要性。

2.1 原生API基礎(chǔ)用法

// 1. 創(chuàng)建SSE連接(參數(shù)為后端SSE接口地址)
const eventSource = new EventSource('/api/sse');
// 2. 監(jiān)聽(tīng)通用消息(服務(wù)器發(fā)送的無(wú)type字段的消息)
eventSource.onmessage = (e) => {
  console.log('收到通用消息:', e.data); // e.data為服務(wù)器推送的文本數(shù)據(jù)
};
// 3. 監(jiān)聽(tīng)自定義類型消息(服務(wù)器指定type字段)
eventSource.addEventListener('customEvent', (e) => {
  console.log('收到自定義消息:', e.data);
});
// 4. 監(jiān)聽(tīng)連接打開(kāi)事件
eventSource.onopen = () => {
  console.log('SSE連接已打開(kāi)');
};
// 5. 監(jiān)聽(tīng)連接錯(cuò)誤事件
eventSource.onerror = (error) => {
  console.error('SSE連接異常:', error);
  // 錯(cuò)誤時(shí)會(huì)自動(dòng)重連,可在此處處理特殊邏輯(如登錄失效)
  if (eventSource.readyState === EventSource.CLOSED) {
    console.log('SSE連接已關(guān)閉,將自動(dòng)重連');
  }
};
// 6. 手動(dòng)關(guān)閉連接
// eventSource.close();

2.2 原生API的痛點(diǎn)

原生API能滿足簡(jiǎn)單場(chǎng)景,但在實(shí)際項(xiàng)目中存在諸多不足:

  • 缺乏統(tǒng)一的錯(cuò)誤處理、重連配置(原生重連間隔不可靈活調(diào)整)。

  • 無(wú)法攜帶自定義請(qǐng)求頭(如Token),適配鑒權(quán)場(chǎng)景繁瑣。

  • 消息格式需要手動(dòng)解析,缺乏數(shù)據(jù)格式化、類型校驗(yàn)?zāi)芰Α?/p>

  • 多實(shí)例管理混亂,無(wú)法統(tǒng)一控制所有SSE連接的狀態(tài)。

  • 缺乏重連次數(shù)限制,極端情況下可能無(wú)限重連消耗資源。

因此,我們需要封裝一個(gè)工具類,解決上述問(wèn)題,提供更易用、更健壯的SSE能力。

三、SSE工具類封裝實(shí)現(xiàn)

本次封裝將圍繞“易用性、健壯性、可擴(kuò)展性”設(shè)計(jì),支持自定義請(qǐng)求頭、重連配置、消息格式化、多實(shí)例管理等功能。

3.1 封裝思路

  1. 抽象配置項(xiàng):允許配置接口地址、請(qǐng)求頭、重連間隔、重連次數(shù)上限、消息類型等。

  2. 狀態(tài)管理:維護(hù)連接狀態(tài)(未連接、連接中、已連接、已關(guān)閉),避免重復(fù)連接。

  3. 請(qǐng)求頭適配:通過(guò)XMLHttpRequest間接實(shí)現(xiàn)自定義請(qǐng)求頭(原生EventSource不支持)。

  4. 重連控制:支持自定義重連間隔、重連次數(shù),超過(guò)次數(shù)后停止重連。

  5. 消息處理:統(tǒng)一解析消息格式,支持JSON自動(dòng)格式化、自定義消息回調(diào)。

  6. 生命周期鉤子:提供連接打開(kāi)、關(guān)閉、錯(cuò)誤、重連等鉤子函數(shù),便于業(yè)務(wù)擴(kuò)展。

  7. 單例/多實(shí)例支持:可靈活創(chuàng)建多個(gè)獨(dú)立SSE連接,互不干擾。

3.2 完整封裝代碼

class SSEClient {
  /**
   * 構(gòu)造函數(shù)
   * @param {Object} options 配置項(xiàng)
   * @param {string} options.url SSE接口地址
   * @param {Object} [options.headers={}] 自定義請(qǐng)求頭
   * @param {number} [options.reconnectInterval=3000] 重連間隔(毫秒)
   * @param {number} [options.maxReconnectTimes=10] 最大重連次數(shù),-1表示無(wú)限重連
   * @param {boolean} [options.autoReconnect=true] 是否自動(dòng)重連
   * @param {string} [options.method='GET'] 請(qǐng)求方法(部分瀏覽器僅支持GET)
   * @param {Function} [options.onOpen] 連接打開(kāi)回調(diào)
   * @param {Function} [options.onMessage] 通用消息回調(diào)
   * @param {Function} [options.onError] 錯(cuò)誤回調(diào)
   * @param {Function} [options.onReconnect] 重連回調(diào)
   * @param {Function} [options.onClose] 連接關(guān)閉回調(diào)
   */
  constructor(options = {}) {
    // 默認(rèn)配置
    this.defaultOptions = {
      url: '',
      headers: {},
      reconnectInterval: 3000,
      maxReconnectTimes: 10,
      autoReconnect: true,
      method: 'GET',
      onOpen: () => {},
      onMessage: () => {},
      onError: () => {},
      onReconnect: () => {},
      onClose: () => {},
    };
 
    // 合并配置
    this.options = { ...this.defaultOptions, ...options };
    if (!this.options.url) {
      throw new Error('SSEClient: url is required');
    }
 
    // 狀態(tài)管理
    this.status = 'closed'; // closed, connecting, open
    this.eventSource = null; // 原生EventSource實(shí)例
    this.reconnectCount = 0; // 已重連次數(shù)
    this.reconnectTimer = null; // 重連定時(shí)器
 
    // 初始化連接
    this.connect();
  }
 
  /**
   * 創(chuàng)建連接
   */
  connect() {
    if (this.status === 'connecting' || this.status === 'open') return;
 
    this.status = 'connecting';
    // 原生EventSource不支持自定義請(qǐng)求頭,此處用XMLHttpRequest兼容(部分場(chǎng)景可用)
    // 若瀏覽器支持EventSource的withCredentials,可結(jié)合后端配置實(shí)現(xiàn)鑒權(quán)
    try {
      this.eventSource = new EventSource(this.buildUrl(), { withCredentials: true });
 
      // 監(jiān)聽(tīng)連接打開(kāi)
      this.eventSource.onopen = (e) => {
        this.status = 'open';
        this.reconnectCount = 0; // 重置重連次數(shù)
        this.options.onOpen(e);
      };
 
      // 監(jiān)聽(tīng)通用消息
      this.eventSource.onmessage = (e) => {
        const data = this.formatMessage(e.data);
        this.options.onMessage(data, e);
      };
 
      // 監(jiān)聽(tīng)錯(cuò)誤
      this.eventSource.onerror = (error) => {
        this.status = 'closed';
        this.options.onError(error);
        this.handleReconnect();
      };
    } catch (error) {
      this.status = 'closed';
      this.options.onError(error);
      this.handleReconnect();
    }
  }
 
  /**
   * 處理重連邏輯
   */
  handleReconnect() {
    if (!this.options.autoReconnect) {
      this.options.onClose();
      return;
    }
 
    // 超過(guò)最大重連次數(shù),停止重連
    if (this.options.maxReconnectTimes !== -1 && this.reconnectCount >= this.options.maxReconnectTimes) {
      this.options.onClose();
      return;
    }
 
    // 清除之前的重連定時(shí)器
    if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
 
    // 延遲重連
    this.reconnectTimer = setTimeout(() => {
      this.reconnectCount++;
      this.options.onReconnect(this.reconnectCount, this.options.maxReconnectTimes);
      this.connect();
    }, this.options.reconnectInterval);
  }
 
  /**
   * 構(gòu)建請(qǐng)求URL(拼接查詢參數(shù),可選)
   * @returns {string} 處理后的URL
   */
  buildUrl() {
    const { url, method } = this.options;
    // 若為GET請(qǐng)求,可在此處拼接查詢參數(shù)(示例)
    // 實(shí)際場(chǎng)景可根據(jù)需求擴(kuò)展,如添加時(shí)間戳避免緩存
    return method.toUpperCase() === 'GET' ? `${url}?t=${Date.now()}` : url;
  }
 
  /**
   * 格式化消息數(shù)據(jù)(默認(rèn)JSON解析,可擴(kuò)展)
   * @param {string} data 原始消息數(shù)據(jù)
   * @returns {any} 格式化后的數(shù)據(jù)
   */
  formatMessage(data) {
    try {
      // 嘗試JSON解析
      return JSON.parse(data);
    } catch (error) {
      // 非JSON格式直接返回原始數(shù)據(jù)
      return data;
    }
  }
 
  /**
   * 監(jiān)聽(tīng)自定義類型消息
   * @param {string} eventType 消息類型
   * @param {Function} callback 回調(diào)函數(shù)
   */
  on(eventType, callback) {
    if (!this.eventSource) return;
    this.eventSource.addEventListener(eventType, (e) => {
      const data = this.formatMessage(e.data);
      callback(data, e);
    });
  }
 
  /**
   * 移除自定義類型消息監(jiān)聽(tīng)
   * @param {string} eventType 消息類型
   * @param {Function} callback 回調(diào)函數(shù)
   */
  off(eventType, callback) {
    if (!this.eventSource) return;
    this.eventSource.removeEventListener(eventType, callback);
  }
 
  /**
   * 手動(dòng)關(guān)閉連接
   */
  close() {
    this.options.autoReconnect = false; // 關(guān)閉自動(dòng)重連
    if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
    if (this.eventSource) {
      this.eventSource.close();
      this.eventSource = null;
    }
    this.status = 'closed';
    this.options.onClose();
  }
 
  /**
   * 獲取當(dāng)前連接狀態(tài)
   * @returns {string} 連接狀態(tài)
   */
  getStatus() {
    return this.status;
  }
}

3.3 封裝核心亮點(diǎn)

  • 靈活配置:支持重連間隔、重連次數(shù)、請(qǐng)求頭、生命周期鉤子等自定義配置,適配不同業(yè)務(wù)場(chǎng)景。

  • 健壯性保障:避免重復(fù)連接、清除無(wú)效定時(shí)器、重置重連次數(shù),減少異常場(chǎng)景下的資源消耗。

  • 消息格式化:自動(dòng)解析JSON格式消息,非JSON格式返回原始數(shù)據(jù),簡(jiǎn)化業(yè)務(wù)層處理。

  • 易用性強(qiáng):提供on/off方法監(jiān)聽(tīng)自定義消息,close/getStatus方法控制和查詢連接狀態(tài),API設(shè)計(jì)清晰。

  • 兼容性考量:支持withCredentials實(shí)現(xiàn)跨域鑒權(quán),可結(jié)合polyfill適配IE瀏覽器(后續(xù)補(bǔ)充)。

四、SSE工具類實(shí)戰(zhàn)用法

下面結(jié)合兩個(gè)常見(jiàn)業(yè)務(wù)場(chǎng)景,講解SSE工具類的使用方法。

4.1 場(chǎng)景一:實(shí)時(shí)消息通知

需求:后端推送新消息通知(如系統(tǒng)公告、用戶私信),前端接收后展示通知彈窗。

// 1. 初始化SSE連接(攜帶Token鑒權(quán),假設(shè)后端支持通過(guò)請(qǐng)求頭獲取Token)
const sseClient = new SSEClient({
  url: '/api/sse/notifications',
  headers: {
    Authorization: 'Bearer ' + localStorage.getItem('token'), // 鑒權(quán)Token
  },
  reconnectInterval: 5000, // 重連間隔5秒
  maxReconnectTimes: 5, // 最大重連5次
  // 生命周期鉤子
  onOpen: () => {
    console.log('消息通知SSE連接已打開(kāi)');
  },
  onError: (error) => {
    console.error('消息通知SSE連接異常:', error);
  },
  onReconnect: (count, max) => {
    console.log(`消息通知SSE正在重連,第${count}/${max}次`);
  },
  onClose: () => {
    console.log('消息通知SSE連接已關(guān)閉');
  },
});
 
// 2. 監(jiān)聽(tīng)通用消息(若后端推送的通知無(wú)自定義type)
sseClient.options.onMessage = (data) => {
  console.log('收到新通知:', data);
  // 展示通知彈窗
  showNotification({
    title: data.title,
    content: data.content,
    time: data.createTime,
  });
};
 
// 3. 監(jiān)聽(tīng)自定義類型消息(若后端按通知類型區(qū)分,如system/pm)
sseClient.on('systemNotice', (data) => {
  console.log('收到系統(tǒng)通知:', data);
  // 系統(tǒng)通知特殊處理(如高亮顯示)
  showNotification({ ...data, type: 'system' });
});
 
sseClient.on('privateMessage', (data) => {
  console.log('收到私信:', data);
  // 私信處理(如跳轉(zhuǎn)聊天頁(yè)面)
  showNotification({ ...data, type: 'pm' });
});
 
// 4. 頁(yè)面卸載時(shí)關(guān)閉連接
window.addEventListener('beforeunload', () => {
  sseClient.close();
});

4.2 場(chǎng)景二:實(shí)時(shí)日志展示

需求:前端展示后端接口調(diào)用日志、服務(wù)運(yùn)行日志,實(shí)時(shí)刷新日志列表。

// 1. 初始化SSE連接(攜帶日志類型參數(shù))
const logSseClient = new SSEClient({
  url: '/api/sse/logs?type=api', // 只接收API日志
  autoReconnect: true,
  maxReconnectTimes: -1, // 無(wú)限重連(日志展示需持續(xù)連接)
  onOpen: () => {
    console.log('日志SSE連接已打開(kāi)');
  },
});
 
// 2. 監(jiān)聽(tīng)日志消息,更新頁(yè)面列表
logSseClient.options.onMessage = (logData) => {
  const logList = document.getElementById('log-list');
  const logItem = document.createElement('li');
  // 格式化日志內(nèi)容(時(shí)間、級(jí)別、信息)
  logItem.innerHTML = `
${logData.timestamp}${logData.level}${logData.message}
  `;
  logList.prepend(logItem); // 新增日志插入頂部
  // 限制日志數(shù)量,避免DOM過(guò)多
  if (logList.children.length > 100) {
    logList.removeChild(logList.lastChild);
  }
};
 
// 3. 手動(dòng)關(guān)閉日志連接(如切換到其他標(biāo)簽頁(yè)時(shí))
document.getElementById('close-log-btn').addEventListener('click', () => {
  logSseClient.close();
  console.log('日志SSE連接已手動(dòng)關(guān)閉');
});

五、進(jìn)階優(yōu)化與注意事項(xiàng)

5.1 兼容性處理

IE瀏覽器不支持原生EventSource,可使用第三方polyfill適配,如event-source-polyfill

// 1. 安裝依賴
npm install event-source-polyfill --save
 
// 2. 引入并使用
import { EventSourcePolyfill } from 'event-source-polyfill';
 
// 在SSEClient類中替換原生EventSource
// this.eventSource = new EventSource(this.buildUrl(), { withCredentials: true });
this.eventSource = new EventSourcePolyfill(this.buildUrl(), {
  withCredentials: true,
  headers: this.options.headers, //  polyfill支持自定義請(qǐng)求頭
});

5.2 鑒權(quán)方案

SSE連接的鑒權(quán)是實(shí)際項(xiàng)目中必遇的問(wèn)題,常用方案有兩種:

  1. URL攜帶Token:將Token作為查詢參數(shù)拼接在URL中(適用于無(wú)法自定義請(qǐng)求頭的場(chǎng)景),但需注意URL長(zhǎng)度限制和安全風(fēng)險(xiǎn)(HTTPS環(huán)境下可緩解)。

  2. 請(qǐng)求頭攜帶Token:通過(guò)polyfill(如event-source-polyfill)支持自定義請(qǐng)求頭,將Token放入Authorization頭中,安全性更高,推薦使用。

5.3 性能優(yōu)化

  • 控制重連頻率:避免短間隔、無(wú)限次重連,防止給服務(wù)器造成壓力。

  • 按需連接:頁(yè)面隱藏時(shí)(visibilitychange事件)關(guān)閉連接,顯示時(shí)重新連接,減少資源消耗。

  • 限制消息數(shù)量:實(shí)時(shí)日志、消息列表等場(chǎng)景,定期清理舊數(shù)據(jù),避免DOM節(jié)點(diǎn)過(guò)多導(dǎo)致頁(yè)面卡頓。

5.4 常見(jiàn)問(wèn)題排查

  • 連接建立失敗:檢查URL是否正確、后端服務(wù)是否正常、跨域配置是否允許SSE請(qǐng)求(Access-Control-Allow-Origin等頭)。

  • 無(wú)法接收消息:確認(rèn)后端推送的數(shù)據(jù)格式符合SSE規(guī)范(需以data: 開(kāi)頭,空行結(jié)尾)、消息編碼為UTF-8。

  • 重連失效:檢查autoReconnect是否設(shè)為true、maxReconnectTimes是否合理,是否手動(dòng)調(diào)用了close方法。

  • 鑒權(quán)失敗:確認(rèn)Token是否有效、鑒權(quán)方式是否與后端一致,跨域場(chǎng)景下是否配置了withCredentials。

六、總結(jié)

SSE作為一種輕量級(jí)實(shí)時(shí)通信技術(shù),在單向推送場(chǎng)景中具有顯著優(yōu)勢(shì),相比WebSocket更簡(jiǎn)單、更省資源。本文封裝的SSE工具類解決了原生API的諸多痛點(diǎn),提供了靈活的配置和易用的API,可直接落地到項(xiàng)目中。

實(shí)際開(kāi)發(fā)中,需結(jié)合業(yè)務(wù)場(chǎng)景選擇合適的實(shí)時(shí)通信方案:?jiǎn)蜗蛲扑瓦xSSE,雙向交互選WebSocket。同時(shí)注意兼容性、鑒權(quán)、性能等問(wèn)題,確保SSE服務(wù)穩(wěn)定運(yùn)行。

后續(xù)可進(jìn)一步擴(kuò)展工具類功能,如添加消息緩存、批量處理、重試機(jī)制等,讓SSE能力更加強(qiáng)大。歡迎在評(píng)論區(qū)分享你的SSE使用經(jīng)驗(yàn)和優(yōu)化建議!

到此這篇關(guān)于前端SSE封裝與實(shí)戰(zhàn)用法的文章就介紹到這了,更多相關(guān)前端SSE封裝與實(shí)戰(zhàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 序列化模塊json代碼實(shí)例詳解

    序列化模塊json代碼實(shí)例詳解

    這篇文章主要介紹了序列化模塊json代碼實(shí)例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • 基于bootstrap實(shí)現(xiàn)收縮導(dǎo)航條

    基于bootstrap實(shí)現(xiàn)收縮導(dǎo)航條

    這篇文章主要介紹了基于bootstrap實(shí)現(xiàn)收縮導(dǎo)航條的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • 微信小程序?qū)崿F(xiàn)復(fù)選框效果

    微信小程序?qū)崿F(xiàn)復(fù)選框效果

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)復(fù)選框效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • 微信小程序?qū)崿F(xiàn)拼圖小游戲

    微信小程序?qū)崿F(xiàn)拼圖小游戲

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)拼圖小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • es5 類與es6中class的區(qū)別小結(jié)

    es5 類與es6中class的區(qū)別小結(jié)

    這篇文章主要給大家介紹了關(guān)于es5 類與es6中class區(qū)別的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • javascript匿名函數(shù)應(yīng)用示例介紹

    javascript匿名函數(shù)應(yīng)用示例介紹

    匿名函數(shù),顧名思義就是沒(méi)有名字,下面有個(gè)不錯(cuò)的示例,大家可以學(xué)習(xí)下
    2014-03-03
  • 用JS實(shí)現(xiàn)簡(jiǎn)單的屏幕錄像機(jī)功能

    用JS實(shí)現(xiàn)簡(jiǎn)單的屏幕錄像機(jī)功能

    這篇文章主要給大家介紹了如何用JS實(shí)現(xiàn)簡(jiǎn)單的屏幕錄像機(jī),文中通過(guò)代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-12-12
  • javascript下用ActiveXObject控件替換word書(shū)簽,將內(nèi)容導(dǎo)出到word后打印

    javascript下用ActiveXObject控件替換word書(shū)簽,將內(nèi)容導(dǎo)出到word后打印

    由于時(shí)間比較緊,沒(méi)多的時(shí)候去學(xué)習(xí)研究上述工具包,現(xiàn)在用javascript操作ActiveXObject控件,用替換word模板中的書(shū)簽方式解決。
    2008-06-06
  • JavaScript簡(jiǎn)單實(shí)現(xiàn)動(dòng)態(tài)改變HTML內(nèi)容的方法示例

    JavaScript簡(jiǎn)單實(shí)現(xiàn)動(dòng)態(tài)改變HTML內(nèi)容的方法示例

    這篇文章主要介紹了JavaScript簡(jiǎn)單實(shí)現(xiàn)動(dòng)態(tài)改變HTML內(nèi)容的方法,結(jié)合實(shí)例形式分析了javascript簡(jiǎn)單獲取及修改HTML元素的相關(guān)操作技巧,非常簡(jiǎn)單易懂,需要的朋友可以參考下
    2018-12-12
  • Typescript中使用引用路徑別名報(bào)錯(cuò)的解決方法

    Typescript中使用引用路徑別名報(bào)錯(cuò)的解決方法

    本文主要介紹了Typescript中使用引用路徑別名報(bào)錯(cuò)的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07

最新評(píng)論

秀山| 株洲市| 盈江县| 苍梧县| 黔江区| 江源县| 获嘉县| 旬阳县| 东阿县| 东方市| 原平市| 巩义市| 舞钢市| 驻马店市| 正宁县| 彭水| 昂仁县| 册亨县| 海丰县| 沙坪坝区| 正宁县| 富民县| 成安县| 那曲县| 永川市| 长沙县| 阜新| 筠连县| 龙海市| 和顺县| 台山市| 辽阳市| 扶绥县| 龙井市| 榆社县| 衡阳县| 西吉县| 武穴市| 尼勒克县| 恩施市| 琼海市|