文章概述
本篇文章是React学习笔记。
创建react项目
创建新的react项目
这种方式创建的react项目,已经为你配置好了Babel和webpack,你可以零配置使用,这种方式灵活性不好,所有的配置都自动被配置好了。
需要Node >= 6, 按如下步骤:
1 | //1.安装创建项目插件: |
在已有项目中添加react
初始化config.json文件,安装react和react-dom库即可支持react开发,为了更好的开发效率,建议使用webpack配置babel-loader来支持ES6和JSX语法;
默认安装最新版,注意react相关库应保持版本一致;
- 通过Yarn安装React:
1 | yarn init |
- 通过npm安装React:
1 | npm init |
JSX
JSX是对JavaScript语法的扩展,具有JavaScrip的全部能力,JSX可以生成React“元素”。
JSX概述
JSX可以直接使用html的写法,如下就可以看做一个JSX表达式:
1 | const element = <h1>Hello, world!</h1>; |
表达式写法规则
- jsx表达式写在{}里,可以用花括号{}把任意的JavaScript表达式嵌入到JSX中。
- JSX本身其实也是一种表达式,可以在if语句或者是for循环中使用JSX:
1 | function getGreeting(user) { |
- 组件命名:大写字母开头。
1 | const SpecificStory = ...; |
- 属性名:使用camelCase小驼峰命名来定义组件属性的名称,包括html模板里的标签属性名。
- JSX中用点表示法来引用组件:
1 | // 引用MyComponents模块中的DatePicker组件 |
属性值
概念:标签内部设置的成员值;
属性赋值方式
- 使用引号来定义以字符串为值的属性:
1 | const element = <div tabIndex="0"></div>; |
- 使用花括号{}来定义以JavaScript表达式为值的属性:
1 | const element = <img src={user.avatarUrl}></img>; |
1 | //使用...作为扩展操作符来传递属性对象: |
模板样式
jsx语法定义的html模板用括号()括起来,可以防止编辑工具自动在行尾加分号;
给标签元素设置样式,有两种方式:
- 通过给标签的style属性指定一个样式对象;
- 使用css样式文件集中管理样式;
指定样式对象
给jsx语法定义的html模板内的标签,添加style属性,属性值设置为一个样式对象:
1 | let x_style = { |
特点
- 允许样式值带逻辑语句;
- 样式对象属性名是用驼峰式命名,没有使用css里的中横杠;
CSS样式文件
- 定义样式文件x.css:
1 | #jsxId { |
- jsx文件中导入样式文件使用:
1 | import './x.css'; |
JSX语法
变量使用
1 | let name='jason'; |
条件表达式
if语句
if不能嵌入在{}里面
1 | if (bool) { |
与运算符
&&
概述
在 JavaScript 中,true && expression 总是返回 expression,而 false && expression 总是返回 false。
使用
可以通过用花括号{}包裹代码在 JSX 中嵌入‘与运算’表达式。
示例:
1 | {1 > 0 && <h2>hello</h2>} |
三目运算符
表达式
1 | condition ? true : false |
使用示例
1 | let flag = false; |
循环方法
通过map方法遍历数组生成列表:
1 | let names = ['Jason', 'Lily', 'Simon']; |
元素
概念
元素是构成React应用的最小单位,用来描述你在屏幕上看到的内容。
1 | // 定义一个元素 |
与浏览器的DOM元素不同,React中的元素事实上是普通的对象,React DOM可以确保 浏览器DOM的数据内容与React元素保持一致。
注意:元素事实上只是构成组件的一个部分。
根节点
用React开发应用时一般只会定义一个根节点。但如果你是在一个已有的项目当中引入 React的话,你可能会需要在不同的部分单独定义React 根节点。
在react项目的public/index.html中,id=”root”的div作为项目的根节点,根节点的内容由React Dom来管理。1
<div id="root"></div>
元素的渲染
一般通过src/index.js中的ReactDOM.render()方法将React元素渲染到根节点。
如下:将定义好的App渲染到根节点。
1 | ReactDOM.render( |
组件
概念
组件从概念上看就像是函数,它可以接收任意的输入值(称之为“props”),并返回一个需要在页面上展示的React元素。
组件的定义
- 类定义的组件名或者定义组件的函数名,必须以大写字母开头。
函数定义组件
使用JavaScript函数定义一个组件:
1 | function Welcome(props) { |
该函数是一个有效的React组件,它接收一个单一的“props”对象并返回了一个React元素。
ES6类定义组件
1 | // 继承自Component组件类 |
React 组件也可以通过数组的形式返回多个元素:
1 | render() { |
组件的渲染
元素也是一个组件,自定义组件通过render()方法返回渲染出的界面。
阻止组件渲染
阻止组件渲染,让View、组件或组件的render方法返回null,而不是它的渲染结果即可实现。
示例:
1 | // 组件函数 |
注意:
阻止组件的渲染,并不会影响该组件生命周期方法的回调。
例如,componentWillUpdate 和 componentDidUpdate 依然可以被调用。
props
组件的属性
概念
- props是一种从父级向子级传递数据的方法;
- 使用时组件内部只能读父组件的属性值,组件不能改变props;
属性的种类
继承父组件属性
1 | class MyComponent extends React.Component{ |
默认属性
create-react-app创建的项目支持这种写法1
2
3
4
5// 定义默认属性
static defaultProps={
name:'张三(默认名字)',
age:20
}
props类型检查
主要对props的属性进行类型检查。
注意: React.PropTypes 自 React v15.5 起已弃用。请使用 prop-types 库代替。
1 | // 命令安装prop-types库到node_modules内,并添加到package.json中 |
使用方式
给props成员设置类型约束
1 | import PropTypes from 'prop-types'; |
常见约束类型
约束类型都在PropTypes模块中
1 | var ReactPropTypes = { |
常用类型约束写法
1 | import PropTypes from 'prop-types'; |
静态类型检查
- 像Flow和TypeScript这样的静态类型检查器可以在运行代码之前识别某些类型的问题。
- 对于大的项目建议使用Flow或者TypeScript来替代PropTypes。
state
状态;
概念
- 状态与属性十分相似,但是状态是私有的,完全受控于当前组件。
- 对于组件,state是可变的,一般通过改变state来刷新组件。
- State 只在交互的时候使用,即随时间变化的数据。
state的定义
1 | // 方法1:默认静态成员声明; |
1 | // 方法2:构造器中定义; |
1 | // 方法3:构造器中定义; |
改变state
1 | // 一般写法 |
1 | // 接受一个函数,参数1:先前的状态;参数2:props |
state异步改变
在react中设置state后,state的更新时异步执行的,如果想state更新后立即执行某些逻辑,可以为setState方法添加第二个参数,setState的第二个参数使用一个匿名函数作为异步跟新后的处理函数;
示例:
1 | this.setState({ |
事件的处理
- 事件名称首字母小写的驼峰式命名法;
- 事件需要一个处理函数/方法(类中);
阻止链接打开页面
注:# 表示无效链接
- 传统的HTML中:通过处理函数返回false来阻止打开默认页面;
1 | <a href="https://www.baidu.com/" onclick="console.log('The link was clicked.'); return false"> |
- react中通过调用e.preventDefault()方法来阻止打开默认页面;
1 | render() { |
监听事件的绑定
- 在ES6中,方法不再自动绑定this,需要手动bind,并且每次bind都会返回一个新的引用。
- 使用箭头函数或者构造器绑定的方法可以为事件方法绑定this;
在构造器中绑定this
1 | class Parent extends React.Component { |
箭头函数绑定this
使用箭头函数在定义的时候就绑定好了this指针:即this.event=event;
方式一:在方法调用的地方使用箭头函数:
1 | class Parent extends React.Component { |
方式二:在方法声明时,使用箭头函数声明,调用时用this直接调用:
1 | //定义方法时:使用箭头函数返回箭头函数的方式定义; |
生命周期钩子
生命周期方法调用图
react声明周期图如下:
触发生命周期方法调用示例
代码如下:
1 | class MyComponent extends React.Component { |
组件间的组合关系
纯组件嵌套
直接嵌套组件使用:
1 | class Child extends React.Component { |
子代容器组件
- 组件中利用props(props.children)传递子内容或标签内容;
- 组件开始和结束标签的JSX 表达式中,标记之间的内容作为子代(子内容)。使用{props.children}作为子代内容的占位。
示例
1 | class A extends React.Component { |
子代内容类型
- 字符串常量:
1 | <MyComponent>Hello world!</MyComponent> |
- JSX组件标签
1 | <MyContainer> |
- JavaScript 表达式
通常情况下,插入 JSX 中的 JavsScript 表达式将被认作字符串、React 元素或这些内容的列表。
1 | // 以下两个等价 |
1 | // 渲染任意长度的 JSX 表达式的列表很有用 |
- 函数
利用props.children 来获得传递的子代:
1 | function Repeat(props) { |
- 布尔值、Null 和 Undefined 被忽略
- false、null、undefined 和 true 都是有效的子代,但它们不会直接被渲染。
下面的表达式是等价的:
1 | <div /> |
- 如果让false、null、undefined和true输出,需要强制转成字符串:
1
{String(myVariable)}.
组件间通信
父组件通信子组件
父组件通过设置属性传递给子组件,子组件通过props获取父组件传递的属性;
子组件通信父组件
通过在父组件内定义回调函数,在子组件里利用props调用父组件的回调函数即可;
1 | class ChildA extends React.Component { |
兄弟组件通信
通过状态提升进行兄弟组件通信;
状态提升
子组件A通讯传给父组件,改变父组件的state,父组件再讲state传给兄弟组件;(这种方式为了在兄弟组件中传递数据,把数据放到了父组件里,这种方式叫状态提升)
示例
1 | class ChildA extends React.Component { |
原生APP交互
原生APP调用React
原生APP调用React中的方法时,React的方法需要提升到window才能被正常调用,因为react只是js模板语法库,不能像原生js那样使用;
具体实现如下:
- 原生应用中调用js方法;
1 | //android WebView调用react的方法并传递参数 |
- react中定义方法由原生调用;
1 | //react中方法被原生调用 |