1.对于React-Native开发,仅仅有基础前端开发的知识是不够的,你还需要了解和掌握的有:
• Node.js基础
• JSX语法基础
• Flexbox布局
2.分为两部分:
渲染器 ( renderer ) 和全新的 React
第一部分是全新的 React ,它只负责启用 React 范式。第二部分叫做 ReactDOM ,它唯一的任务就是与浏览器中的 DOM 进行交互。因为 ReactDOM 负责更新 DOM ,而 DOM 又决定了浏览器渲染的内容,所以我们将 ReactDOM 称之为渲染器。
在调用react-native run-android命令时,其实这个命令就是执行的两部分操作一是是构建你的android项目并生成apk,另外一个是打开react-native的package管理工具同时编译你的js文件,其实可以在项目根目录的package.json下找到
其实是执行了另外一条命令node node_modules\react-native\packager\packager.js来打开package的管理工具,有些可能没打开一个新的命令行窗口,自己手动执行这条node命令也是可以的。在这条命令执行完之后,node就会开启一个服务,同时把js文件编译成jsbundle文件,我们可以通过http://localhost:8081/index.android.bundle?platform=android来访问到这个文件,可以简单将这个文件理解成一个html,android就是通过解析这个html来达到渲染的目的,将该文件部署到CDN可供android app从网络获取,即可实现不用发版本让app的UI随时更新,并且可获得接近native的体验,这也是react-native最吸引开发者的亮点之一。
3.
相比于 Web 上的 React ,React Native 包括更多东西:
• 全新的 React 作为核心库 (我们的超级英雄,只不过没穿斗篷)
• iOS 和安卓的渲染器
• 将代码转换成可安装应用的工具
• 原生 UI 组件 (状态栏、列表等等)和动画
• UI 的样式和布局工具箱 (flexbox)
• 构建大多数应用的基础部分 (比如网络)
• 提供原生功能的部分,比如粘贴板、加速计和存储
4.原生 UI 是让 React Native 大放异彩的原因之一。
在react-native中一个文件也是一个组件
React Native 中的尺寸都是无单位的,表示的是与设备像素密度无关的逻辑像素点。
require中的字符串是相对地址或者绝对地址,require()中的参数必须是一个字面量而不能是一个变量活常量
不存在zIndex,后面的元素覆盖前面的元素;内层元素覆盖外层元素等等,borderRadius的设置,需要考虑到内层元素的位置等等。
在React-Native中图片的大小是不会根据给定一个宽度或者高度而自适应大小的,因此我们需要让图片根据宽度或者高度来自适应,那么可以使用resizeMode:Image.resizeMode.contain
5.
props和state共同控制了一个组件,props在父组件中指定,在指定组件的生命周期中不在改变。对于需要改变的数据我们使用state
一般来说,需要在constructor中初始化state
• 一切界面变化都是状态state变化
• state的修改必须通过setState()方法
○ this.state.likes = 100; // 这样的直接赋值修改无效!
○ setState 是一个 merge 合并操作,只修改指定属性,不影响其他属性
○ setState 是异步操作,修改不会马上生效
6.
通过exports去暴露模块的成员或方法(暴露公开的api)
有两种方式:
1.module.exports.xxx = 模块里面的某个接口
2.exports.xxx = 模块里面的某个接口
这两者的区别:
1.
exports是module.exports的一个引用
2.require需要返回的是module.exports,而不是exports,如果此时exports仍为module.exprots的引用则没有关系,如果不是则会报错。
所谓的引用是指指向同一个内存地址
eg. var personA = {Name:'TOM'};
var personB = personA;
此时personB是personA的引用
如果此时将personB的属性Name 修改personA同样也会修改因为他们指向同一个内存地址,若此时将personB = {Name:'Candy'},则此时personA不会被改变,因为已将personB重新赋值,personB不再是personA的引用了,这里可以解释上的exports和module.exports的关系。
var market = require('./Market.js')//.代表当前目录下
这段代码表达用require加载Market.js这个模块,返回了module.exports暴露出来的所有方法到market这个对象上
ES5用require, ES6用import
注意导入和导出的写法必须配套,不能混用!
7.
关于样式
(1)普通内联样式:{{}},第一层{}是表达式,第二层{}是js对象;
<View style={{fontSize:40, width:80,}}> </View>
(2)调用样式表:{样式类.属性}
<View style={styles.container}></View>
(3)样式表和内联样式共存:{[]}
<View style={[styles.container, {fontSize:40, width:80}]}>
(4)多个样式表:{[样式类1, 样式类2]}
<View style={[styles.container, styles.color]}>
8.
React进行了虚拟DOM的封装,所有的视图的更新都是虚拟DOM做了一个校验(diff)后最小更新。为什么这么做,因为现在机器的内存已经足以支撑这样视图UI的diff计算,用内存计算换取UI渲染效率。
9.AppRegistry是JS运行所有React Native应用的入口
AppRegistry模块则是用来告知React Native哪一个组件被注册为整个应用的根容器。
使用AppRegistry.registerComponent进行注册自己,然后原生系统就可以进行加载运行bundle文件包,最后就会可以调用AppRegistry.runApplication进行运行起来应用。当一个视图被摧毁的时候,为了结束应用需要调用AppRegistry.unmountApplictionComponentAtRootTag方法。
AppRegistry.registerComponent('Allen', () => Allen);
这段代码中系统自动创建了一个组件叫做Allen 然后这个组件会被Appregistry 这个API的注册函数显示出来。
带引号的这个“Allen”代表的是这个APP的名称( init 时创建的项目名) ,后面的Allen代表的是所要显示的组件名称(class名称), 那么我们就可以在创建一个xxx.js文件 (在react-native中一个文件也是一个组件) 那么我们就可以将这个组件注册到这里来 则可以显示这个js所呈现的内容
9.
箭头函数实际上是在这里定义了一个临时的函数,箭头函数的箭头=>之前是一个空括号、单个的参数名、或用括号括起的多个参数名,而箭头之后可以是一个表达式(作为函数的返回值),或者是用花括号括起的函数体(需要自行通过return来返回值,否则返回的是undefined)。
不论是bind还是箭头函数,每次被执行都返回的是一个新的函数引用,因此如果你还需要函数的引用去做一些别的事情(譬如卸载监听器),那么你必须自己保存这个引用
10.
在ES6中,如果在自定义的函数里使用了this关键字,则需要对其进行“绑定”操作,否则this的指向不对
this.fetchData = this.fetchData.bind(this);
11.
<Image source={{uri:'http://xxxxxxxx'}} style={{width: 90, height: 90}}/>
这里需要注意两点:
1)、图片地址关键字是 uri 不是 url,
2)、
加载网络图片需要指定图片的size,否则无法显示,我们了解到,在浏览器中,如果你不给图片指定尺寸,那么浏览器会首先渲染一个0x0大小的元素占位,然后下载图片,在下载完成后再基于正确的尺寸来渲染图片。这样做的最大问题是UI会在图片加载的过程中上下跳动,使得用户体验非常糟糕。
3).
原生资源指的我们开发android的时候再res目录下的drawable或者mipmap目录
默认加载的是drawable下的图片资源,如果想加载mipmap中的资源
需要在资源前面加目录名mipmap/
子view会默认根据父view来absolute,这里有个技巧,如果想让子view实现100%的效果可以设置left:0 ,right :0,同理height可以用top:0,bottom:0。
使用text的numberOfLines可以实现文本截取省略号,即css的text-overflow属性。
-------------------
12.
setInterval、setTimeout
每次调用setState时, 都会重新执行 render 方法重新渲染。
13.
FlatList组件用于显示一个垂直的滚动列表,其中的元素之间结构近似而仅数据不同。
FlatList更适于长列表数据,且元素个数可以增删。和ScrollView不同的是,FlatList并不立即渲染所有元素,而是优先渲染屏幕上可见的元素。
FlatList组件必须的两个属性是data和renderItem。
data是列表的数据源,而renderItem则从数据源中逐个解析数据,然后返回一个设定好格式的组件来渲染。
如果要渲染的是一组需要分组的数据,也许还带有分组标签的,那么SectionList将是个不错的选择
ScrollView是一个通用的可滚动的容器,你可以在其中放入多个组件和视图,而且这些组件并不需要是同类型的。ScrollView 不仅可以垂直滚动,还能水平滚动(通过horizontal属性来设置)。
ScrollView适合用来显示数量不多的滚动元素
14.
需要注意的是,安全机制与网页环境有所不同:在应用中你可以访问任何网站,没有跨域的限制。
15.
Promise是一个构造函数,自己身上有all、reject、resolve这几个眼熟的方法,原型上有then、catch等同样很眼熟的方法。
Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。强大之处:处理 多层回调。
getNumber()
.then(function(data){
console.log('resolved');
console.log(data);
console.log(somedata); //此处的somedata未定义
})
.catch(function(reason){
console.log('rejected');
console.log(reason);
});
catch效果和写在then的第二个参数里面一样。不过它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。
用Promise.all来执行,all接收一个数组参数
all方法的效果实际上是「谁跑的慢,以谁为准执行回调」,那么相对的就有另一个方法「谁跑的快,以谁为准执行回调」,这就是race方法
16.
注意在rn版本0.46版本的时候添加了ImageBackground控件,在0.46版本以后使用Image的时候不能在嵌套使用,使用会报错,ImageBackground就是解决这个问题的。ImageBackground的使用和Image一样,只不过可以嵌套其他组件了。
如果要在<Image>组件里面嵌套布局,后面需要用<ImageBackground>组件替代(现在在<Image>里面嵌套子元素,会报警告),目的是为了解决前面使用<Image>组件时,必须明确赋值图片的大小(width和height),<ImageBackground>可以根据图片的实际大小计算整个容器的大小
return (
<ImageBackground
source={require('./image/icon.png')}
style={{flex:1,width:200, height:100,
resizeMode: Image.resizeMode.stretch}}>
<Text style={{marginTop: 60, backgroundColor: 'red'}}>
下面是背景图片
</Text>
</ImageBackground>
);
17.
require语法也可以用来静态地加载你项目中的声音、视频或者文档文件。大多数常见文件类型都支持,包括.mp3, .wav, .mp4, .mov, .htm 和 .pdf等
18.
• requestAnimationFrame(): 用来执行在一段时间内控制视图动画的代码
• setImmediate/setTimeout/setInterval(): 在稍后执行代码。注意这有可能会延迟当前正在进行的动画。
• runAfterInteractions(): 在稍后执行代码,不会延迟当前进行的动画。
19.
有些时候你必须要重新编译应用才能使修改生效:
• 增加了新的资源(比如给 iOS 的Images.xcassets或是 Andorid 的res/drawable文件夹添加了图片)
• 更改了任何的原生代码(objective-c/swift/java)
20.
你可以使用console.error()来手动触发红屏错误,console.warn()来手动触发黄屏警告
21.
在开发者菜单中选择"Debug JS Remotely"选项,即可以开始在 Chrome 中调试 JavaScript 代码。点击这个选项的同时会自动打开调试页面 http://localhost:8081/debugger-ui.(如果地址栏打开的是 ip 地址,则请自行改为 localhost)
Chrome 中并不能直接看到 App 的用户界面,而只能提供 console 的输出,以及在 sources 项中断点调试 js 脚本
22.
在终端中运行如下命令来查看控制台的日志
react-native log-android
23.
开发服务器(官方名称 metro,但我们更常称之为 Packager)
24.
生成一个签名密钥
$ keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
设置 gradle 变量
1. 把my-release-key.keystore文件放到你工程中的android/app文件夹下。
2. 编辑~/.gradle/gradle.properties(全局配置,对所有项目有效)或是项目目录/android/gradle.properties(项目配置,只对所在项目有效)。如果没有gradle.properties文件你就自己创建一个,添加如下的代码(注意把其中的****替换为相应密码)
把签名配置加入到项目的 gradle 配置中
android/app/build.gradle
生成发行 APK 包
$ cd android $
$ ./gradlew assembleRelease
请确保 gradle.properties 中没有包含_org.gradle.configureondemand=true_,否则会跳过 js 打包的步骤,导致最终生成的 apk 是一个无法运行的空壳。
生成的 APK 文件位于android/app/build/outputs/apk/release/app-release.apk
测试应用的发行版本
$ react-native run-android --variant=release
针对不同的 CPU 架构生成 APK 以减小 APK 文件的大小
def enableSeparateBuildPerCPUArchitecture = true
universalApk true // 额外生成一个适用不同CPU架构的通用APK
def enableProguardInReleaseBuilds = true//
//Proguard 是一个 Java 字节码混淆压缩工具,它可以移除掉 React Native Java(和它的依赖库中)中没有被使用到的部分,最终有效的减少 APK 的大小。
25.移除不需要的权限
android/app/src/main/AndroidManifest.xml
android/app/src/release/AndroidManifest.xml
26.把 React Native 组件集成到 Android 应用中有如下几个主要步骤:
1. 配置好 React Native 依赖和项目结构。
2. 创建 js 文件,编写 React Native 组件的 js 代码。
3. 在应用中添加一个RCTRootView。这个RCTRootView正是用来承载你的 React Native 组件的容器。
4. 启动 React Native 的 Packager 服务,运行应用。
5. 验证这部分组件是否正常工作。
27.render中必须有标签,标签中才能包含构造子标签的函数。
#####精彩稍后继续,尽请点赞打赏.