iT邦幫忙

2024 iThome 鐵人賽

DAY 29
1
JavaScript

不會 VueUse 而被提分手的我系列 第 29

D-29 模仿 vueuse 來做一個自己的 useBarCode 吧 2 封裝

  • 分享至 

  • xImage
  •  

在封裝過程中,我思考如何讓這個工具變得更靈活,支援多種條碼格式,同時考慮到使用者可能遇到的錯誤處理情況。我加入了自定義配置選項,讓開發者能調整掃描靈敏度和生成條碼的樣式。
https://ithelp.ithome.com.tw/upload/images/20241012/20162115iZQ9SL1Xpj.jpg

Type Declarations

首先,我們根據昨天撰寫的文件來撰寫 useBarCode 的型別。主要用於定義函式的參數型別和回傳值,讓開發者能在 TypeScript 中更方便地使用這個函式。

import { Ref } from 'vue';
import JsBarcode from 'jsbarcode';

export interface UseBarCodeOptions {
  format?: JsBarcode.Format; // 條碼格式,如 CODE128, EAN, UPC
  width?: number; // 條碼的寬度
  height?: number; // 條碼的高度
  displayValue?: boolean; // 是否顯示條碼下面的文字
  text?: string; // 條碼顯示的文本
  fontOptions?: string; // 字體選項(如 "bold", "italic")
  font?: string; // 字體類型
  textAlign?: 'left' | 'center' | 'right'; // 條碼文本的對齊方式
  textPosition?: 'top' | 'bottom'; // 條碼文本顯示的位置
  lineColor?: string; // 條碼的顏色
  background?: string; // 條碼的背景顏色
  margin?: number; // 條碼周圍的外邊距
}

export declare function useBarCode(
  text: MaybeRefOrGetter<string>,
  options?: UseBarCodeOptions
): {
  barCodeUrl: Ref<string | null>;
};

Source Code

接下來是 useBarCode 的原始碼部分。我們將使用 JsBarcode 生成條碼,並利用 Vue 的 Composition API 實現響應式管理。

import { computed } from 'vue';
import { toValue } from '@vueuse/core'; // 使用 toValue 來解析 MaybeRefOrGetter
import JsBarcode from 'jsbarcode';

interface UseBarCodeOptions {
  format?: string;
  width?: number;
  height?: number;
  displayValue?: boolean;
  text?: string;
  fontOptions?: string;
  font?: string;
  textAlign?: 'left' | 'center' | 'right';
  textPosition?: 'top' | 'bottom';
  lineColor?: string;
  background?: string;
  margin?: number;
}

export function useBarCode(
  text: MaybeRefOrGetter<string>,
  options?: UseBarCodeOptions
) {
  // 函數用於生成條碼的 Data URL
  const generateBarcode = (barcodeText: string): string | null => {
    const svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg');

    try {
      JsBarcode(svgElement, barcodeText, {
        format: options?.format || 'CODE128',
        width: options?.width || 2,
        height: options?.height || 100,
        displayValue: options?.displayValue ?? true,
        text: options?.text,
        fontOptions: options?.fontOptions || '',
        font: options?.font || 'monospace',
        textAlign: options?.textAlign || 'center',
        textPosition: options?.textPosition || 'bottom',
        lineColor: options?.lineColor || '#000000',
        background: options?.background || '#ffffff',
        margin: options?.margin || 10,
      });

      // 將 SVG 元素轉換為字符串
      const svgString = new XMLSerializer().serializeToString(svgElement);

      // 將 SVG 字符串轉換為 Base64 格式的 Data URL
      return `data:image/svg+xml;base64,${btoa(svgString)}`;
    } catch (error) {
      console.error('Error generating barcode:', error);
      return null;
    }
  };

  // 使用 computed 來生成條碼 URL
  const barCodeUrl = computed(() => {
    const barcodeText = toValue(text);
    if (!barcodeText) {
      return null; // 如果沒有有效的文本,返回 null
    }
    return generateBarcode(barcodeText);
  });

  return {
    barCodeUrl,
  };
}

文件解釋

  1. Type Declarations:
    • 我們定義了一個 UseBarCodeOptions 介面,用於描述可選的條碼配置參數。
    • 函式 useBarCode 接收一個字符串或 MaybeRefOrGetter 作為文本參數,並返回一個包含條碼 URL (barCodeUrl) 的對象,這個 URL 是基於 Base64 的 SVG 格式的 Data URL,適合直接用於顯示條碼圖像。
  2. Source Code:
    • 使用了 Vue 的 Composition API(computedref),來管理條碼生成的響應式邏輯,並使用 VueUse 的 toValue 來處理 MaybeRefOrGetter 的輸入。
    • JsBarcode 用於生成條碼,並且使用 SVG 作為輸出格式,這樣可以保持高解析度並且便於縮放操作。最終生成的 SVG 會被轉換為 Base64 格式的 Data URL,方便在 <img> 標籤中直接使用。
    • generateBarcode 函數
      • 接受文本並使用 JsBarcode 生成條碼。可以通過用戶提供的選項來自定義條碼的外觀(如寬度、高度、顏色等)。
      • 創建一個 SVG 元素,並將其轉換為字符串,再將其轉換為 Base64 URL,以便作為條碼圖像顯示。
    • computed 生成 barCodeUrl
      • 使用 computed 將條碼 URL 的生成邏輯封裝起來,當 text 發生變化時,computed 會自動重新計算並生成新的條碼 URL。
      • computed 保證條碼生成的結果是基於 text 的變化自動更新的,並且有緩存機制,可以提升性能。

總結

這些改進使得 useBarCode 更加靈活和易用:

  • SVG 作為條碼輸出格式:使用 SVG 保證了生成的條碼具有高解析度,適合需要縮放或打印的場景,並且支持使用 Base64 URL 在 <img> 中展示。
  • 更加簡潔的代碼結構:通過使用 computed 而不是 watch 來追蹤變化和自動更新,使得代碼變得更加簡潔、集中和易於理解。computed 的緩存機制也使得條碼生成的計算更加高效。
  • 與 VueUse 工具更好地集成:使用 toValue 可以更靈活地處理 MaybeRefOrGetter 類型的輸入,使得代碼對於各種輸入類型具有更高的兼容性,符合 VueUse 的最佳實踐。

使用方式

這個源代碼可以直接在你的 Vue 應用中使用。useBarCode 會自動根據文本的變化生成新的條碼,並返回 Base64 的 URL,方便直接用於 <img> 標籤顯示。

<template>
  <div>
    <input v-model="text" placeholder="輸入要生成的條碼" />
    <img v-if="barCodeUrl" :src="barCodeUrl" alt="條碼" />
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { useBarCode } from './useBarCode';

const text = ref('1234567890');
const { barCodeUrl } = useBarCode(text);
</script>

既然是模仿 VueUse 工具,明天就來寫文件解析吧~


上一篇
D-28 模仿 vueuse 來做一個自己的 useBarCode 吧 1 確認需求
下一篇
D-30 模仿 vueuse 來做一個自己的 useBarCode 吧 3 文件說明與範例
系列文
不會 VueUse 而被提分手的我30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言