前言
突发情况,不得不快速入门学习react-native?,
文章比较倾向于帮助我自己?疏通思维的。
我先贴出学习的项目地址:https://github.com/shooterRao...
是一个比较简洁的水果商城,作者大大也写了文章在掘金:https://juejin.im/post/5a3f06...
但是作为小白来说,其中有很多细节值得学习和研究。
结构
新建src文件夹来存放页面内容和素材。
src下分为:common(公用组件)、img、mobx、scene(页面)四个文件夹。
因为每个页面下可能又有几个组件可以抽出来,所以都各自创建了文件夹来分开来。
Root.js
作用:用于react-navigation的配置。
react-navigation
原本react-native是有默认的Navigator组件,但是在新版本中已经废除了,现在就主要都用这个模块来实现导航。
官方文档:https://reactnavigation.org/d...
博客翻译:http://blog.csdn.net/u0137181...
StackNavigator:用来@R_662_404@面和传递参数
TabNavigator:类似底部导航栏,用来在同一屏幕下切换不同界面
DrawerNavigator:侧滑菜单导航栏,用于轻松设置带抽屉导航的屏幕
这里要实现首页底部的菜单,实现菜单内的页面之间的跳转,要用TabNavigator,
而因为我们也要实现大版权之间的@R_662_404@面,所以也要引入StackNavigator。
另外,我们还要引入所有的主页面。
import TabBarItem from './common/tabBarItem' import theme from './common/color'
这里还引入了tabBarItem和color,
tabBarItem的主要内容如下:
const TabBarItem = ({focused,tintColor,selectedImage,normalImage}) => { return ( <Image source = {focused ? selectedImage : normalImage} style={{ tintColor: tintColor,width: 25,height: 25 }} /> ) }
返回的是导航图标被选中和没被选中的一些改变设定,用于tabBarIcon自定义的设置。
color.js里面保存的就是颜色的常量值,单独抽出来方便使用和修改。
然后定义TabNavigator常量,格式按照文档模仿写即可。再定义一个StackNavigator来绑定TabNavigator实现页面跳转,随后返回这个StackNavigator。
common/viewpager
ViewPager是一种滚动功能,也就是首页的轮播图了,这里的代码应该是直接引用过来的。
这里有一些不太熟悉的模块~
create-react-class:很明显,有了它可以使用React.createClass
prop-types:对react组件中props对象中的变量进行类型检测(老版中直接可以从react里面引入PropTypes,后面独立出来成为了模块)。
react-timer-mixin:https://www.npmjs.com/package...
避免setTimeout,setInterval等带来的潜在风险,用于计时的模块。
不熟悉的react-native组件/API:
Dimensions:https://reactnative.cn/docs/0...
本模块用于获取设备屏幕的宽高。
TouchableOpacity:https://reactnative.cn/docs/0...
当按下的时候,封装的视图的不透明度会降低。
mobx
mobx官网:http://cn.mobx.js.org/
mobx一个功能强大,上手容易的状态管理工具,这里使用它来保存数据进行切换。
参考文章:https://www.jianshu.com/p/505...
在这个项目里,cartGoods.js、newGoods.js、categoryGoods.js分别暂存了商城的数据,通过store.js来管理。
observable,顾名思义,用于观察一个对象,当对象变化的时候,如果对象在autorun()中,就会执行对应的动作。
如果不是观测每一个变化,也可以用computed,顾名思义,可以用于计算:
const plus = computed(() => number.get() > 0);
会返回true或者false,改变的时候,对象在autorun()中且结果变化才会执行。
mobx推荐将修改被观测变量的行为放在action中
项目中使用了ES7语法,所以要安装模块transform-decorators-legacy。
然后定义对应的数据处理的动作,返回RootStore这个类。
scene/Home
主页拥有一个轮播图,以及新品水果的呈现,所以肯定要引入轮播组件和新品水果的数据。
HomeScreen.js:
为了获得mobx的数据,引入Provider才能获取到。加上@inject('rootStore'),可以使用 this.props.rootStore来获取数据。
@inject('rootStore')来实现数据的获取,然后再一步步地把数据传到它们的子组件中。
再来看主类中的内容:
static navigationOptions = { title: '迷你水果商城',headerTitleStyle: {alignSelf: 'center',fontSize: 15,color: theme.fontColor},headerStyle: {height: 38,backgroundColor: theme.color} };
定义了页面头部的信息的样式内容,也是react-navigation中的(这里留个疑问,它怎么定位到头顶的,我如果想定位到其他地方要怎么改呢)。
构造函数中,初始化轮播图片链接地址。
然后渲染页面内容。
NewGoodsItem.js:
这里是封装了展示最近新品的单个小块:
const NewGoodsItem = ({name,price,image,onPress}) => { return ( <TouchableOpacity onPress={() => onPress && onPress()}> <View style={styles.item}> <Image source={image} style={styles.image}/> <Text>{name}</Text> <Text>¥ {price}/500g</Text> </View> </TouchableOpacity> ) }
看代码看得出,你点击每个小块的时候,还会有一个透明度的变化。
NewGoodsView.js:
是整个新品的板块
在HomeScreen.js中是这样写的:
<NewGoodsView itemDatas={data} navigation={this.props.navigation}/>
传入水果数据和导航给NewsGoodsView,这里this.props.navigation是react-navigation中带的:
在界面组件注入到StackNavigator中时,界面组件就被赋予了navigation属性,即在界面组件中可以通过【this.props.navigation】获取并进行一些操作。
在NewGoodsView相应写的是:
<NewGoodsItem onPress={()=> props.navigation.navigate('ItemDetail',{value})} name={value.name} price={value.price} image={value.image} key={index}/>
能想到意思是,当点下新品的单个项目,页面导航会跳转到水果细则。
另外,就是使用了map循环去把整个列表都列出来。
scene/Category
这个页面有一个子导航,以及下面对应的商品列表。
CategoryScreen.js:
为了实现子导航,引入了react-native-scrollable-tab-view这个模块:
https://www.jianshu.com/p/b77...
CategoryListView.js:
每个分类页面的内容封装,有一个可以重新刷新的操作,如果数据有变化再打乱渲染。
就引用了refreshControl控件,用于下拉刷新:https://reactnative.cn/docs/0...
scene/ItemDetail
这里引用了一个react-native-easy-toast模块:https://github.com/crazycodeb...
toast是“吐司”的意思,它属于android杂项组件,是一个简单的消息提示框,类似于javascript中的alert
商品信息页面,除了水果的信息之外,还有一个加入购物车的操作。
在构造函数中定义了一个bounceValue: new Animated.Value(1),用于动画变化,可以查看文档:
https://reactnative.cn/docs/0...
后面在添加到购物车的时候,使用了:
this.state.bounceValue.setValue(1.5); Animated.spring( this.state.bounceValue,toValue: 1,friction: 1,} ).start();
实现了购车图标蹭的一下变大又弹回去的动画。
MessageView.js:
是底部的商品详情/产品参数/售后保障,也用到了之前说的react-native-scrollable-tab-view这个模块。
因为内容比较简单,没有像之前一样再把tab下的子模块又抽出来,直接定义了一个结构来引用:
const List = ({ message }) => ( <View style={{ flex: 1 }}> <Text>{message}</Text> </View> )
scene/Cart
CartScreen.js:
可以直接导航到购物车页面,也可以在商品的页面跳转到购物车页面,在商品详细页面跳转的时候传入了一个参数headerStyle,由此判断进入方式是哪种,好显示返回箭头。
@computed get dataSource() 根据数据是否变化来更新商品数组内容。
_renderItem((item}) 根据数据渲染商品
_keyExtractor(item,index) 返回目标商品的名字
(FlatList的keyExtractor属性指定使用id作为列表每一项的key)
CartList.js:
商品列表,要检测商品选择/不选的变化,检测商品选择数目的变化(+/-)。
CartCheckOut.js:
使用了Alert API:https://reactnative.cn/docs/0...
以及react-native-loading-spinner-overlay模块:https://www.npmjs.com/package...
用于加载时的动画显示提示。
<Spinner visible={this.state.visible} textContent={this.state.loadText} textStyle={{fontSize: 15,color: '#FFF'}} />
等支付的时候才显示这个控件。
支付完成后,需要拷贝购物车数据到订单数据中,购物车数据清空。