前言
以前开发移动端页面,总会被原生开发各种嫌弃,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