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() 的方法调用:
在这里插入图片描述
涉及的基本库有 reactreact-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.statethis.props 来获取数据
  • 可返回nullfalse 或任何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即将进行重新渲染前调用。在该方法中不要再去更改propsstate

componentDidUpdate(prevProps, prevState)

组件重新渲染后被调用,可访问DOM.

销毁时调用下面的方法:

componentWillUnmount

组件从DOM中移除的时候调用。通常在componentDidMount 中绑定的事件等在这里删除。

父组件、子组件都会走一遍上面的流程。

状态提升和自上而下的数据流

如果两个组件需要共享状态,应当将其提升到离他们最近的一个父组件中,保持数据来源的单一性。采用自上而下的数据流。

数据从父组件自顶向下传递给子组件,子组件通过props来接收;

当需要更改父组件的数据时,可以在子组件中再加一个属性接收父组件的一个方法(该方法需要bind父组件的this),在该方法中设置更改状态的方法(this.setState)。然后子组件中监听事件并在回调中调用该方法。

如果某些数据可以由props或者state计算所得,那么很有可能不应该放在state中。

关于ref

ref属性接收一个回调函数,该回调在加载和卸载的时候会立即调用,会在componentDidMountcomponentDidUpdate这些生命周期之前执行。加载时接收当前的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要写成classNamefor要写成htmlFor。因为这些在react中的保留字。
此外,style要这样写:
style={{opacity: this.state.opacity}}
外层大括号表示这是JS语法,内层表示这是一个对象。

JSX允许在{}中嵌入任何表达式。

子组件通过props接收一个函数,如果该函数需要使用父组件的this,那么传入的这个函数应该通过bind 来绑定父组件的this
&&之前的必须是布尔值,数字0仍然会判定为true , &&`后面的仍然会执行。

下一篇对react更深入的知识进行介绍,暂定是diff 算法吧。

参考:React:组件的生命周期

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值