Vue3使用指南.md 7.8 KB

Vue3 中使用扫描模块指南

本文档说明如何在 Vue3 项目中使用 iData 扫描模块。

📁 文件结构

project/
├── utils/
│   └── useBarcodeModule.js     # 扫描模块核心工具
├── composables/
│   └── useBarcode.js          # Vue3 composable 封装
├── pages/
│   ├── simple-scan.vue        # 简单使用示例
│   ├── scan-example.vue       # 完整功能示例
│   └── composable-scan.vue    # Composable 使用示例
└── docs/
    └── Vue3使用指南.md        # 本文档

🚀 快速开始

1. 基础使用方式

最简单的使用方式,直接在 Vue3 页面中导入和使用:

<template>
  <view class="container">
    <button @click="startScan" :disabled="isScanning">
      {{ isScanning ? '扫描中...' : '开始扫描' }}
    </button>
    
    <view v-if="scanResult">
      扫描结果:{{ scanResult }}
    </view>
  </view>
</template>

<script setup>
import { ref, onUnmounted, onShow } from 'vue'
import { 
  useInit, 
  useGlobalEvent, 
  updateActivePageOnShow,
  cleanupOnPageUnload 
} from '@/utils/useBarcodeModule.js'

const scanResult = ref('')
const isScanning = ref(false)
let removeListener = null

const startScan = async () => {
  // 初始化扫描模块
  useInit()
  
  // 注册扫描事件监听
  removeListener = useGlobalEvent((result) => {
    const barcode = result.barcode || result.data || result.code
    scanResult.value = barcode
    console.log('扫描结果:', result)
  })
  
  isScanning.value = true
}

const stopScan = () => {
  if (removeListener) {
    removeListener()
    removeListener = null
  }
  isScanning.value = false
}

onShow(() => {
  updateActivePageOnShow()
})

onUnmounted(() => {
  if (removeListener) {
    removeListener()
  }
  cleanupOnPageUnload()
})
</script>

2. 使用 Composable(推荐)

更优雅的方式是使用 composable:

<template>
  <view class="container">
    <button @click="startScan" :disabled="isScanning">
      {{ isScanning ? '扫描中...' : '开始扫描' }}
    </button>
    
    <button @click="stopScan" :disabled="!isScanning">
      停止扫描
    </button>
    
    <view v-if="scanResult">
      <text>条码:{{ scanResult.barcode }}</text>
      <text>时间:{{ scanResult.timestamp }}</text>
    </view>
    
    <view v-if="error" class="error">
      错误:{{ error.message }}
    </view>
  </view>
</template>

<script setup>
import { useBarcode } from '@/composables/useBarcode.js'

const {
  isScanning,
  scanResult,
  error,
  startScan,
  stopScan
} = useBarcode({
  onScan: (scanData) => {
    uni.showToast({
      title: `扫描成功: ${scanData.barcode}`,
      icon: 'success'
    })
  },
  onError: (err) => {
    uni.showToast({
      title: '扫描出错',
      icon: 'error'
    })
  },
  autoInit: true
})
</script>

📚 API 说明

核心模块 API

useInit()

初始化扫描模块。

import { useInit } from '@/utils/useBarcodeModule.js'

useInit()

useGlobalEvent(callback)

注册全局扫描事件监听器。

import { useGlobalEvent } from '@/utils/useBarcodeModule.js'

const removeListener = useGlobalEvent((result) => {
  console.log('扫描结果:', result)
})

// 移除监听器
removeListener()

参数:

  • callback: 扫描结果回调函数
    • result: 扫描结果对象

返回值:

  • Function: 移除监听器的函数

updateActivePageOnShow()

更新当前活跃页面,在页面的 onShow 生命周期中调用。

import { updateActivePageOnShow } from '@/utils/useBarcodeModule.js'
import { onShow } from 'vue'

onShow(() => {
  updateActivePageOnShow()
})

cleanupOnPageUnload()

清理页面回调,在页面的 onUnmounted 生命周期中调用。

import { cleanupOnPageUnload } from '@/utils/useBarcodeModule.js'
import { onUnmounted } from 'vue'

onUnmounted(() => {
  cleanupOnPageUnload()
})

Composable API

useBarcode(options)

Vue3 composable,提供响应式的扫描功能。

import { useBarcode } from '@/composables/useBarcode.js'

const {
  isScanning,
  isInitialized,
  scanResult,
  scanHistory,
  error,
  init,
  startScan,
  stopScan,
  clearHistory,
  cleanup
} = useBarcode(options)

Options 参数:

  • onScan: 扫描成功回调
  • onError: 扫描失败回调
  • autoInit: 是否自动初始化(默认 false)

返回的响应式状态:

  • isScanning: 是否正在扫描
  • isInitialized: 是否已初始化
  • scanResult: 最新扫描结果
  • scanHistory: 扫描历史记录
  • error: 错误信息

返回的方法:

  • init(): 初始化扫描器
  • startScan(): 开始扫描
  • stopScan(): 停止扫描
  • clearHistory(): 清空扫描历史
  • cleanup(): 清理资源

🔥 最佳实践

1. 生命周期管理

正确管理页面生命周期是避免内存泄漏的关键:

<script setup>
import { onShow, onUnmounted } from 'vue'
import { updateActivePageOnShow, cleanupOnPageUnload } from '@/utils/useBarcodeModule.js'

// 页面显示时更新活跃页面
onShow(() => {
  updateActivePageOnShow()
})

// 页面卸载时清理
onUnmounted(() => {
  cleanupOnPageUnload()
})
</script>

2. 错误处理

始终处理可能的错误:

<script setup>
const handleScan = async () => {
  try {
    const success = await startScan()
    if (!success) {
      uni.showToast({
        title: '扫描启动失败',
        icon: 'error'
      })
    }
  } catch (error) {
    console.error('扫描错误:', error)
    uni.showToast({
      title: '扫描出错',
      icon: 'error'
    })
  }
}
</script>

3. 结果验证

对扫描结果进行验证和格式化:

const handleScanResult = (result) => {
  try {
    // 提取条码内容
    const barcode = result.barcode || result.data || result.code || String(result)
    
    // 验证条码格式
    if (!barcode || barcode.length < 3) {
      throw new Error('无效的条码格式')
    }
    
    // 处理业务逻辑
    processBarcode(barcode)
    
  } catch (error) {
    console.error('处理扫描结果失败:', error)
    uni.showToast({
      title: '条码格式错误',
      icon: 'error'
    })
  }
}

4. 性能优化

限制历史记录数量,避免内存过度使用:

const addToHistory = (scanData) => {
  scanHistory.value.unshift(scanData)
  
  // 限制历史记录数量
  if (scanHistory.value.length > 100) {
    scanHistory.value = scanHistory.value.slice(0, 100)
  }
}

⚠️ 注意事项

  1. 平台兼容性:此模块仅支持 uni-app APP 端(App-Plus)
  2. 设备要求:需要 iData 扫描设备和对应的原生插件
  3. 权限需求:可能需要相机权限等设备权限
  4. 内存管理:务必在页面卸载时清理监听器
  5. 多页面管理:模块已处理多页面切换,但仍需正确调用生命周期方法

🐛 常见问题

Q: 扫描没有反应?

A: 检查以下几点:

  • 确保已正确初始化 (useInit())
  • 确保已注册监听器 (useGlobalEvent())
  • 确保在 onShow 中调用了 updateActivePageOnShow()
  • 检查设备是否支持扫描功能

Q: 切换页面后扫描结果发送到错误页面?

A: 确保在每个使用扫描的页面的 onShow 生命周期中调用 updateActivePageOnShow()

Q: 页面卸载后仍然收到扫描事件?

A: 确保在 onUnmounted 生命周期中调用清理函数

Q: 内存泄漏问题?

A: 检查是否正确清理了监听器和页面回调

📝 示例页面

项目中提供了三个示例页面:

  1. simple-scan.vue - 最简单的使用方式
  2. scan-example.vue - 完整功能展示
  3. composable-scan.vue - 使用 composable 的优雅方式

建议从简单示例开始,然后根据需要选择合适的实现方式。