在uni-app+Vue3中使用JSSDK时,如何调用微信提供的原生接口?

在 uni-app + Vue3 中调用微信 JSSDK 原生接口的详细方法

一、前置条件
  1. 环境准备

    • uni-app 版本 ≥ 3.0
    • Vue 版本 ≥ 3.2
    • 已引入微信 JSSDK(在 index.html 中)
    • 已完成微信公众号配置(AppID、安全域名)
  2. JSSDK 初始化

    • 确保在调用接口前已完成 JSSDK 配置
    • 配置中需包含要使用的接口名称(jsApiList
二、调用微信原生接口的通用步骤
  1. 初始化 JSSDK
  2. wx.ready 回调中调用接口
  3. 处理成功/失败回调
// 1. 初始化 JSSDK
wx.config({
  debug: false, // 生产环境关闭调试
  appId: 'YOUR_APPID',
  timestamp: 123456789, // 时间戳
  nonceStr: 'abcdefg', // 随机字符串
  signature: '...', // 签名
  jsApiList: [
    'getLocation', // 地理位置
    'scanQRCode', // 扫一扫
    'chooseImage', // 选择图片
    'updateAppMessageShareData', // 分享给朋友
    // 其他需要使用的接口
  ]
});

// 2. 在 ready 回调中调用接口
wx.ready(() => {
  // 调用具体接口
  wx.getLocation({
    type: 'wgs84',
    success: (res) => {
      // 3. 处理成功回调
      console.log('地理位置:', res);
    },
    fail: (err) => {
      // 处理失败回调
      console.error('获取位置失败:', err);
    }
  });
});
三、在 Vue3 中封装 JSSDK 服务

推荐创建一个可复用的服务模块:

// services/wx.js
import { ref, onMounted, onUnmounted } from 'vue';
import axios from 'axios';

// 缓存配置状态
const isConfigured = ref(false);
let readyCallback = null;

// 获取签名配置
async function getSignature(url) {
  try {
    const response = await axios.get('/api/wx/signature', {
      params: { url }
    });
    return response.data;
  } catch (error) {
    console.error('获取微信签名失败:', error);
    return null;
  }
}

// 初始化 JSSDK
async function initJssdk(jsApiList = []) {
  // 避免重复初始化
  if (isConfigured.value) return true;

  // 获取当前 URL(不含 hash)
  const url = window.location.href.split('#')[0];
  
  // 获取签名配置
  const config = await getSignature(url);
  if (!config) return false;

  return new Promise((resolve, reject) => {
    wx.config({
      debug: false,
      appId: config.appId,
      timestamp: config.timestamp,
      nonceStr: config.nonceStr,
      signature: config.signature,
      jsApiList: [
        'checkJsApi', // 检查接口可用性
        ...jsApiList // 用户自定义接口
      ]
    });

    wx.ready(() => {
      isConfigured.value = true;
      if (readyCallback) readyCallback();
      resolve(true);
    });

    wx.error((res) => {
      console.error('微信 JSSDK 配置失败:', res);
      reject(res);
    });
  });
}

// 检查接口可用性
function checkJsApi(apiList) {
  return new Promise((resolve, reject) => {
    wx.checkJsApi({
      jsApiList: apiList,
      success: (res) => {
        resolve(res.checkResult);
      },
      fail: (err) => {
        reject(err);
      }
    });
  });
}

// 组合式函数:在组件中使用
function useWxApi(jsApiList = []) {
  // 初始化 JSSDK
  onMounted(async () => {
    try {
      await initJssdk(jsApiList);
    } catch (error) {
      console.error('初始化微信 JSSDK 失败:', error);
    }
  });

  // 调用接口的通用方法
  const callWxApi = (apiName, options = {}) => {
    return new Promise((resolve, reject) => {
      if (!isConfigured.value) {
        reject(new Error('JSSDK 未初始化'));
        return;
      }

      wx[apiName]({
        ...options,
        success: (res) => resolve(res),
        fail: (err) => reject(err)
      });
    });
  };

  return {
    isConfigured,
    callWxApi,
    checkJsApi
  };
}

export default {
  initJssdk,
  checkJsApi,
  useWxApi
};
四、常用接口调用示例
1. 获取地理位置
<template>
  <view>
    <button @click="getLocation">获取位置</button>
    <text v-if="location">
      纬度: {{ location.latitude }}, 经度: {{ location.longitude }}
    </text>
  </view>
</template>

<script setup>
import { ref } from 'vue';
import wxService from '@/services/wx';

// 注入 JSSDK 服务,指定需要的接口
const { callWxApi } = wxService.useWxApi(['getLocation']);
const location = ref(null);
const error = ref(null);

const getLocation = async () => {
  try {
    const res = await callWxApi('getLocation', {
      type: 'wgs84', // 默认为wgs84的gps坐标,可改为'gcj02'
      success: (res) => {
        location.value = {
          latitude: res.latitude,
          longitude: res.longitude,
          speed: res.speed,
          accuracy: res.accuracy
        };
      }
    });
    console.log('位置信息:', res);
  } catch (err) {
    error.value = err;
    console.error('获取位置失败:', err);
  }
};
</script>
2. 扫一扫功能
<template>
  <view>
    <button @click="scanCode">扫一扫</button>
    <text v-if="scanResult">扫描结果: {{ scanResult }}</text>
  </view>
</template>

<script setup>
import { ref } from 'vue';
import wxService from '@/services/wx';

const { callWxApi } = wxService.useWxApi(['scanQRCode']);
const scanResult = ref('');

const scanCode = async () => {
  try {
    const res = await callWxApi('scanQRCode', {
      needResult: 1, // 1: 返回结果,0: 微信处理结果
      scanType: ['qrCode', 'barCode'], // 二维码或条形码
    });
    scanResult.value = res.resultStr;
  } catch (err) {
    console.error('扫描失败:', err);
  }
};
</script>
3. 拍照/选择图片
<template>
  <view>
    <button @click="chooseImage">选择图片</button>
    <view v-for="(img, index) in images" :key="index">
      <image :src="img" mode="aspectFit" />
    </view>
  </view>
</template>

<script setup>
import { ref } from 'vue';
import wxService from '@/services/wx';

const { callWxApi } = wxService.useWxApi(['chooseImage']);
const images = ref([]);

const chooseImage = async () => {
  try {
    const res = await callWxApi('chooseImage', {
      count: 9, // 最多选择9张
      sizeType: ['original', 'compressed'], // 原图或压缩图
      sourceType: ['album', 'camera'], // 相册或相机
    });
    
    images.value = res.localIds; // 本地图片ID
    
    // 上传图片到微信服务器(可选)
    for (const localId of res.localIds) {
      try {
        const uploadRes = await callWxApi('uploadImage', {
          localId,
          isShowProgressTips: 1
        });
        console.log('上传成功,serverId:', uploadRes.serverId);
        // 可将 serverId 发送到自己的服务器
      } catch (uploadErr) {
        console.error('上传失败:', uploadErr);
      }
    }
  } catch (err) {
    console.error('选择图片失败:', err);
  }
};
</script>
4. 分享功能
<template>
  <view>
    <button @click="setShareConfig">设置分享</button>
  </view>
</template>

<script setup>
import wxService from '@/services/wx';

const { callWxApi } = wxService.useWxApi([
  'updateAppMessageShareData', // 分享给朋友
  'updateTimelineShareData'    // 分享到朋友圈
]);

const setShareConfig = async () => {
  try {
    // 设置分享给朋友
    await callWxApi('updateAppMessageShareData', {
      title: '分享标题',
      desc: '分享描述',
      link: 'https://yourdomain.com/share',
      imgUrl: 'https://yourdomain.com/logo.png',
      success: () => {
        console.log('设置好友分享成功');
      }
    });
    
    // 设置分享到朋友圈
    await callWxApi('updateTimelineShareData', {
      title: '分享标题',
      link: 'https://yourdomain.com/share',
      imgUrl: 'https://yourdomain.com/logo.png',
      success: () => {
        console.log('设置朋友圈分享成功');
      }
    });
  } catch (err) {
    console.error('设置分享失败:', err);
  }
};
</script>
五、高级用法
1. 批量检查接口可用性
const checkApiAvailability = async () => {
  try {
    const result = await wxService.checkJsApi([
      'getLocation',
      'scanQRCode',
      'chooseImage'
    ]);
    
    console.log('接口可用性:', result);
    // result 格式: { getLocation: true, scanQRCode: true, ... }
  } catch (err) {
    console.error('检查接口失败:', err);
  }
};
2. 自定义组合式函数
// composables/useWxLocation.js
import { ref, onMounted } from 'vue';
import wxService from '@/services/wx';

export function useWxLocation() {
  const location = ref(null);
  const isLoading = ref(false);
  const error = ref(null);
  
  const { callWxApi } = wxService.useWxApi(['getLocation']);
  
  const getLocation = async (options = {}) => {
    isLoading.value = true;
    error.value = null;
    
    try {
      const res = await callWxApi('getLocation', {
        type: 'wgs84',
        ...options
      });
      
      location.value = {
        latitude: res.latitude,
        longitude: res.longitude,
        speed: res.speed,
        accuracy: res.accuracy
      };
    } catch (err) {
      error.value = err;
    } finally {
      isLoading.value = false;
    }
  };
  
  // 组件挂载时自动获取位置(可选)
  onMounted(() => {
    getLocation();
  });
  
  return {
    location,
    isLoading,
    error,
    getLocation
  };
}

在组件中使用:

<template>
  <view>
    <button @click="getLocation">刷新位置</button>
    <view v-if="isLoading">加载中...</view>
    <view v-else-if="error">错误: {{ error.errMsg }}</view>
    <view v-else-if="location">
      纬度: {{ location.latitude }}, 经度: {{ location.longitude }}
    </view>
  </view>
</template>

<script setup>
import { useWxLocation } from '@/composables/useWxLocation';

const { location, isLoading, error, getLocation } = useWxLocation();
</script>
六、注意事项
  1. URL 一致性

    • 签名计算的 URL 必须与当前页面 URL 完全一致(不含 hash)
    • 单页应用路由变化时需重新获取签名
  2. 错误处理

    • 使用 try/catch 捕获接口调用错误
    • 常见错误:签名错误、权限不足、接口未配置
  3. 接口限制

    • 部分接口需要用户授权(如地理位置)
    • 某些接口有调用频率限制(如上传图片)
  4. 版本兼容

    • 检查微信客户端版本是否支持所需接口
    • 使用 checkJsApi 验证接口可用性
  5. 生产环境优化

    • 关闭 debug: true
    • 缓存签名配置(有效期 7200 秒)
    • 错误日志上报

通过以上方法,您可以在 uni-app + Vue3 项目中优雅地调用微信 JSSDK 提供的各种原生接口,实现丰富的微信生态功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯狂的沙粒

您的鼓励是我创作最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值