React学习笔记基础
Posted 做枚温婉的妹纸吧哈哈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React学习笔记基础相关的知识,希望对你有一定的参考价值。
文章目录
最近又看了一遍react的文档,对上面的一些关键信息记录了一些笔记。主要是一些基础~
jsx语法
在JS里写html结构。html可以存成变量,中书写js表达式。多个并列的html要在外面包一层(),防止自动插入分号:
const element = (
<div>
<h1>hello, user.name</h1>
<p>content</p>
<img className=class src=imglink />;
</div>
);
属性为驼峰式,属性值用JS表达式时不要加引号。自闭合标签要写 />。
JSX本身也是一种表达式,会被编译成JS对象。Babel 转译器会把 JSX 转换成一个名为 React.createElement() 的方法调用:
涉及的基本库有 react
和react-dom
。作用分别如下:
react
基本库,比如下面的方法:
React.createClass(
render: function ()
, … //其他选项
);
是创建组件的方法之一。
react-dom
ReactDom.render(组件或节点变量, 挂载dom);
渲染前所有内容转换为字符串,可以防止XXS攻击。ReactDOM 首先会比较元素内容先后的不同,而在渲染过程中只会更新改变了的部分。即便重新调用ReactDom.render进行渲染。
组件
组件可以是一个函数:
function Welcome(props)
return <h1>Hello, props.name</h1>;
函数接收一个props对象来接收调用组件时传入的属性。
也可以采用ES6类:
class Welcome extends React.Component
constructor(props)
super(props);
,
render()
return <h1>Hello, this.props.name</h1>;
或者使用var App = React.createClass()
.
this.props
外部将数据通过属性传递给组件,组件用props
来接收。
组件内部 可通过this.props.children
访问组件的子节点。如果当前组件没有子节点,它就是 undefined
;如果有一个子节点,数据类型是object
;如果有多个子节点,数据类型就是array
,因此可以用React.Children.map
来遍历子节点而无需关心它的类型到底是什么。
this.refs.refName
组件可用它来获取内部的真实DOM节点。组件的ref
接收字符串或者回调为值,如果是字符串,则内部通过this.refs.propName
来获取传入的节点;如果是回调,则回调的参数是DOM节点,可以在回调函数内部将节点赋值给this.XXX
。推荐回调函数的方式。官网上有这样一段解释:
this.state
组件内部的状态机,触发改变后更新UI。与props
的区别是:props
是父组件传入且不在组件内部更改,是外部控制的;而state
是组件局部创建、控制和修改的。
-
创建
方式分下面的情况:
(1)当使用React.createClass()
创建组件时:
在getInitialState: function() return state1: XXX
中进行初始化;
(2)当使用ES6的类语法创建组件时:
在construtor
中声明this.state =
来初始化状态。 -
更新
通过this.setState(state1: XXX)
来更新state
。该方法接收一个对象为参数,或者一个函数,如:
this.setState((prevState, props) => (state1: XXX));
-
调用
通过 this.state.state1来引用。 -
何时使用state
从上面说的第三点来看,如果需要根据state
或者props
计算而得到的数据,最好是在render
中进行,不要把计算的结果放到state
里.
事件监听
对元素进行事件监听的时候,回调函数内部不会自动获得指向组件的this
(指向元素的?),此时需要通过bind
来绑定,this.handler.bind(this)
。通过这种方式,事件处理函数handler
自动获得event
对象作为最后一个参数。
生命周期
组件首次创建时,以下方法依次被调用:
- constructor
- componentWillMount
- render
- componentDidMount
PS:如果是在服务端渲染,则没有componentDidMount
这一步。
constructor(props, context)
在此处可以初始化state
,声明组件内部的一些变量等(通过this.XXX = XXX
)。
如果是用ES6的语法创建的对象,需要在该函数内调用super(props, context)
来进行继承。
componentWillMount()
组件挂载之前调用一次,在render
之前。该函数内可以进行setState
,并且此时不会导致额外调用一次render
.
render()
该方法是创建了虚拟节点,用来表示组件的输出。该方法需满足以下条件:
- 通过
this.state
和this.props
来获取数据 - 可返回
null
、false
或任何react组件 - 只能返回一个顶级组件
- 不能改变组件的状态
- 不能修改DOM的输出
componentDidMount()
在组件挂载完成后调用一次,此时子组件也挂载完毕。render
之后调用,此时可以访问DOM节点,可以使用refs
。该方法在服务端不会被调用,在该方法调用过程中,已经渲染出真实的DOM节点。可通过ReactDOM.findDOMNode(this)
访问真实节点。
更新组件时以下函数顺次调用:
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
它们都不会在组件首次渲染的时候调用。
componentWillReceiveProps(nextProps)
当props
有更新的时候调用。即便是子组件首次渲染也不会调用(虽然从父组件接收了数据)。只有在props
有更新的时候调用。
shouldComponentUpdate(nextProps, nextState)
返回一个布尔值,如果确定当props
或者state
有更新的时候不需要重新渲染,则不会调用render
及其之后的方法。
componentWillUpdate(nextProps, nextState)
在组件接收到了新的props
或者state
即将进行重新渲染前调用。在该方法中不要再去更改props
和 state
。
componentDidUpdate(prevProps, prevState)
组件重新渲染后被调用,可访问DOM.
销毁时调用下面的方法:
componentWillUnmount
组件从DOM中移除的时候调用。通常在componentDidMount
中绑定的事件等在这里删除。
父组件、子组件都会走一遍上面的流程。
状态提升和自上而下的数据流
如果两个组件需要共享状态,应当将其提升到离他们最近的一个父组件中,保持数据来源的单一性。采用自上而下的数据流。
数据从父组件自顶向下传递给子组件,子组件通过props来接收;
当需要更改父组件的数据时,可以在子组件中再加一个属性接收父组件的一个方法(该方法需要bind
父组件的this
),在该方法中设置更改状态的方法(this.setState
)。然后子组件中监听事件并在回调中调用该方法。
如果某些数据可以由props
或者state
计算所得,那么很有可能不应该放在state
中。
关于ref
ref
属性接收一个回调函数,该回调在加载和卸载的时候会立即调用,会在componentDidMount
和componentDidUpdate
这些生命周期之前执行。加载时接收当前的DOM元素为参数(当用在class
声明的组件上时,传入组件实例),可以在该回调中进行这样的赋值:this.XXX = param
,以便在react组件中使用;卸载时传入null
。
注意:ref
属性传入字符串之后通过this.refs.refName
来调用属于遗留问题,不推荐使用。
表单受控组件和非受控组件
受控组件
表单节点的value
属性接收某个state
值,之后在表单控件监听事件回调中setState
保证组件的state
与表单值是一致的。通常可用于即时的表单校验。
参考文档里有这么一段解释:
This flow kind of ‘pushes’ the value changes to the form component, so the Form component always has the current value of the input, without needing to ask for it explicitly. This means your data (state) and UI (inputs) are always in sync. The state gives the value to the input, and the input asks the Form to change the current value. This also means that the form component can respond to input changes immediately.
非受控组件
不采用上面的方式,而是通过ref
,将表单节点的值同步给组件的某个属性(参考ref
的使用)。此时可通过给表单节点的defaultValue
而非value
属性传入初始值。
常用于简单的情况,仅仅需要获取表单值,而无需其他的操作。
对比两者:
参考:Controlled and uncontrolled form inputs in React don’t have to be complicated
context
官网上有这么一段解释:
In some cases, you want to pass data through the component tree without having to pass the props down manually at every level. You can do this directly in React with the powerful “context” API.
简单说来就是context
相当于是一个全局对象,组件树上的组件都要访问的属性,可以放到这个全局对象里,之后就可以通过this.context.propName
来拿到了,而不是通过逐层的props
传递。
子组件:需定义contextTypes
,声明这个数据我要通过this.context.XXX
拿到,同时规定了其类型。例如:
ChildComponet.contextTypes =
store: PropTypes.object.isRequired
;
父组件:class
内添加getChildContext()
方法,返回一个对象,对象里为要往下传递的属性:
getChildContext()
return
store: this.props.store or this.state.XXX
getChildContext
函数将会在每次state
或者props
改变时调用。为了更新context
中的数据,使用this.setState
触发本地状态的更新。这将触发一个新的context
并且数据的改变可以被子元素收到。
同时设置该属性类型:
ParentComponent.childContextTypes =
store: PropTypes.object.isRequired
;
这样可以避免深层嵌套的子组件想要拿到外部数据时逐层传递的麻烦。
这样,该父组件的所有子孙组件内部都能通过this.context.store
拿到store
对象。这也是Provider
组件的实现原理。
PS: 不太建议用context
,可能会被废弃。
Portals
portals
提供了将子节点渲染到其他dom
节点的方式。平常只能将组建的子节点放置离它最近的父节点,但通过portals
则可以放置到别的节点。使用方式为:
render()
return ReactDom.createPortal(this.props.children, someDOM);
其他
html
标签中的class
要写成className
, for
要写成htmlFor
。因为这些在react中的保留字。
此外,style要这样写:
style=opacity: this.state.opacity
外层大括号表示这是JS语法,内层表示这是一个对象。
JSX允许在中嵌入任何表达式。
子组件通过props
接收一个函数,如果该函数需要使用父组件的this
,那么传入的这个函数应该通过bind
来绑定父组件的this
。
&&
之前的必须是布尔值,数字0
仍然会判定为true
, &&`后面的仍然会执行。
下一篇对react更深入的知识进行介绍,暂定是diff 算法吧。
以上是关于React学习笔记基础的主要内容,如果未能解决你的问题,请参考以下文章