09-小程序原生能力调用

1 阅读2分钟

📱 Taro 从零到一(九):小程序原生能力调用

系列导读:小程序不仅是网页,还能调用扫码、定位、相机、支付等原生能力。 Taro 将各平台原生 API 统一封装,让你一套代码调用所有平台能力。


🗂 1. Taro API 分类

分类常用 API用途
🔐 登录授权Taro.login / Taro.getUserInfo获取用户身份
📍 位置Taro.getLocation / Taro.chooseLocation定位和选址
📸 媒体Taro.chooseImage / Taro.chooseMedia拍照和选图
📋 剪贴板Taro.setClipboardData / Taro.getClipboardData复制粘贴
📲 扫码Taro.scanCode扫描二维码/条码
📞 电话Taro.makePhoneCall拨打电话
📦 存储Taro.setStorage / Taro.getStorage本地缓存
📤 分享useShareAppMessage分享到聊天
💰 支付Taro.requestPayment发起支付
🔔 通知Taro.requestSubscribeMessage订阅消息

🔐 2. 登录与用户信息

import Taro from '@tarojs/taro'

// 微信登录流程
async function wechatLogin() {
  try {
    // 1. 获取 code
    const { code } = await Taro.login()
    console.log('登录 code:', code)

    // 2. 发送 code 到后端换取 token
    const res = await http.post('/api/auth/wechat', { code })
    const { token, user } = res

    // 3. 保存登录状态
    useAuthStore.getState().setAuth(token, user)

    Taro.showToast({ title: '登录成功', icon: 'success' })
  } catch (error) {
    Taro.showToast({ title: '登录失败', icon: 'none' })
  }
}

// 获取用户头像和昵称(微信新规需要用户主动填写)
function UserProfileForm() {
  const [avatar, setAvatar] = useState('')
  const [nickname, setNickname] = useState('')

  const handleChooseAvatar = (e) => {
    setAvatar(e.detail.avatarUrl)
  }

  return (
    <View>
      <Button openType="chooseAvatar" onChooseAvatar={handleChooseAvatar}>
        <Image src={avatar || '/assets/default-avatar.png'} className="avatar" />
      </Button>
      <Input
        type="nickname"
        placeholder="请输入昵称"
        onBlur={(e) => setNickname(e.detail.value)}
      />
    </View>
  )
}

📸 3. 图片选择与上传

async function chooseAndUploadImage() {
  try {
    // 1. 选择图片
    const res = await Taro.chooseImage({
      count: 9,                          // 最多 9 张
      sizeType: ['compressed'],          // 压缩
      sourceType: ['album', 'camera'],   // 相册 + 拍照
    })

    const filePaths = res.tempFilePaths

    // 2. 逐个上传
    const uploadResults = await Promise.all(
      filePaths.map(filePath =>
        Taro.uploadFile({
          url: 'https://api.example.com/upload',
          filePath,
          name: 'file',
          header: {
            Authorization: `Bearer ${useAuthStore.getState().token}`,
          },
        })
      )
    )

    // 3. 解析上传结果
    const imageUrls = uploadResults.map(r => {
      const data = JSON.parse(r.data)
      return data.url
    })

    console.log('上传成功:', imageUrls)
    return imageUrls
  } catch (error) {
    if (error.errMsg?.includes('cancel')) return []
    Taro.showToast({ title: '上传失败', icon: 'none' })
    return []
  }
}

📍 4. 定位与地图

async function getCurrentLocation() {
  try {
    // 获取授权
    const setting = await Taro.getSetting()
    if (!setting.authSetting['scope.userLocation']) {
      await Taro.authorize({ scope: 'scope.userLocation' })
    }

    // 获取位置
    const location = await Taro.getLocation({
      type: 'gcj02',   // 国测局坐标(中国推荐)
      isHighAccuracy: true,
    })

    console.log(`经度: ${location.longitude}, 纬度: ${location.latitude}`)
    return location
  } catch (error) {
    Taro.showModal({
      title: '提示',
      content: '需要获取位置权限,请在设置中开启',
      confirmText: '去设置',
      success: (res) => {
        if (res.confirm) Taro.openSetting()
      },
    })
  }
}

// 选择地址
async function chooseAddress() {
  const res = await Taro.chooseLocation({})
  console.log('选择的地址:', res.name, res.address)
  console.log('坐标:', res.latitude, res.longitude)
}

📋 5. 存储与缓存

// 封装存储工具
class Storage {
  // 同步存储
  static set(key: string, value: any) {
    Taro.setStorageSync(key, JSON.stringify(value))
  }

  static get<T>(key: string, defaultValue?: T): T | undefined {
    try {
      const raw = Taro.getStorageSync(key)
      return raw ? JSON.parse(raw) : defaultValue
    } catch {
      return defaultValue
    }
  }

  static remove(key: string) {
    Taro.removeStorageSync(key)
  }

  static clear() {
    Taro.clearStorageSync()
  }

  // 带过期时间的存储
  static setWithExpiry(key: string, value: any, ttlMs: number) {
    const item = {
      value,
      expiry: Date.now() + ttlMs,
    }
    Taro.setStorageSync(key, JSON.stringify(item))
  }

  static getWithExpiry<T>(key: string): T | null {
    try {
      const raw = Taro.getStorageSync(key)
      if (!raw) return null
      const item = JSON.parse(raw)
      if (Date.now() > item.expiry) {
        Taro.removeStorageSync(key)
        return null
      }
      return item.value
    } catch {
      return null
    }
  }
}

// 使用
Storage.set('userInfo', { name: '张三', age: 25 })
const user = Storage.get<User>('userInfo')

// 缓存接口数据 5 分钟
Storage.setWithExpiry('products', productList, 5 * 60 * 1000)
const cached = Storage.getWithExpiry<Product[]>('products')

📤 6. 分享

import { useShareAppMessage, useShareTimeline } from '@tarojs/taro'

function ProductDetailPage() {
  // 分享给好友
  useShareAppMessage(() => ({
    title: '发现一个好物,推荐给你!',
    path: `/pages/detail/index?id=${productId}`,
    imageUrl: product.image,
  }))

  // 分享到朋友圈(微信支持)
  useShareTimeline(() => ({
    title: product.name,
    query: `id=${productId}`,
    imageUrl: product.image,
  }))

  return (
    <View>
      <Button openType="share">分享给好友</Button>
    </View>
  )
}

✅ 本篇小结 Checklist

  • 掌握微信登录流程
  • 会实现图片选择和上传
  • 掌握定位和选择地址
  • 会封装本地存储工具
  • 实现分享功能

下一篇预告:《实战项目:从零搭建一个完整小程序》


本文是「Taro 从零到一」系列第 9 篇,共 10 篇。