全棧工程師之路-React Native之掃描二維碼

創宇前端發表於2018-03-30

前言

以前開發移動端頁面,總會被原生開發各種嫌棄,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之掃描二維碼

相關文章