前言
以前開發移動端頁面,總會被原生開發各種嫌棄,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