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

Vue3?PDF預(yù)覽組件設(shè)計與實現(xiàn)方法分析

 更新時間:2026年03月31日 09:48:59   作者:anan_user_name  
隨著互聯(lián)網(wǎng)的發(fā)展,PDF文件在信息交流和文檔分享中起著重要的作用,通過在Vue組件中實現(xiàn)PDF預(yù)覽功能,我們可以為用戶提供便捷的內(nèi)容閱讀體驗,這篇文章主要介紹了Vue3?PDF預(yù)覽組件設(shè)計與實現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下

引言

PDF 預(yù)覽是現(xiàn)代 Web 應(yīng)用中常見的功能需求,尤其是在文檔管理、在線閱讀等場景下。本文將深入分析一個基于 Vue3 和 PDF.js 實現(xiàn)的高性能 PDF 預(yù)覽組件,探討其設(shè)計思路、核心功能和優(yōu)化策略,為開發(fā)者提供參考。

組件整體架構(gòu)

該組件采用 Vue3 的 Composition API 開發(fā),結(jié)合 PDF.js 庫實現(xiàn) PDF 文檔的加載、渲染和交互。整體架構(gòu)分為以下幾個主要部分:

1. 組件結(jié)構(gòu)與布局

組件采用了清晰的三層布局結(jié)構(gòu):

  • 頭部區(qū)域:包含標題和關(guān)閉按鈕,用于展示文檔標題和控制組件顯示/隱藏
  • 內(nèi)容區(qū)域:分為 PDF 頁面容器和加載指示器
  • PDF 渲染區(qū)域:負責(zé) PDF 頁面的渲染和滾動顯示
<template>
  <div class="pdf-viewer-container" ref="container">
    <div class="pdf-header">
      <!-- 頭部標題和關(guān)閉按鈕 -->
    </div>
    <div class="pdf-content">
      <div class="pdf-pages-wrapper">
        <div class="pdf-pages-container" ref="pagesContainer" @scroll.passive="handleScroll">
          <div class="pdf-canvas-container" ref="canvasContainer"></div>
        </div>
        <!-- PDF加載中指示器 -->
        <div class="spin-container" v-if="loading">
          <n-spin size="large" />
        </div>
      </div>
    </div>
  </div>
</template>

2. 核心狀態(tài)管理

組件通過 Vue3 的響應(yīng)式 API 管理關(guān)鍵狀態(tài):

狀態(tài)變量類型作用
loadingboolean控制加載指示器顯示
pdfDocobjectPDF 文檔實例
totalPagesnumber文檔總頁數(shù)
scalenumber頁面縮放比例
currentPageNumbernumber當(dāng)前頁碼
visiblePagesnumber可見區(qū)域前后渲染頁數(shù)
renderedPagesarray已渲染頁面索引
pageHeightnumber單頁高度
renderingPagesSet正在渲染的頁面集合
renderQueuearray頁面渲染隊列

核心功能實現(xiàn)

1. PDF 文檔加載

組件在 onMounted 鉤子中調(diào)用 initPDF 方法初始化 PDF 文檔:

const initPDF = async () => {
  try {
    loading.value = true;
    await nextTick();
    const loadingTask = pdfjsLib.getDocument({
      url: props.src,
      cMapUrl: "/cmaps/",
      cMapPacked: true,
    });
    const doc = await loadingTask.promise;
    pdfDoc.value = doc;
    totalPages.value = doc.numPages;
    // 設(shè)置默認縮放比例和頁面高度
    const defaultScale = 1.0;
    scale.value = defaultScale;
    if (totalPages.value > 0) {
      const firstPage = await doc.getPage(1);
      const viewport = firstPage.getViewport({ scale: defaultScale });
      pageHeight.value = viewport.height;
    }
    // 渲染可見區(qū)域頁面
    await renderVisiblePages();
    loading.value = false;
  } catch (error) {
    loading.value = false;
    console.error("PDF加載失敗:", error);
  }
};

2. 虛擬滾動機制

為了優(yōu)化大型 PDF 文檔的性能,組件實現(xiàn)了虛擬滾動機制,只渲染可見區(qū)域附近的頁面:

  1. 可見區(qū)域計算:通過 getVisiblePageRange 方法計算當(dāng)前可見區(qū)域需要渲染的頁面范圍
  2. 渲染隊列管理:使用 renderQueueisRenderingQueue 控制頁面渲染順序
  3. 異步渲染:采用異步方式渲染頁面,避免阻塞主線程
  4. 頁面清理:自動清理不可見區(qū)域的頁面,釋放資源
const getVisiblePageRange = () => {
  if (!pagesContainer.value) return { start: 1, end: Math.min(visiblePages.value, totalPages.value) };
  const currentPage = currentPageNumber.value;
  let start = Math.max(1, currentPage - 5);
  let end = Math.min(totalPages.value, currentPage + 5);
  start = Math.max(1, start - 2);
  end = Math.min(totalPages.value, end + 2);
  return { start, end };
};

3. 頁面渲染邏輯

頁面渲染是組件的核心功能,通過 renderPage 方法實現(xiàn):

  1. Canvas 創(chuàng)建與管理:為每個頁面創(chuàng)建獨立的 Canvas 元素,并按順序插入到容器中
  2. 頁面渲染:使用 PDF.js 的 page.render() 方法將頁面內(nèi)容渲染到 Canvas 上
  3. 縮放處理:根據(jù)當(dāng)前縮放比例調(diào)整 Canvas 顯示大小
  4. 錯誤處理:完善的錯誤捕獲和日志記錄機制
const renderPage = async (pageNum) => {
  if (!pdfDoc.value || !canvasContainer.value) return;
  if (pageNum < 1 || pageNum > totalPages.value) return;
  // 檢查頁面是否正在渲染中,如果是則跳過
  if (renderingPages.value.has(pageNum)) {
    return;
  }
  // 標記頁面正在渲染
  renderingPages.value.add(pageNum);
  try {
    const page = await pdfDoc.value.getPage(pageNum);
    const viewport = page.getViewport({
      scale: 2.0,
      rotation: 0 
    });
    // 創(chuàng)建或獲取 Canvas 元素
    let canvas = pageCanvasRefs.value[pageNum];
    if (!canvas) {
      // Canvas 創(chuàng)建邏輯...
    }
    // 設(shè)置 Canvas 尺寸
    canvas.width = Math.round(viewport.width);
    canvas.height = Math.round(viewport.height);
    // 獲取繪圖上下文并渲染頁面
    const context = canvas.getContext('2d');
    if (!context) return;
    await page.render({
      canvasContext: context,
      viewport,
    }).promise;
    // 應(yīng)用當(dāng)前縮放比例
    canvas.style.transform = `scale(${scale.value})`;
  } catch (error) {
    console.error(`渲染頁面 ${pageNum} 失敗:`, error);
  } finally {
    // 標記頁面渲染完成
    renderingPages.value.delete(pageNum);
  }
};

4. 滾動事件處理

組件通過監(jiān)聽滾動事件實現(xiàn)頁面的動態(tài)加載和清理:

  1. 防抖處理:使用 lodash-esdebounce 函數(shù)優(yōu)化滾動事件,避免頻繁觸發(fā)
  2. 當(dāng)前頁碼計算:根據(jù)滾動位置計算當(dāng)前瀏覽的頁碼
  3. 動態(tài)渲染:調(diào)用 renderVisiblePages 方法渲染可見區(qū)域頁面
const handleScroll = debounce(() => {
  if (!pagesContainer.value) return;
  const scrollContainer = pagesContainer.value;
  const scrollTop = scrollContainer.scrollTop;
  const gap = props.pageGap || 20;
  const unit = pageHeight.value + gap;
  let page = 1;
  if (unit > 0) {
    page = Math.floor(scrollTop / unit) + 1;
  }
  if (page < 1) page = 1;
  if (page > totalPages.value) page = totalPages.value;
  currentPageNumber.value = page;
  renderVisiblePages();
}, 500);

性能優(yōu)化策略

1. 虛擬滾動優(yōu)化

  • 渲染范圍控制:只渲染可見區(qū)域前后各 7 頁(總共 15 頁左右)
  • 動態(tài)清理:自動清理距離可見區(qū)域較遠的頁面,釋放內(nèi)存和 DOM 節(jié)點
  • 渲染隊列:采用隊列機制管理頁面渲染,避免同時渲染過多頁面導(dǎo)致性能問題

2. 渲染性能優(yōu)化

  • 高分辨率渲染:使用 2.0 倍縮放渲染 Canvas,提高頁面清晰度
  • 按需渲染:僅在頁面進入可見區(qū)域時渲染,避免不必要的計算和繪制
  • 異步渲染:頁面渲染采用異步方式,不阻塞主線程

3. 內(nèi)存管理

  • Canvas 復(fù)用:對于已經(jīng)渲染過的頁面,保存 Canvas 引用,避免重復(fù)創(chuàng)建
  • 及時清理:組件卸載時釋放 PDF 文檔實例和 Canvas 資源
  • 渲染狀態(tài)管理:使用 Set 數(shù)據(jù)結(jié)構(gòu)跟蹤正在渲染的頁面,避免重復(fù)渲染

代碼亮點與最佳實踐

1. 事件處理優(yōu)化

  • 使用 passive 滾動事件@scroll.passive="handleScroll" 提高滾動性能
  • 防抖處理:減少滾動事件觸發(fā)頻率,優(yōu)化性能

2. 組件生命周期管理

在組件卸載時,釋放所有資源,避免內(nèi)存泄漏:

onUnmounted(() => {
  if (pdfDoc.value) {
    pdfDoc.value.destroy();
  }
  for (const key in pageCanvasRefs.value) {
    const c = pageCanvasRefs.value[Number(key)];
    if (c && c.parentNode) c.parentNode.removeChild(c);
  }
  pageCanvasRefs.value = {};
  renderedPages.value = [];
});

應(yīng)用場景與擴展方向

該組件適用于以下場景:

  • 文檔管理系統(tǒng):用于在線預(yù)覽上傳的 PDF 文檔
  • 在線閱讀平臺:提供流暢的 PDF 閱讀體驗
  • 報表系統(tǒng):用于預(yù)覽和導(dǎo)出報表文檔
  • 教育平臺:在線教材、課件預(yù)覽

擴展方向

  • 添加頁碼導(dǎo)航:允許用戶直接跳轉(zhuǎn)到指定頁碼
  • 實現(xiàn)縮放控制:提供縮放按鈕,允許用戶調(diào)整頁面大小
  • 添加文本搜索功能:支持在 PDF 文檔中搜索文本
  • 實現(xiàn)頁面旋轉(zhuǎn):允許用戶旋轉(zhuǎn)頁面方向
  • 添加書簽功能:支持添加和管理文檔書簽

總結(jié)

本文深入分析了一個基于 Vue3 和 PDF.js 實現(xiàn)的高性能 PDF 預(yù)覽組件,探討了其設(shè)計思路、核心功能和優(yōu)化策略。該組件通過虛擬滾動、按需渲染、異步處理等技術(shù),實現(xiàn)了高效的 PDF 文檔預(yù)覽功能,具有良好的性能表現(xiàn)和用戶體驗。

對于開發(fā)者來說,該組件提供了一個優(yōu)秀的參考案例,展示了如何在 Vue3 項目中實現(xiàn)復(fù)雜的第三方庫集成和高性能交互功能。通過學(xué)習(xí)其設(shè)計思想和實現(xiàn)細節(jié),開發(fā)者可以更好地理解和應(yīng)用 Vue3 的 Composition API,以及如何進行前端性能優(yōu)化。

隨著 Web 技術(shù)的不斷發(fā)展,PDF 預(yù)覽功能的需求將越來越多樣化和復(fù)雜化。開發(fā)者可以在此基礎(chǔ)上,結(jié)合實際業(yè)務(wù)需求,進一步擴展和優(yōu)化該組件,提供更加豐富和高效的 PDF 預(yù)覽體驗。

全部代碼

<template>
  <div class="pdf-viewer-container" ref="container">
    <div class="pdf-header">
      <div class="pdf-header-title">
        <h2>{{ props.title }}</h2>
      </div>
      <div class="pdf-header-actions">
        <n-button quaternary circle @click="close">
          <template #icon>
            <n-icon>
              <Close />
            </n-icon>
          </template>
        </n-button>
      </div>
    </div>
    <div class="pdf-content">
      <!-- 右側(cè)主內(nèi)容 - 多頁容器 -->
      <div class="pdf-pages-wrapper">
        <div class="pdf-pages-container" ref="pagesContainer" :style="{
          position: 'absolute',
          top: '0',
          right: '0',
          bottom: '0',
          left: '0',
          '--page-gap': pageGap + 'px',
        }" @scroll.passive="handleScroll">
          <div class="pdf-canvas-container" ref="canvasContainer"></div>
        </div>
        <!-- PDF加載中指示器 -->
        <div class="spin-container" v-if="loading">
          <n-spin size="large" />
        </div>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import {
  ref,
  onMounted,
  onUnmounted,
  shallowRef,
  nextTick,
} from "vue";
import * as pdfjsLib from "pdfjs-dist/build/pdf";
import { NIcon, NSpin } from "naive-ui";
import {debounce} from 'lodash-es'
import {
  Close,
} from "@vicons/carbon";
const loading = ref(false);
pdfjsLib.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.js', import.meta.url).href;
const props = defineProps({
  src: {
    type: String,
    required: true,
  },
  title: {
    type: String,
    default: 'pdf預(yù)覽',
  },
  pageGap: {
    type: Number,
    default: 20,
  },
});
const pagesContainer = ref<HTMLDivElement | null>(null);
const canvasContainer = ref<HTMLDivElement | null>(null);
const pageCanvasRefs = ref<Record<number, HTMLCanvasElement>>({});
const pdfDoc = shallowRef<any>(null);
const totalPages = ref(0);
const scale = ref(2.0);
const currentPageNumber = ref(1);
// 渲染單頁PDF到canvas
const renderPage = async (pageNum) => {
  if (!pdfDoc.value || !canvasContainer.value) return;
  if (pageNum < 1 || pageNum > totalPages.value) return;
  // 檢查頁面是否正在渲染中,如果是則跳過
  if (renderingPages.value.has(pageNum)) {
    return;
  }
  // 標記頁面正在渲染
  renderingPages.value.add(pageNum);
  try {
    const page = await pdfDoc.value.getPage(pageNum);
    const viewport = page.getViewport({
      scale: 2.0,
      rotation: 0 
    });
    let canvas = pageCanvasRefs.value[pageNum];
    if (!canvas) {
      // 創(chuàng)建新canvas
      canvas = document.createElement('canvas');
      canvas.className = `pdf-page-canvas page-${pageNum}`;
      canvas.style.display = 'block';
      canvas.style.margin = '0 auto var(--page-gap, 20px) auto';
      canvas.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.15)';
      canvas.style.backgroundColor = 'white';
      canvas.style.transition = 'box-shadow var(--transition-speed) ease, transform var(--transition-speed) ease';
      canvas.style.transformOrigin = 'center center';
      // 確保頁面按順序添加到DOM中
      // 查找當(dāng)前頁碼應(yīng)該插入的位置
      const existingPages = Array.from(canvasContainer.value.children);
      let insertIndex = existingPages.length;
      for (let i = 0; i < existingPages.length; i++) {
        const child = existingPages[i];
        if (child.className.includes('pdf-page-canvas')) {
          const childPageNum = parseInt(child.className.match(/page-(\d+)/)[1]);
          if (childPageNum > pageNum) {
            insertIndex = i;
            break;
          }
        }
      }
      // 按順序插入canvas
      canvasContainer.value.insertBefore(canvas, existingPages[insertIndex] || null);
      pageCanvasRefs.value[pageNum] = canvas;
    }
    // 設(shè)置canvas尺寸
    canvas.width = Math.round(viewport.width);
    canvas.height = Math.round(viewport.height);
    // 獲取繪圖上下文
    const context = canvas.getContext('2d');
    if (!context) return;
    // 渲染頁面
    await page.render({
      canvasContext: context,
      viewport,
    }).promise;
    // 應(yīng)用當(dāng)前的縮放transform
    canvas.style.transform = `scale(${scale.value})`;
  } catch (error) {
    console.error(`渲染頁面 ${pageNum} 失敗:`, error);
  } finally {
    // 標記頁面渲染完成
    renderingPages.value.delete(pageNum);
  }
};
// 虛擬滾動相關(guān)變量
const visiblePages = ref(10); // 可見區(qū)域前后各渲染5頁,總共10頁
const renderedPages = ref([]); // 當(dāng)前已渲染的頁面索引
const pageHeight = ref(0); // 單頁高度
const renderingPages = ref(new Set()); // 正在渲染的頁面集合
// 頁面渲染隊列,確保按順序渲染
const renderQueue = ref([]);
let isRenderingQueue = ref(false);
// 計算可見區(qū)域的頁面范圍
const getVisiblePageRange = () => {
  if (!pagesContainer.value) return { start: 1, end: Math.min(visiblePages.value, totalPages.value) };
  const currentPage = currentPageNumber.value;
  let start = Math.max(1, currentPage - 5);
  let end = Math.min(totalPages.value, currentPage + 5);
  start = Math.max(1, start - 2);
  end = Math.min(totalPages.value, end + 2);
  return { start, end };
};
// 處理渲染隊列
const processRenderQueue = async () => {
  if (isRenderingQueue.value) return;
  isRenderingQueue.value = true;
  try {
    while (renderQueue.value.length > 0) {
      const pageNum= renderQueue.value.shift();
      // 跳過已經(jīng)渲染或正在渲染的頁面
      if (renderedPages.value.includes(pageNum) || renderingPages.value.has(pageNum)) {
        continue;
      }
      try {
        // 渲染頁面
        await renderPage(pageNum);
        // 頁面渲染完成后添加到已渲染列表
        if (!renderedPages.value.includes(pageNum)) {
          renderedPages.value.push(pageNum);
          renderedPages.value.sort((a, b) => a - b);
        }
      } catch (innerError) {
        console.error(`渲染頁面 ${pageNum} 失敗:`, innerError);
      }
    }
  } catch (error) {
    console.error('渲染隊列處理異常:', error);
  } finally {
    isRenderingQueue.value = false;
  }
};
// 渲染可見區(qū)域頁面
const renderVisiblePages = async () => {
  if (!pdfDoc.value || !canvasContainer.value) return;
  const { start, end } = getVisiblePageRange();
  // 收集需要渲染的頁面
  const pagesToRender = [];
  const currentQueueSet = new Set(renderQueue.value);
  for (let i = start; i <= end; i++) {
    if (!renderedPages.value.includes(i) &&
      !renderingPages.value.has(i) &&
      !currentQueueSet.has(i)) {
      pagesToRender.push(i);
    }
  }
  if (pagesToRender.length > 0) {
    // 添加到渲染隊列,按順序渲染
    renderQueue.value.push(...pagesToRender.sort((a, b) => a - b));
    // 處理渲染隊列
    processRenderQueue();
  }
  // 清理不可見的頁面(確保不在渲染中)
  const pagesToRemove = renderedPages.value.filter(
    pageNum => pageNum < start - 5 || pageNum > end + 5
  );
  for (const pageNum of pagesToRemove) {
    // 檢查頁面是否正在渲染中,如果是則跳過清理
    if (renderingPages.value.has(pageNum)) {
      continue;
    }
    const canvas = pageCanvasRefs.value[pageNum];
    if (canvas && canvas.parentNode) {
      canvas.parentNode.removeChild(canvas);
      delete pageCanvasRefs.value[pageNum];
    }
    renderedPages.value = renderedPages.value.filter(p => p !== pageNum);
  }
};
// 初始化 PDF
const initPDF = async () => {
  try {
    loading.value = true;
    await nextTick();
    // 確保容器存在且樣式滿足要求
    if (!pagesContainer.value || !canvasContainer.value) {
      await nextTick();
    }
    const loadingTask = pdfjsLib.getDocument({
      url: props.src,
      cMapUrl: "/cmaps/",
      cMapPacked: true,
    });
    const doc = await loadingTask.promise;
    pdfDoc.value = doc;
    totalPages.value = doc.numPages;
    // 設(shè)置默認縮放比例
    const defaultScale = 1.0;
    scale.value = defaultScale;
    // 計算頁面高度和位置
    if (totalPages.value > 0) {
      const firstPage = await doc.getPage(1);
      const viewport = firstPage.getViewport({ scale: defaultScale });
      pageHeight.value = viewport.height;
    }
    // 渲染可見區(qū)域頁面
    await renderVisiblePages();
    loading.value = false;
  } catch (error) {
    loading.value = false;
    console.error("PDF加載失敗:", error);
  }
};
const handleScroll = debounce(() => {
  if (!pagesContainer.value) return;
  const scrollContainer = pagesContainer.value;
  const scrollTop = scrollContainer.scrollTop;
  const gap = props.pageGap || 20;
  const unit = pageHeight.value + gap;
  let page = 1;
  if (unit > 0) {
    page = Math.floor(scrollTop / unit) + 1;
  }
  if (page < 1) page = 1;
  if (page > totalPages.value) page = totalPages.value;
  currentPageNumber.value = page;
  renderVisiblePages();
}, 500);
onMounted(() => {
  initPDF();
});
onUnmounted(() => {
  if (pdfDoc.value) {
    pdfDoc.value.destroy();
  }
  for (const key in pageCanvasRefs.value) {
    const c = pageCanvasRefs.value[Number(key)];
    if (c && c.parentNode) c.parentNode.removeChild(c);
  }
  pageCanvasRefs.value = {};
  renderedPages.value = [];
});
const emit = defineEmits(["close"]);
const close = () => {
  emit("close");
};
</script>
<style lang="less" scoped>
/* 主容器樣式 */
.pdf-viewer-container {
  align-items: center;
  display: flex;
  flex-direction: column;
  height: 100%;
  position: relative;
  width: 100%;
}
/* 圖標激活狀態(tài) */
.n-icon.active {
  color: #1890ff;
}
.pdf-header {
  align-items: center;
  background-color: #fff;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  box-sizing: border-box;
  display: flex;
  gap: 50px;
  height: 56px;
  justify-content: space-between;
  padding: 0 15px;
  width: 100%;
  &-title {
    h2 {
      color: rgb(51, 54, 57);
      font-size: 18px;
      font-weight: 400;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
}
.pdf-content {
  display: flex;
  flex: 1;
  overflow: hidden;
  position: relative;
  width: 100%;
}
.spin-container {
  position: absolute;
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(255, 255, 255, 0.9);
  z-index: 10;
}
.pdf-pages-wrapper {
  background-color: #f4f5f7;
  box-sizing: border-box;
  flex: 1;
  padding: 20px;
  position: relative;
}
// PDF頁面容器樣式
.pdf-pages-container {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  overflow-y: auto;
  overflow-x: auto;
  padding: 0 40px;
  background-color: var(--bg-color);
  // 響應(yīng)式調(diào)整
  @media (max-width: 768px) {
    padding: 0 20px;
  }
  @media (max-width: 480px) {
    padding: 0 10px;
  }
}
/* PDF Canvas Container */
.pdf-canvas-container {
  display: block;
  margin: 0 auto;
  padding: 20px 0;
  width: 100%;
}
// PDF頁面Canvas樣式優(yōu)化
.pdf-page-canvas {
  display: block;
  margin: 0 auto var(--page-gap, 20px) auto;
  border: none;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  background: white;
  transition: box-shadow var(--transition-speed) ease;
  // 頁面懸停效果
  &:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  }
  // 響應(yīng)式頁面間距
  @media (max-width: 768px) {
    --page-gap: 15px;
  }
  @media (max-width: 480px) {
    --page-gap: 10px;
  }
}
</style>

到此這篇關(guān)于Vue3 PDF預(yù)覽組件設(shè)計與實現(xiàn)方法分析的文章就介紹到這了,更多相關(guān)Vue3 PDF預(yù)覽組件設(shè)計內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Elementui如何限制el-input框輸入小數(shù)點

    Elementui如何限制el-input框輸入小數(shù)點

    這篇文章主要介紹了Elementui如何限制el-input框輸入小數(shù)點,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • vue.js實現(xiàn)簡單計時器功能

    vue.js實現(xiàn)簡單計時器功能

    這篇文章主要為大家詳細介紹了vue.js實現(xiàn)簡單計時器功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • node+vue前后端分離實現(xiàn)登錄時使用圖片驗證碼功能

    node+vue前后端分離實現(xiàn)登錄時使用圖片驗證碼功能

    這篇文章主要介紹了node+vue前后端分離實現(xiàn)登錄時使用圖片驗證碼,記錄前端使用驗證碼登錄的過程,后端用的是node.js,關(guān)鍵模塊是svg-captcha,結(jié)合實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-11-11
  • element修改form的el-input寬度,el-select寬度的方法實現(xiàn)

    element修改form的el-input寬度,el-select寬度的方法實現(xiàn)

    有時候像form表單這樣,頁面的input、select等寬度不一定會是一樣的,可能有些長,有些短,本文就介紹了如何element修改form的el-input寬度,el-select寬度的方法實現(xiàn),感興趣的可以了解一下
    2022-02-02
  • 解決vant中 tab欄遇到的坑 van-tabs

    解決vant中 tab欄遇到的坑 van-tabs

    這篇文章主要介紹了解決vant中 tab欄遇到的坑 van-tabs,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • vue使用混入定義全局變量、函數(shù)、篩選器的實例代碼

    vue使用混入定義全局變量、函數(shù)、篩選器的實例代碼

    本文主要是給大家分享利用混入mixins來實現(xiàn)全局變量和函數(shù)。這種方法優(yōu)點是ide會有方法、變量、篩選器提示。對vue中 利用混入定義全局變量、函數(shù)、篩選器的相關(guān)知識感興趣的朋友,跟隨小編一起看看吧
    2019-07-07
  • Vue el-table 默認展開某一行的實例

    Vue el-table 默認展開某一行的實例

    這篇文章主要介紹了Vue el-table 默認展開某一行的實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • Vue和React組件之間的傳值方式詳解

    Vue和React組件之間的傳值方式詳解

    這篇文章主要介紹了Vue和React組件之間的傳值方式詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • Vue中$root的使用方法及注意事項

    Vue中$root的使用方法及注意事項

    這篇文章主要給大家介紹了關(guān)于Vue中$root使用方法及注意事項的相關(guān)資料,vue中$root是用來訪問根組件的,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-03-03
  • vue2.0嵌套路由實現(xiàn)豆瓣電影分頁功能(附demo)

    vue2.0嵌套路由實現(xiàn)豆瓣電影分頁功能(附demo)

    這篇文章主要介紹了vue2.0嵌套路由實現(xiàn)豆瓣電影分頁功能(附demo),這里整理了詳細的代碼,有需要的小伙伴可以參考下。
    2017-03-03

最新評論

大化| 奉新县| 酉阳| 江陵县| 高碑店市| 华容县| 福鼎市| 长阳| 朔州市| 丹寨县| 浦城县| 宕昌县| 长海县| 河东区| 白城市| 泗水县| 保山市| 高碑店市| 崇义县| 彭山县| 杭锦后旗| 新乡县| 东台市| 集安市| 安宁市| 莒南县| 黄大仙区| 新巴尔虎左旗| 任丘市| 神农架林区| 连云港市| 定西市| 郓城县| 江城| 奉化市| 读书| 龙州县| 安国市| 册亨县| 区。| 遂川县|