Taro跨端,实现H5跟小程序上传图片兼容问题

66 阅读2分钟

Taro简介

Taro是一个开放式跨端跨框架解决方案,支持使用React/Vue/Nerv等框架来开发 微信 / 京东 / 百度 / 支付宝 / 字节跳动 / QQ / 飞书 / 快手 小程序/ H5 / RN等应用。

项目是Taro + vue3 + ts, 这两天在玩Taro,就遇到一个问题,想实现H5跟小程序都能调用本地图片,但他们调用的方法都不一样!

H5上传本地图片

<input type="file" accept="image/*" style="display: none;" @change="handleFileChange" id="fileInput" />

小程序上传图片


<template>
<view class="photograph flex align-center justify-center" @tap="photographClick" v-if="!isWeb">
    <view class="photograph-icon">
        <image src="../../assets/icon/camera.png" mode=""></image>
    </view>
    拍照识图
</view>
</template>
<script lang="ts" setup>
import Taro from '@tarojs/taro'

const photographClick = () => {
  Taro.chooseImage({
    count: 1,
    sizeType: ['original', 'compressed'],
    sourceType: ['album', 'camera'],
    success: (res) => {
      const tempFilePaths = res.tempFilePaths
      console.log('选择的图片路径:', tempFilePaths)
      // 在这里处理选择的图片
    }
  })
}
</script>

咱们要H5跟小程序都可以使用,就得先判断用户访问的是web端还是小程序,调用Taro.getEnv()方法!

<script lang="ts" setup>
import { ref, onMounted, nextTick } from 'vue'
import Taro from '@tarojs/taro'

const env = ref('')
const isWeb = ref(false)

onMounted(() => {
  env.value = Taro.getEnv()
  isWeb.value = env.value === Taro.ENV_TYPE.WEB // 判断用户进来是web端的话,切换显示上传视图
})
</script>

如果你跟我一样,不想显示input type="file"的原生样式,就可以加个样式style="display: none;"


<template>
<view class="flex flex-wrap">
    <view class="photograph flex align-center justify-center" @tap="photographClick" v-if="!isWeb">
        <view class="photograph-icon">
            <image src="../../assets/icon/camera.png" mode=""></image>
        </view>
       拍照识图
   </view>
   <view class="photograph flex align-center justify-center" @click="triggerFileInput" v-else>
       <view class="photograph-icon">
           <image src="../../assets/icon/camera.png" mode=""></image>
       </view>
       拍照识图
       <input type="file" accept="image/*" style="display: none;" @change="handleFileChange" id="fileInput" />
   </view>
</view>
</template>

这时候开始我们就要点击外层triggerFileInput方法,触发模拟点击handleFileChange方法,这里面也是一堆坑的时候!

<script lang="ts" setup>
// 使用了很多种方法去获取input type="file"元素,用ref去绑定实例,inputElement.click()还是会没有反应,用DOM元素,绑定click事件就可以,但记得加一个判断,判断用户只能每次点击一次,不然我发现inputElement.click()会一直重复执行,也是奇怪
const triggerFileInput = () => {
  if (inputClicked.value) return  // 如果已经点击过,直接返回
  inputClicked.value = true  // 标记已经点击过

  nextTick(() => {
    let inputElement = document.querySelector('input[type="file"]') // 只适用当前页面只有一个input type="file"元素

    if (inputElement) {
      inputElement.click()
      inputClicked.value = false
    } else {
      console.error("找不到 <input type='file'>");
    }
  });
};

// handleFileChange方法,上传单张图片,查ChatGPT的时候,发现老让我用event.target.files,结果根本打印不出值!
const handleFileChange = (event) => {
  const files = event.target.firstChild.files[0]
  console.log('files', files);
  if (files) {
    if (!files.type.startsWith("image/")) {
      alert("只能上传图片文件!");
      return;
    }
  } else {
    console.log('files无值', files);
  }
}
</script>

图片需要预览的话,可以转成base64方法,后续有问题在修改!