上帝打开的那扇窗
因着项目的需要,学习RN有一段时间了,但自己的基础实在是太差,大大小小的问题遇到过无数,也谢谢其中认识或不认识的小伙伴们对我的帮助,真的很感恩,上帝将你们带到我的生命中,有些时候,我所期待的那扇门没有打开,我并不是一个大牛学什么都很快,但上帝为我开了一扇窗,还有你们的热心援助。记录一下菜鸟的自己在其中的挣扎吧~有些已经解决,有些还是不懂,但终有一天,都会好起来的,对吗?
环境搭建:
RN中文的官网说的很详细啦,现在环境搭建的教程还是比较多的,
http://reactnative.cn/docs/0.35/getting-started.html#content(RN中文网)
http://www.reactnative100.com/docs/getting-started.html(RN100的教程也是翻译的很不错呢)
http://facebook.github.io/react-native/docs/getting-started.html#content(Facebook的官网教程与中文网的会有点点不同,它可以在线看效果呢)
可能遇到的问题:
iOS里:第二次打开项目时,因没有提前开启npm,就直接去run了,然后就could not connet to development server了。然后,我就直接去搜索答案,但后来发现,错误提示里说,要我确定是否开启了node,然后我就在控制台里直接 npm start,就可以使用了,给自己的提示是:在网上搜答案之前,要先学习查看错误提示。
Android里:因在iOS中,已经配好了Homebrew、Node、react-native-cli ,接下来就是 Android APP 需要运行的模拟器啦。与Windows上配置Android环境相同,Android Studio 是最简单的配置。但是,Android Studio 是需要有JDK为基础的,因此,提前安装JDK啦。只是自己对 vi 不熟悉,所以一致没有明白 那句 Android_HOME 在配置文件中是怎样的:原来是要将 export 也要写入。
还有一个错误是,没有模拟器:那就需要先创建模拟器呢,就直接在Android Studio里,创建 虚拟设备哈,我们将其命名为 react-native。
再次启动Android项目时,必须要启动模拟器,如何开启呢?在项目所在的目录下,输入命令 android avd ,就可以启动模拟器了。然后,可以再打开一个bash,在项目所在目录下,输入 react-native run-android,就可以出现页面了。
this埋下的坑
原因:我也不知道……
备注:群里小伙伴聊天的时候,我发现大家都很困惑呢~调试小技巧是:pressRow = () => {},这样就会解决this的问题。前辈给了一张图片,来解释这个问题:
Image的宽与高
flex布局是RN中必学的内容,初初接触,满心欢喜,因为它真的很有趣,比在PC端的布局简单,但做起项目来,却发现,有很多都是我不熟悉的,比如Image。
当需求是 一行里有三个按钮,且紧紧靠下时,我才知道它们个属性:
flexDirection: 'row', alignItems: 'flex-end', //子组件在垂直方向上的对齐方式,靠下排列
当这样的布局,会使三个按钮一样宽,可产品的需求并非如此,当我们两边固定宽,中间是一张图片自适应布局时,该怎样布局呢?【拿到屏幕宽度 - 去 2边固定的宽度 = 你中间的宽度】,于是中间的宽度就是如下啦:(其中,我们并不是只要在页面上放置一张图片,而且以图片为背景的一个按钮,那记得将button的宽度与Image的宽度都如下设置呢,而且,Image的style中需要有reiszeMode={'cover'})
width: Dimensions.get('window').width - 两边之和,
显示与隐藏
需求是说,点击一个按钮,弹出两个子列表,而且,每一个子列表还可以进入到新的页面。我跟着网上的资料,模仿着弹出子列表,也模仿出子列表进入新的页面,但我就是不知道如何一起实现,现在觉得自己好low呀,竟然会认为这个不可以一起实现……也是醉了……
先说列表的显示与隐藏吧:(现在看起来,似乎明白了一点state的意义,就是为choosed初始化一个值,表示不选中;然后,在函数里,为当前对象调用 setState,为其选中取反--取反,请不要再用if为值为假了,使用!符号。this.state.choosed表示当前属性的状态值。我在为一个button绑定这个showOrHide()函数,就可以显示啦,但还是要记得,使用this.showOrHide().bind(this)这个方式来绑定,但我不晓得为何如此。
this.state = { choosed: false }
showOrHide() { this.setState({ choosed: !this.state.choosed }); }
接下来再说,在子列表上使用navigator跳转到新的页面,代码如下图所示。在push里面,name是对所进入页面的描述,component是最重要不可出错的呢,在RN中,页面也是一个组件,只是,页面中出现的<View>等都是子组件,组件可以s是自定义的,也可以是RN提供的,所以,也理解有些人编写代码时,将头部和footer单独拿出来写,只是导入了。因为一切都是组件的概念,切记哦,组件的首字母要大写呢。params是页面传递时的参数,比如,在该函数里,在push到新的页面时,会传递参数id,而id是在constructor里this.state中定义好的,这是最简单的传参,都是确定的值,其中,id不一定是数字哦。于是,NewPage就可以利用this.props.id就可以取到id里的值啦~
两者如何一起实现呢?当时我遇到的问题,就是this,因为点击按钮是一个this,点击进入下一个页面时,是需要新的this了,所以,小伙伴们给的建议是bind(this)。
还有问题是,render()方法中如何利用choosed的值来使其显示与隐藏呢?我想,也许会想到<View>组件,但View组件一旦调用就会占据布局上一定的空间吧?于是有小伙使用了<Text>使其宽高均为零,背景色也是之前的按钮颜色,在<Text>组件里,可以显示参数,于是在大括号中{}填写参数,参数是将 this.state.choosed与待显示的button按钮进行&&,也就是说,若this.state.choosed为真,则显示button按钮,若为假,就不显示啦。
帮我打开这扇窗的是交流群中的晴明,他当时被我的简单问题问到崩溃,他说你难道没有编程基础吗?嗯,这是一个好问题,我也在问自己,软件学院毕业的孩子呀,你怎么练一点编程基础都没有呢?忘记背后,努力面前吧。晴明很棒的是,没有一次性的告诉我答案,而是,一点点的引导我,学会分析问题,解决问题,比如在控制台里不断的到console.log()看哪个没有执行。
导航跳转Navigator
navigator组件也许是我这种菜鸟必经痛苦之路呢~在学习Navigator组件的时候,我才知道,并不是将所有的代码都是完全复制两份,一份iOS,一份Android,而且,在初始的iOS和Android路由中,进入同一个页面就好啦,瞬间就开心了,这样,只有设置navigator路由的页面需要复制就可以啦,除非具有平台差异再使用相关方法进行规避,但整体的代码量简化了超级多。
index.ios.js与index.android.js中是相同的,记得import所需用到的defaultComponent组件,相关准确的讲解已有很多的前辈说过,我就以才菜鸟的角度来描述吧,initialRoute因名而定,就是进入在let中所定义的页面(ES6中,let表示在当前函数内有效的参数呢),configureScene定义是下一个页面的出场方式,从右边滑入,还是从下面上浮等,renderScene中我也不是完全懂了,但知道return中,会返回参数。切记,registerComponent注册组件时,就非常重要啦,Test是整个项目的名字,唯一的哦,Index就是初始路由页的名字呢,这两个不要反了,也不要写错了。
于是呢,在IndexPage里,就可以设置navigator进入哪一个页面啦。push。而且,在后来前辈的指导下,我才知道,我只会push,没有学会pop,pop是不需要传参的,它类似于一个短暂的存储,更有效,而且,可以在navigator中pop之前带回回调函数所需要的值。不断的使用push,会浪费很多的存储空间。
垂直居中
RN的样式依然支持“层叠”,也就是说后声明的属性会覆盖先声明的同名属性。但我之前,总是以为层叠是指样式布局中,子组件的样式自动继承父组件的,然后,再对子组件部分声明时,只需要调用子组件样式就可以将父组件的继承属性与子组件的新属性完美结合。但实际并非如此,RN的层叠是指,在子组件里,同时写了父属性和子属性,那么后写的属性会自动覆盖到之前的属性。
“层叠”的真实含义是我后来才明白的。但项目之中,我却发现,当同一行里有图片,也有文字时,我无法做到垂直居中。但同事帮我看的时候,他只是添加了一个属性,就OK了:包括有图片与文字的容器添加属性alignItems: 'center'。学习调试技巧,可以参考前辈们分享的链接:RN调试技巧 http://blog.csdn.net/quanqinyang/article/details/52215652。