开发环境安装及相关代码库配置见官方文档
Windows系统搭建ReactNative开发环境
创建RN项目react-nativeinitProjectName--version0.61.3//根据指定版本号创建RN项目
添加指定版本依赖库
yarnaddlibName@version_numberi//添加指定版本号依赖库,需安装yarn环境
或者
npminstall--savelibName@version_number
开启DeveloperMenu模拟器:CommandD
真机:摇一摇
远端(浏览器)代码调试DeveloperMenu
选择Debug
CommandOptionI
打开浏览器开发者工具
打开RCTWebSocketExecutor.m
,将localhost
修改为本机电脑IP,再开启远端调试
ECMAScript6基础1.支持
let
和const
let
:在代码块内定义局部作用域的变量,支持与全局变量重名,需要在使用前先定义const
:定义常量,需要在使用之前先定义并同时赋值
可以使用class
关键字定义类,类似于其他面向对象语言。
letmethodName='getPoint';classPoint{//constructor为构造方法constructor(x,y){//this指代类实例对象this.x=x;this.y=y;}//使用static声明类属性,只可以通过类名访问,不可以通过实例访问staticgreeting='hello'//在方法前加static关键字,表示此方法是类方法,只能通过类名调用,类似OC中的staticclassMethod(){//类方法中的this指代类本身returnthis.greeting;}//定义类的方法时,不需要加function关键字toString(){return'('this.x','this.y')';}//使用变量当函数名或属性名,需要用[]将变量名包起来[methodName](){//dosth.}}//类的实质是函数typeofPoint//"function"//类实质上等价于其构造函数Point===Point.prototype.constructor//true//使用new关键字来创建实例letp=newPoint();//实例的函数实际就是其原型的函数p.constructor=Point.prototype.constructor//true//使用Object.assign来一次性注入多个函数Object.assign(Point.prototype,{toString(){},toValue(){}});
类的继承
//使用extends关键字来表明继承关系classColorPointextendsPoint{//子类的constructor方法constructor(x,y,color){super(x,y);//必须要调用父类的constructor(x,y)。这里super是方法,作为方法时只能在子类的构造函数中使用this.color=color;//在调用父类的constructor之后才可以使用this}toString(){returnthis.color''super.toString();//调用父类的toString()。这里super指代的是父类的原型对象}}//判断一个类是否继承自另一个类Object.getPrototypeOf(ColorPoint)===Point//true
3.模块化(module)每一个模块都有单独的作用域,模块之间的相互调用通过export
来规定模块对外暴露的接口,通过import
来引用其他模块提供的接口。模块化同时提供了命名空间,防止函数的命名冲突。
exportvarname='Rainbow';exportfunctionsomeFunc(argu){//Dosth.}
importimport{module1,module2,...}from'fileRelativePath';//module.jsimport{name}from'Module';
4.箭头函数普通匿名函数定义的缩写方式,形如:
//如果仅有一个入参,可以省略argus的圆括号//执行语句如果只有一句,可以省略花括号,该语句的返回值会被返回。(argus)=>{//operations//returnvalues}
箭头函数内部的this
总是指向定义时所在的对象。
functionfoo(color='red',height=50){//Dosth.}
6.动态字符串Chrome貌似不支持
varfirstName='Bill',secondName='Gates';varstr=`Mynameis${firstName}${secondName}.`;
7.解构赋值[a,b,c]=[1,2,3,4];//a=1,b=2,c=3[a,,,d]=[1,2,3,4];//a=1,d=4//提供默认值[a=3,b=5]=[1];//a=1,b=5[a=3,b=5]=[b,a];//a=5,b=3[a=3,b=a]=[1];//a=1,b=1
对象解构赋值。对象的解构必须保证变量名与对象的属性名相同。
conststudent={name:'XiaoMing',age:8,}//实际是const{name:name,age:age}=student的缩写const{name,age}=student;//name='XiaoMing',age=18
8.扩展运算符符号:...
。作用:将数组按顺序展开,或者将对象按键值对进行展开。
constgroup1=[2,3];constgroup2=[1,...group1,4,5];//[1,2,3,4,5]constgroup3=[...group1];//[2,3]
ECMAScript2018
中延展操作符增加了对对象的支持
varobj1={x:1,y:2};varobj2={x:5,z:6};varobj3={...obj1};//{x:1,y:2}varobj4={...obj1,...obj2};//{x:5,y:2,z:6}varparams={x:1,y:2,z:3};var{z,...other}=params;//相当于定义了一个other变量,且other={x:1,y:2}
9.对象属性简写ES6
直接使用定义的变量作为对象的属性而无需按照键值对的方式去书写定义对象
varname='xiaoming',age=10,height=100;varstudent={name,age,height};
10.Promise用于异步回调。
functionmultiply(input){returnnewPromise(function(resolve,reject){console.log('calculating'input'x'input'...');setTimeout(resolve,500,input*input);});}functionadd(input){returnnewPromise(function(resolve,reject){console.log('calculating'input''input'...');setTimeout(resolve,500,inputinput);});}varp=newPromise(function(resolve,reject){console.log('startnewPromise...');resolve(123);});p.then(multiply).then(add).then(multiply).then(add).then(function(result){console.log('Gotvalue:'result);});
ECMA
新特性APIasync
和await
async
:异步执行函数,默认返回一个Promise
对象。await
:等待指定函数执行结束后再执行后续代码
Object.values()
返回object自身所有属性的值,不包括继承得到的属性
Object.entries()
for(const[key,value]ofObject.entries(obj)){console.log('key:'key',value:'value);}
React基础JSX
JSX
是一个JavaScript
的语法扩展,可以定义简洁且包含属性的树状结构语法
React
可以渲染HTML标签或React组件。渲染HTML标签,需在JSX里使用小写字母开头的标签名。
varmyDivElement=<divclassName='foo'/div>;React.render(myDivElement,document.root);
渲染React组件,需创建大写字母开头的本地变量
varmyComponent=<MyComponentsomeProps={true}/>;React.render(myElement,document.body);
组件的属性(props)可以通过this.props.p
的方式获取组件的任意属性,对象的属性也可以任意定义。
遍历对象的所有属性:this.props.children
:返回组件对象的所有属性。可以通过React.Children.map()
或React.Children.forEach()
来遍历子节点。
PropTypes:添加属性传值要求
defaultProps:为属性添加默认值
classMyTitleextendsReact.Component{staticPropTypes={title:PropTypes.string.isRequired,//要求传入字符串,且不可为空//otherrequirements};staticdefaultProps={shortName='MyTitle';};}
组件的状态statestate
是组件私有的,可以通过state={}
方式来初始化,通过this.setState()
来改变。当state
更新后,组件会重新渲染。
render()
方法依赖于组件的props
和state
。框架会确保渲染出来的UI界面和组件的属性和状态保持一致。
//此初始化只会在组件的生命周期中执行一次constructor(props){super(props);this.state={name:'小明';};}
更新state通过this.setState()
来更新状态。调用该方法后,组件会重新渲染相关UI。
this.setState({favourite:!this.state.favourite});
组件的生命周期组件生命周期的三种状态:
Mounting
:加载中,对应componentDidMount()
Updating
:更新中,对应componentDidUpdate()
Unmounting
:移除中,对应componentDidUnmount()
componentDidMount
:在组件被装配后立即调用,通常在该方法中执行一些初始化相关操作,例如:网络请求。如果在此方法中修改组件的状态,会触发重新渲染。但此时组件并未被展示,所以用户不会看到中间中台shouldComponentUpdate(nextProps,nextState)
:针对指定属性或状态,询问是否需要更新componentDidUpdate
:组件更新后的通知回调componentDidUnmount
:组件被移除后的回调,在该方法中执行清理相关操作
- FunctionComponent:通过函数创建组件,在函数的结尾处返回一个组件。函数组件内部无法添加状态、不能提供组件的生命周期方法回调,属于一种无状态的组件(通过其他手段也可以实现状态功能)。可以通过函数参数传入创建组件所需的参数,直接在函数内部使用。
- ClassComponent:通过定义
class
创建组件,通过render()
方法渲染组件内容。此方式相当于定义新类型,在内部可以提供属性、状态等相关参数,同时也可以实现组件生命周期相关方法。实际使用组件时的代码书写格式与函数调用完全一致,但是相关的参数需要在render()
方法中额外进行解构获取。
关于二者更多的差别,参考:
精读《FunctionComponent入门》
精读《FunctionVSClass组件》
JavaScript中的this
指向并不清晰。在类组件内部定义的函数中使用this
,实际调用该函数时,可能会出现this
丢失而并不指向该组件类对象,而是指向全局window对象的问题。
因此,需要将函数中使用到的this
绑定到该类对象,具体实现方法有如下几种:
在使用到该类函数的地方,通过.bind{this}
来将该函数内部用到的this
绑定到该组件对象
<Buttontype="primary"onClick={this.onSearch.bind(this)}>搜索</Button>
2.ES7函数绑定语法就是上述方式的语法糖,通过在函数前添加::
来代替在函数后面使用.bind(this)
<Buttontype="primary"onClick={::this.onSearch}>搜索</Button>
3.在构造函数中bind(this)可以在构造函数中将组件内部的方法绑定到该组件的对象
constructor(props){super(props);this.onSearch=this.onSearch.bind(this)//将onSearch方法中的this绑定到这个初始化的对象}
4.使用箭头函数在为组件中的子组件赋值函数时直接通过定义箭头函数来赋值,该箭头函数函数体中的this
会默认绑定到该组件对象。
<Buttontype="primary"onClick={()=>{/*Dosthwiththis*/}>搜索</Button>
5.core-decorators.js在组件内部使用@autobind
修饰符,则该组件内部使用到的this
默认都会绑定到该组件对象
classSearchextendsComponent{@autobindonSearch(){console.log('表单值:',this.field.getValues());this.props.onSearch(this.field.getValues());}render(){const{init}=this.field;return<div><Formdirection="hoz"labelAlign="left"><FormItemlabel="loginID:"><Inputplaceholder="请输入loginID"{...init('loginID')}/></FormItem><Buttontype="primary"onClick={this.onSearch}>搜索</Button></Form></div>}}
使用VSCode断点调试RN项目
- 搜索安装ReactNativeTools插件
- 点击IDE左侧面板的Debug图标,打开调试界面
- 点击左边顶部齿轮按钮,添加启动配置文件,在弹出的环境选择列表中选择
ReactNative
- 选择环境后,根据需要,选择
DebugiOS
或对应的平台 - 点击确定后,会自动添加配置信息,在左侧顶部点击绿色运行按钮即可。
- 添加启动配置文件,选择环境时可能列表中没有
ReactNative
选项。此时可以先到已安装的插件中选择查看该插件,再回到Debug界面添加配置文件,即可出现ReactNative
选项 - 项目可以成功运行,但调试工具启动失败。引发原因可能是RN项目中的库与调试工具的依赖库不匹配。进入RN项目,执行
npminstall--reset-cache
重置缓存重新安装一遍npm依赖库可解决此问题。