欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

前端使用pdf.js渲染pdf文件解決方案

 更新時間:2025年07月16日 09:07:18   作者:zyk_520  
這篇文章主要介紹了前端使用pdf.js渲染pdf文件解決方案,pdf.js用于前端渲染PDF并實現(xiàn)搜索、縮放、目錄等交互功能,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

一、前言

在前端開發(fā)中,渲染PDF文件一直是一項重要而挑戰(zhàn)性的任務。而今,我們可以借助pdf.js庫來輕松實現(xiàn)這一目標。pdf.js是一個開源的JavaScript庫,它可以在瀏覽器中渲染PDF文件,實現(xiàn)了在網頁上查看PDF文檔的功能。它提供了豐富的API和功能,使得在前端頁面展示PDF文件變得輕而易舉。讓我們一起探索pdf.js的奇妙之處,輕松實現(xiàn)前端PDF文件的渲染與展示吧!

二、簡介

1、pdf.js介紹

pdf.js是一款基于JavaScript的開源PDF閱讀器組件,可以在網頁中直接顯示和操作PDF文件,目前已知的前端渲染pdf組件都是基于pdf.js進行封裝。

git地址:https://github.com/mozilla/pdf.js

注:開源且免費

2、插件版本參數(shù)

插件版本
Nodev22.13.0

@types/react

^18.0.33

@types/react-dom

^18.0.11
pdfjs-2.5.207-es5-dist.zip (viewer.js使用方式)2.5.207
pdfjs-dist   (canvas渲染方式)

3.6.172

三、通過viewer.html實現(xiàn)預覽(推薦)

1、介紹

除了PDF預覽,還待配套的工具欄,支持功搜索、縮放、目錄、打印等功能~ 

Demo如圖:

2、部署

【1】下載插件包

下載地址:https://github.com/mozilla/pdf.js/releases/tag/v2.5.207

【2】客戶端方式

把下載后的pdfjs-2.5.207-es5-dist.zip解壓后,放在項目中的public文件夾下

【3】服務端方式

 pdf.js包仍然放在public目錄下(或者服務端目錄下)

const pdfServerUrl = '/pdfjs-2.5.207-es5-dist/web/viewer.html'

一個可以獲取pdf文件二進制流的地址(需要同源

....
const pdfInfoUrl = `${location.origin}/xxx/xx.pdf`;
const url = `${pdfServerUrl}?file=${encodeURIComponent(pdfInfoUrl)}`
...
<iframe id='pdfIframe' src={url} width="100%" height="100%"></iframe>

3、使用方法

【1】預覽PDF文件

1)客戶端方式(基于React框架為例)

const viewPDF: React.FC = () => {
    // pdf文件路徑,放在項目的public目錄下
    const pdfUrl = '/A.pdf'; 
    //pdf.js庫的代碼,放在項目的public目錄下
    const pdfServerUrl = '/pdfjs-2.5.207-es5-dist/web/viewer.html'
    const url = `${pdfServerUrl}?file=${pdfUrl}`
  
    return <>
        <h1>pdf 搜索(基于pdf-dist,pdf_viewer.html)</h1>
        <iframe id='pdfIframe' src={url} width="100%" height="100%"></iframe>
      </>;
}

2)服務端方式

通過axios接口獲取文件的arraybuffer,再把arraybuffer轉換成二進制Blob,最后把Bolb轉成blob:url傳給viewer.html

...
import axios from 'axios';
...
const [pdfUrl, setPdfUrl] = useState<string>('');
const getPDFViewUrl = (fileName: any) => {
  axios({
    method: 'get',
    url: `URL`,//文件下載的url
    responseType: 'arraybuffer' 
  }).then(response =>{
      const blob = new Blob([response.data], { type: 'application/pdf' });
      const blobUrl = URL.createObjectURL(blob);
      console.log('zyk===>', blobUrl)
      setPdfUrl(`${pdfServerUrl}?file=${blobUrl}`)
    })
 };

return (
  <>
    <iframe id="pdfIframe" src={pdfUrl} width="100%" height="100%"></iframe>
  </>
);

【2】外部搜索條件觸發(fā)pdf.js的搜索邏輯

  • 跳轉至第一個匹配的內容
  • 匹配內容高亮
const viewPDF: React.FC = () => {
    // pdf文件路徑,放在項目的public目錄下
    const pdfUrl = '/A.pdf'; 
    //pdf.js庫的代碼,放在項目的public目錄下
    const pdfServerUrl = '/pdfjs-2.5.207-es5-dist/web/viewer.html'
    const url = `${pdfServerUrl}?file=${pdfUrl}`

    let pdfContentWindow: any = null; //緩存iframContent
    const getPdfContent = () => {
        const pdfFrame: any = document.getElementById('pdfIframe');
        if (!pdfFrame) {
          return;
        }
        pdfContentWindow = pdfFrame.contentWindow;
        //pdf組件部分信息,包括:當前頁碼、總共頁碼等
        console.log('page===>', pdfContentWindow.PDFViewerApplication); 
    }
    const onSearchForOut = (searchText: string) => {
        pdfContentWindow.postMessage(searchText, '*');
        pdfContentWindow.addEventListener('message', (e: any) => {
          
          // 高亮匹配結果
          pdfContentWindow.PDFViewerApplication.findBar.findField.value = e.data;
          pdfContentWindow.PDFViewerApplication.findBar.highlightAll.checked = true;                        pdfContentWindow.PDFViewerApplication.findBar.dispatchEvent('highlightallchange');
          //觸發(fā)搜索項‘下一個'事件
          pdfContentWindow.PDFViewerApplication.findBar.dispatchEvent('again', false);

    }, false);
  }
  useEffect(() => {
    getPdfContent();
    setTimeout(() => {
      // 外部的搜索條件
      onSearchForOut('陽區(qū)CBD核心區(qū)')
    }, 3* 1000)
  }, []);  


    return <>
        <h1>pdf 搜索(基于pdf-dist,pdf_viewer.html)</h1>
        <iframe id='pdfIframe' src={url} width="100%" height="100%"></iframe>
      </>;
}

四、把pdf渲染為canvas實現(xiàn)預覽

1、安裝

npm install pdfjs-dist --save

2、功能實現(xiàn)

【1】實現(xiàn)pdf預覽

import { Button } from 'antd';
import { useState, useEffect, useRef } from 'react';
import * as pdfjsLib from 'pdfjs-dist'; // 引入pdfjs-dist
const pdfUrl = '/zyk.pdf'; // pdf 文件路徑,pdf文件存放于public目錄下
const workerUrl = `/pdf.worker.min.js`; //webworker存放于public目錄下
pdfjsLib.GlobalWorkerOptions.workerSrc = workerUrl;

const viewPdf = (props: {height: string}) => {
  const {height} = props;
  const pdfContainerRef = useRef<any>(null);
  const [pagesList, setPagesList] = useState<any>([]);
  const scale = 2; // 縮放比例
  // 渲染單個頁面
  const renderPage = async (page: any, pageNumber: number) => {
    const viewport = page.getViewport({ scale });
    const pageContentDom = document.createElement('div');
    pageContentDom.id = `pdfPage-content-${pageNumber}`;
    pageContentDom.style.width = `${viewport.width}px`;
    pageContentDom.style.height = `${viewport.height}px`;
    pageContentDom.style.position = 'relative';
    // 創(chuàng)建 Canvas 元素
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    canvas.id=`pdfPage-${pageNumber}`
    canvas.width = viewport.width;
    canvas.height = viewport.height;
    canvas.style.border = '1px solid black';
    pageContentDom.appendChild(canvas);
    pdfContainerRef.current.appendChild(pageContentDom);
    // 渲染 PDF 頁面到 Canvas
    await page.render({
      canvasContext: context,
      viewport,
    }).promise;
  };
  // 渲染 PDF 頁面
  const renderPagesGroup = ( pages: any) => {
    pages.forEach(({page}:any, index: number) => {
      renderPage(page, index);
    });
  };
  // 加載 PDF 文件
  const loadPdf = async (url: any) => {
    const pdf = await pdfjsLib.getDocument(url).promise;
    const pages: any[] = [];
    for (let i = 1; i <= pdf.numPages; i++) {
      const page = await pdf.getPage(i);
      const textContent = await page.getTextContent();
      pages.push({
        page,
        textContent
      });
    }
    setPagesList(pages);
    renderPagesGroup(pages);
  };
  useEffect(() => {
    loadPdf(pdfUrl);
  }, []);
  return <>
      <div>
          <h1>PDF 搜索(基于@pdfjs-dist-自定義實現(xiàn))</h1> 
      <div>
      <div style={{ height: height || '500px' }}>
        {/* PDF 容器 */}
        <div ref={pdfContainerRef} style={{ position: 'relative', height: '100%', overflowY: 'scroll' }} />
      </div>
      </div>
     </div>
    </>
};

export default viewPdf;

【2】實現(xiàn)pdf內容文本可選進行復制

...
//基于“【1】實現(xiàn)pdf預覽”代碼, 修改renderPage方法

// 渲染單個頁面
 const renderPage = async (page: any, pageNumber: number) => {
    const viewport = page.getViewport({ scale });
    const pageContentDom = document.createElement('div');
    pageContentDom.id = `pdfPage-content-${pageNumber}`;
 //add-begin: 文本可選則  為了文本層和canvas層重疊,利用組件庫的類名(類名不能修改)
 pageContentDom.className = 'pdfViewer';
 pageContentDom.style.setProperty('--scale-factor', scale as any);
 //add-end: 文本可選則
    pageContentDom.style.width = `${viewport.width}px`;
    pageContentDom.style.height = `${viewport.height}px`;
    pageContentDom.style.position = 'relative';
    // 創(chuàng)建 Canvas 元素
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    canvas.id=`pdfPage-${pageNumber}`
    canvas.width = viewport.width;
    canvas.height = viewport.height;
    canvas.style.border = '1px solid black';
    pageContentDom.appendChild(canvas);
    createHeightLightCanvas(viewport, pageNumber, pageContentDom);
    pdfContainerRef.current.appendChild(pageContentDom);
    // 渲染 PDF 頁面到 Canvas
    await page.render({
      canvasContext: context,
      viewport,
    }).promise;
 //add-begin: 文本可選則
    const textLayerDiv = document.createElement('div');
    textLayerDiv.style.width = viewport.width;
    textLayerDiv.style.height = viewport.height;
    //為了文本層和canvas層重疊,利用組件庫的類名
    textLayerDiv.className = 'textLayer';
    const textContent = await page.getTextContent();
    pdfjsLib.renderTextLayer({
      textContentSource: textContent,
      container: textLayerDiv,
      viewport: viewport,
      textDivs: [],
    });
    pageContentDom.appendChild(textLayerDiv);
 //add-end: 文本可選則
  };

【3】實現(xiàn)搜索,匹配內容高亮,并且可以跳轉至匹配內容的位置

import { Button } from 'antd';
import { useState, useEffect, useRef } from 'react';
import * as pdfjsLib from 'pdfjs-dist'; // 引入pdfjs-dist
const pdfUrl = '/zyk.pdf'; // pdf 文件路徑,pdf文件存放于public目錄下
const workerUrl = `/pdf.worker.min.js`; //webworker存放于public目錄下
pdfjsLib.GlobalWorkerOptions.workerSrc = workerUrl;

const viewPdf = (props: {height: string}) => {
   const {height} = props;
  const [searchText, setSearchText] = useState('');
  const pdfContainerRef = useRef<any>(null);
  const [pagesList, setPagesList] = useState<any>([]);
  const [matchList, setMatchList] = useState<any>([]);
  const scale = 2; // 縮放比例
  const createHeightLightCanvas = (viewport: any, pageNumber: number, parentDom: any) => {
    // 為每頁創(chuàng)建一個高亮層canvas
    const highlightCanvas = document.createElement('canvas');
    highlightCanvas.id = `highlightCanvas-${pageNumber}`;
    highlightCanvas.className = 'highlightCanvas';
    highlightCanvas.width = viewport.width;
    highlightCanvas.height = viewport.height;
    highlightCanvas.style.position = 'absolute';
    highlightCanvas.style.top = '0';
    highlightCanvas.style.left = '0';
    highlightCanvas.style.zIndex = '1';
    parentDom.appendChild(highlightCanvas);
  }
  // pageNumber 頁碼(從0開始)
  const jumpToPage = (pageIndex: number) => {
    let beforeCanvasHeight = 0;
    for (let i = 0; i < pageIndex; i++) {
      const canvasParentDom = pdfContainerRef.current.querySelector(`#pdfPage-content-${i}`);
      let canvasParentHeight = canvasParentDom.style.height.replace('px', '');
      beforeCanvasHeight += Number(canvasParentHeight);
    }
    pdfContainerRef.current.scrollTo({
      top: beforeCanvasHeight, // 垂直滾動位置
      behavior: 'smooth'
    });
  }
  const getCurrentTextContentY = (canvas: any, match: any) => {
    // pdfjs 坐標系原點在左下角。transform[5]代表y軸的基線,所以需要減去高度
    const {textBlock} = match;
    const { transform, height } = textBlock;
    return canvas.height - (transform[5] + height -2) * scale;
  }
  // 滾動到指定的匹配項
  const scrollToMatch = (match: any) => {
    const { pageIndex, matchList } = match;
    const firstMatchContent = matchList[0];
    // 獲取滾動區(qū)域的高度
    const scrollHeight = pdfContainerRef.current.scrollHeight;
    console.log('滾動區(qū)域的高度:', scrollHeight);
    // 獲取當前頁碼之前dom的高度
    let beforePageHeight = 0;
    for (let i = 0; i < pageIndex; i++) {
      const canvasParentDom = pdfContainerRef.current.querySelector(`#pdfPage-content-${i}`);
      let canvasParentHeight = canvasParentDom.style.height.replace('px', '');
      beforePageHeight += Number(canvasParentHeight);
    }
    // todo 繼續(xù)計算 匹配項目的高度
    const currentPageCanvas = pdfContainerRef.current.querySelector(`#pdfPage-${pageIndex}`);
    const textContentY = getCurrentTextContentY(currentPageCanvas, firstMatchContent);
    const offsetTop = 50; //為了滾動目標文字不頂格
    const targetScrollTop = beforePageHeight + textContentY -offsetTop;
    pdfContainerRef.current.scrollTo({
      top: targetScrollTop, // 垂直滾動位置
      behavior: 'smooth'
    });
  };
  // 繪制高亮區(qū)域
  const drawHighlights = async (canvas: any, matchesList: MatchBlockItem[]) => {
    if (matchesList.length === 0) {
      return;
    }
    const context = canvas.getContext('2d');
    context.fillStyle = 'rgba(255, 255, 0, 0.5)'; // 黃色半透明填充
    matchesList.forEach((match: any) => {
      const {textBlock} = match;
      const { transform, width, height, str } = textBlock;
      // 獲取每一個字符的寬度
      const charWidth = width / str.length;
      const lightWidth = (match.textEndIndex - match.textStartIndex) * charWidth;
      const lightHeight = height;
      const x = transform[4] + match.textStartIndex * charWidth;
      const y = getCurrentTextContentY(canvas, match);
      context.fillRect(
        Math.floor(x * scale), 
        Math.floor(y), 
        Math.ceil(lightWidth * scale), 
        Math.ceil(lightHeight * scale)
      );
    });
  };
  // 渲染單個頁面
  const renderPage = async (page: any, pageNumber: number) => {
    const viewport = page.getViewport({ scale });
    const pageContentDom = document.createElement('div');
    pageContentDom.id = `pdfPage-content-${pageNumber}`;
    //為了文本層和canvas層重疊,利用組件庫的類名
    pageContentDom.className = 'pdfViewer';
    pageContentDom.style.setProperty('--scale-factor', scale as any);
    pageContentDom.style.width = `${viewport.width}px`;
    pageContentDom.style.height = `${viewport.height}px`;
    pageContentDom.style.position = 'relative';
    // 創(chuàng)建 Canvas 元素
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    canvas.id=`pdfPage-${pageNumber}`
    canvas.width = viewport.width;
    canvas.height = viewport.height;
    canvas.style.border = '1px solid black';
    pageContentDom.appendChild(canvas);
    createHeightLightCanvas(viewport, pageNumber, pageContentDom);
    pdfContainerRef.current.appendChild(pageContentDom);
    // 渲染 PDF 頁面到 Canvas
    await page.render({
      canvasContext: context,
      viewport,
    }).promise;
    // 渲染文本框
    const textLayerDiv = document.createElement('div');
    textLayerDiv.style.width = viewport.width;
    textLayerDiv.style.height = viewport.height;
    //為了文本層和canvas層重疊,利用組件庫的類名
    textLayerDiv.className = 'textLayer';
    const textContent = await page.getTextContent();
    pdfjsLib.renderTextLayer({
      textContentSource: textContent,
      container: textLayerDiv,
      viewport: viewport,
      textDivs: [],
    });
    pageContentDom.appendChild(textLayerDiv)
  };
  // 渲染 PDF 頁面
  const renderPagesGroup = ( pages: any) => {
    pages.forEach(({page}:any, index: number) => {
      renderPage(page, index);
    });
  };
  // 加載 PDF 文件
  const loadPdf = async (url: any) => {
    const pdf = await pdfjsLib.getDocument(url).promise;
    const pages: any[] = [];
    for (let i = 1; i <= pdf.numPages; i++) {
      const page = await pdf.getPage(i);
      const textContent = await page.getTextContent();
      pages.push({
        page,
        textContent
      });
    }
    setPagesList(pages);
    renderPagesGroup(pages);
  };
  const findAllMatches = (text: string, pattern: string) => {
    // 創(chuàng)建正則表達式對象
    const regex = new RegExp(pattern, 'g');
    // 使用match方法找到所有匹配項
    const matches = text.match(regex);
    // 如果沒有匹配項,返回空數(shù)組
    if (!matches) {
        return [];
    }
    // 創(chuàng)建一個數(shù)組來存儲所有匹配的位置
    const positions = [];
    // 遍歷所有匹配項,找到它們在字符串中的位置
    let match;
    while ((match = regex.exec(text)) !== null) {
      positions.push(match.index);
    }
    return positions;
  }

  // todo 優(yōu)化參數(shù)個數(shù),
  const getMatchesList = (
    items: any,
    currentItem: any, 
    currentItemIndex: number,
    currentTextIndex: number, 
    searchStr: string): MatchBlockItem[] => {
    let matchSearchList: MatchBlockItem[] = [];
    if(currentItem.str.length - (currentTextIndex + 1) < searchStr.length -1 ) {
      // 獲取當前文本塊中剩余字符,如果小于搜索字符長度,則繼續(xù)查找下一個文本塊
      let itemText = currentItem.str.slice(currentTextIndex); // 獲取當前文本塊中剩余字符
      let tempMatchSearchList = [{
        blockIndex: currentItemIndex,
        textStartIndex: currentTextIndex,
        textEndIndex: currentItem.str.length,// 由于統(tǒng)一使用slice截取,所以不包括最后一位
        textBlock: currentItem
      }]; // 存儲后續(xù)文本塊
      let index = currentItemIndex;
      const otherSearchLength = searchStr.length -1;
      while (itemText.length <= otherSearchLength) {
        index = index + 1;
        const currentOtherSearchLength = otherSearchLength - itemText.length; // 當前剩余搜索字符長度
        if (items[index].str.length > currentOtherSearchLength) {
          // 文本塊的長度大于剩余搜索字符長度,則截取剩余搜索字符長度的字符
          itemText = `${itemText}${items[index].str.slice(0, currentOtherSearchLength+1)}`;
          tempMatchSearchList.push({
            blockIndex: index,
            textStartIndex: 0,
            textEndIndex: currentOtherSearchLength + 1,
            textBlock: items[index]
          })
        } else {
          // 文本塊的長度小于剩余搜索字符長度,則截取全部字符, 繼續(xù)
          itemText = `${itemText}${items[index].str}`;
          tempMatchSearchList.push({
            blockIndex: index,
            textStartIndex: 0,
            textEndIndex: items[index].str.length,
            textBlock: items[index]
          })
        }
      }
      if (itemText === searchStr) {
        matchSearchList = matchSearchList.concat(tempMatchSearchList);
      }
    }
    else {
      // 獲取當前文本塊中剩余字符,如果大于等于搜索字符長度,則截取當前文本塊中搜索文本長度的字符
      const textEndIndex = currentTextIndex + searchStr.length;
      const text = currentItem.str.slice(currentTextIndex, textEndIndex); // 取出匹配字符所在文本塊及后續(xù)文本塊
      if (text === searchStr) {
        console.log('匹配到了:', currentItem, currentItemIndex)
        matchSearchList.push({
          blockIndex: currentItemIndex,
          textStartIndex: currentTextIndex,
          textEndIndex: textEndIndex,
          textBlock: currentItem
        })
      }
    }
    return matchSearchList;
  }

  // 查找文本的所有出現(xiàn)位置
  const findAllOccurrences = (items: any, searchStr: string): MatchBlockItem[] => {
    const firstSearchStr = searchStr[0];
    let matchSearchList: MatchBlockItem[] = [];
    for(let i=0; i<items.length; i++) {
      const currentItem = items[i];
      const currentMatchIndexList = findAllMatches(currentItem.str, firstSearchStr); // 獲取當前文本塊中第一個匹配字符的索引列表
      if (currentMatchIndexList.length > 0) {
        for(let j=0; j<currentMatchIndexList.length; j++){
          matchSearchList = [...matchSearchList, ...getMatchesList(items, currentItem, i, currentMatchIndexList[j], searchStr)];
        }
      }
    }
    return matchSearchList;
  };
  const clearHeightLightsCanvas = () => {
    const highlightCanvases = Array.from(pdfContainerRef.current.querySelectorAll('.highlightCanvas'));
    highlightCanvases.forEach((canvas: any) => {
      const context = canvas.getContext('2d');
      context.clearRect(0, 0, canvas.width, canvas.height);
    });
  }
  const handleSearch = async () => {
    clearHeightLightsCanvas()
    if (!searchText) {
      jumpToPage(0);
      return;
    }
    const newMatches: any = [];
    console.log('pagesList', pagesList)
    // todo  目前是按照每頁來匹配,可能會匹配不到跨頁的內容
    pagesList.forEach(async ({textContent}: any, pageIndex: number) => {
      const pageMatches = findAllOccurrences(textContent.items, searchText);
      newMatches.push({
        pageIndex, // 頁面索引
        matchList: pageMatches, // 匹配項列表
      });
    })
    console.log('newMatches', newMatches);
    const isNotMatch = newMatches.every((match: any) => match.matchList.length === 0);
    if (isNotMatch) {
      alert('未找到匹配項');
      return;
    }
    /// 重新繪制高亮區(qū)域
    pagesList.forEach((_: any, pageIndex: number) => {
      const highlightCanvas = pdfContainerRef.current.querySelectorAll('.highlightCanvas')[pageIndex]; // 獲取高亮層 Canvas
      const currentMatches = newMatches.find((match: any) => match.pageIndex === pageIndex);
      drawHighlights(
        highlightCanvas,
        currentMatches?.matchList || []
      );
    });
    // 跳轉
    const isExistItem = newMatches.find((match: any) => match.matchList.length > 0);
    if (isExistItem) {
      scrollToMatch(isExistItem);
    }
  };
   // 初始化 PDF.js
   useEffect(() => {
    loadPdf(pdfUrl);
  }, []);
  return <>
      <div>
      <h1>PDF 搜索(基于@pdfjs-dist-自定義實現(xiàn))</h1>
      <input
        type="text"
        value={searchText}
        onChange={(e) => setSearchText(e.target.value)}
        placeholder="輸入要搜索的內容"
      />
        <Button onClick={handleSearch}>搜索</Button>
      <div>
      <div style={{ height: height || '500px' }}>
        {/* PDF 容器 */}
        <div ref={pdfContainerRef} style={{ position: 'relative', height: '100%', overflowY: 'scroll' }} />
      </div>
      </div>
     </div>
    </>
};

export default viewPdf;

【4】獲取pdf文件中目錄的數(shù)據(jù)結構

....
//基于‘【1】實現(xiàn)pdf預覽'的代碼
  const get= async (url: any) => {
    const pdf = await pdfjsLib.getDocument(url).promise;
    // 獲取目錄數(shù)據(jù)
    const pdfCatalogue= await pdf.getOutline();
    console.log('目錄數(shù)據(jù):', pdfCatalogue); 
  };
...

總結 

到此這篇關于前端使用pdf.js渲染pdf文件解決方案的文章就介紹到這了,更多相關前端pdf.js渲染pdf文件內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • javascript實現(xiàn)tabs選項卡切換效果(擴展版)

    javascript實現(xiàn)tabs選項卡切換效果(擴展版)

    常用的頁面效果有彈出層效果,無縫滾動效果,選項卡切換效果,接下來與大家分享一款自己用原生javascript寫的選項卡切換效果在原有的基礎上進行了擴展,加入了自動輪播,這樣就變成了類似圖片輪播的效果
    2013-03-03
  • React?diff算法面試考點超詳細講解

    React?diff算法面試考點超詳細講解

    渲染真實DOM的開銷很大,有時候我們修改了某個數(shù)據(jù),直接渲染到真實dom上會引起整個dom樹的重繪和重排。我們希望只更新我們修改的那一小塊dom,而不是整個dom,diff算法就幫我們實現(xiàn)了這點。diff算法的本質就是:找出兩個對象之間的差異,目的是盡可能做到節(jié)點復用
    2022-12-12
  • JavaScript?canvas繪制動態(tài)圓環(huán)進度條

    JavaScript?canvas繪制動態(tài)圓環(huán)進度條

    這篇文章主要為大家詳細介紹了JavaScript?canvas繪制動態(tài)圓環(huán)進度條,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • JavaScript?內置對象?BigInt詳細解析

    JavaScript?內置對象?BigInt詳細解析

    這篇文章主要介紹了JavaScript?內置對象?BigInt詳細解析,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-07-07
  • JavaScript實現(xiàn)的購物車效果可以運用在好多地方

    JavaScript實現(xiàn)的購物車效果可以運用在好多地方

    JavaScript實現(xiàn)的購物車效果,當然這個效果可以運用在好多地方,比如好友的選擇,人力資源模塊等等,需要的朋友可以參考下
    2014-05-05
  • JS的反射問題

    JS的反射問題

    兩個等號直接比較值,但是類型不能相互轉換的時候報錯
    2010-04-04
  • bootstrap柵格系統(tǒng)示例代碼分享

    bootstrap柵格系統(tǒng)示例代碼分享

    這篇文章主要為大家詳細介紹了bootstrap柵格系統(tǒng)示例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • 基于BootStrap Metronic開發(fā)框架經驗小結【六】對話框及提示框的處理和優(yōu)化

    基于BootStrap Metronic開發(fā)框架經驗小結【六】對話框及提示框的處理和優(yōu)化

    這篇文章主要介紹了基于BootStrap Metronic開發(fā)框架經驗小結【六】對話框及提示框的處理和優(yōu)化的相關知識,主要對比說明在Bootstrap開發(fā)中用到的這些技術要點,對此文感興趣的朋友一起學習吧
    2016-05-05
  • 微信小程序云開發(fā)實現(xiàn)數(shù)據(jù)添加、查詢和分頁

    微信小程序云開發(fā)實現(xiàn)數(shù)據(jù)添加、查詢和分頁

    這篇文章主要為大家詳細介紹了微信小程序云開發(fā)實現(xiàn)數(shù)據(jù)添加、查詢和分頁,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • 使用webpack/gulp構建TypeScript項目的方法示例

    使用webpack/gulp構建TypeScript項目的方法示例

    這篇文章主要介紹了使用webpack/gulp構建TypeScript項目的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-12-12

最新評論