全栈工程师之路-React Native之扫描二维码

前言

以前开发移动端页面,总会被原生开发各种嫌弃,H5性能太低,动画不流畅,身为一名小前端我能怎么办呢?总是在无人的夜里,心里默默地流泪~

后来 React Native 出来以后,终于可以翻身农奴把歌唱:哈哈哈,原生的小X人们,等待我 RN 的小皮鞭吧,pia~

但是那时候若是不懂点 Android 或者 iOS,完全用 RN 开发一个 App,是非常痛苦的。

在尝试一段时间以后,由于实在难以忍受调教各种莫明其妙的报错,让我一度对这项新技能又爱又恨,望而生畏~

但是最近由于项目上的需求又捡了起来,猛然发现,原来不知不觉间,RN 这迷人的小妖精已经成长得越发成熟了~

好了废话不多说,把口水擦干净后,我们先来讲讲本次主题:如何破解一张有码的图片~

项目构建

准备

如何读懂这张有码的图片就是我们要攻克的最大难题了,但是如果单凭我自身大脑的人工智能,我想这问题是无解了。

没错,我们需要用到照相机,随手一搜react-native-camera。。。

咦我是乱搜的,还真有这个库啊。。。再搭配react-native-qrcode-scanner,嗯,就是你了,和我一起拯救银河系吧~

开始工作

首先项目根目录安装三方库,通过yarn add命令安装相应包文件

由于会用到 native 的功能,react link会自动向 native 模块中添加各种依赖和导包的操作。

$ yarn add react-native-camera
$ react-native link react-native-camera
$ yarn add react-native-qrcode-scanner
$ react-native link react-native-qrcode-scanner

这里我们假设点击一个小按钮,然后进入相册,扫描出这张有码的二维图后,回到小按钮页面,并弹出扫描内容。

需要注意的一点是:按钮页和相册扫描是两个页面,这里我们用react-navigation管理路由,具体使用详见这里

先看看App.js:

import React from 'react';
import { StackNavigator } from 'react-navigation';
import Home from './Home';
import Scanner from './Scanner';

// Home 和 Scanner 是两个页面,点开应用后首先进入 Home
const Stack = StackNavigator({
  Home: {
    screen: Home,
  },
  Scanner: {
    screen: Scanner,
  },
});

export default Stack;

这里的Home,react-navigation自动会往props上加个navigation属性,类似 web 开发时的 history,有 push, pop,replace等多个方法。

Home.js只需要一个按钮,点击跳转至 Scanner 页即可

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Button, Toast } from 'antd-mobile';

export default class Home extends Component {

  // react-navigation 的 StackNavigator 会自动在添加组件的 props 上添加 navigation 属性
  static propTypes = {
    navigation: PropTypes.object.isRequired,
  };

  // 点击按钮时触发
  scan = () => {
    this.props.navigation.navigate('Scanner', {
      onRead: this.onRead
    });
  };

  // 传递给下一个页面的回调函数,显示传入内容
  onRead = (message) => {
    Toast.success(message);
  };

  render() {
    return (
      <Button
        onClick={this.scan}
      >屠龙宝刀,点击就送</Button>
    );
  }
}

Scanner.js 就是本次的重点了

import React, { Component } from 'react';
import QRCodeScanner from 'react-native-qrcode-scanner';

const Scanner = props => {
  const { state, goBack } = props.navigation;

  // onRead 是相机扫描二维码后自动调用,首先返回上一页,然后再调用传入的回调函数,显示扫描内容
  return (
    <QRCodeScanner
      onRead={e => {
        goBack();
        state.params.onRead(e.data);
      }}
    />
  );
}

export Scanner;

至此,所有的工作结束。

探索

依然很麻烦不是么?毕竟需要引入两个三方包呢,未来 RN 升级会不会不兼容?

所以即使已给了我莫大的好处,我正义凛然的内心依然是拒绝的。

等等,大侠您等一等!!!先把我脖子上的刀放下来好好说,我不是故意逗你玩的。

不行,我陈D秀这次一定要站着把话说完!

这里不得不说下Expo,一款 RN 开发的工具链,集成并提供了 RN 开发过程中各种问题的解决方案,也是官网目前推荐方式。

于是第二个文件 Scanner.js 修改一下:

import React, { Component } from 'react';
import { BarCodeScanner, Permissions } from 'expo';

class Scanner extends Component {
  state = {
    hasCameraPermission: null,
  };

  static propTypes = {
    navigation: PropTypes.object.isRequired,
  };

  // 这里首先判定是否拥有相机权限,有我们才能正大光明的调用
  async componentWillMount() {
    const { status } = await Permissions.askAsync(Permissions.CAMERA);
    this.setState({ hasCameraPermission: status === 'granted' });
  }

  // 扫描成功自动调用,这里先返回上一页,再调用回调函数,显示扫描内容
  handleBarCodeRead = ({ data }) => {
    const { goBack, state } = this.props.navigation;
    goBack();
    state.params.onRead(data);
  };

  render() {
    const { hasCameraPermission } = this.state;

    // 若无权限,提示用户
    if (hasCameraPermission === null) {
      return <Text>Requesting for camera permission</Text>;
    } else if (hasCameraPermission === false) {
      return <Text>No access to camera</Text>;
    }

    return (
      <View style={{ flex: 1 }}>
        <BarCodeScanner
          onBarCodeRead={this.handleBarCodeRead}
          style={StyleSheet.absoluteFill}
        />
      </View>
    );
  }
}

export default Scanner;

好了,圆满了。对于这智慧的结晶,我还是比较满意的,谢谢大家赞许的目光。

总结

现在使用 RN 最大的感受是,各种开发装备越发全面,当然也或许是之前并未深入学习,对这块的技术链了解太少。

整个开发体验提升不止一个档次,让我再次燃起了内心征服的欲望。

哈哈哈,原生的小X人们,等待着我 RN 的小皮鞭吧,pia


全栈工程师之路-React Native之扫描二维码

上一篇:适用于Android的离线导航软件-那里有什么?


下一篇:android开发的基本布局/导航问题