React基础

React元素

使用 JSX 声明一个元素:

const element = <h1>Hello, World!</h1>

JSX 与函数调用的等效性:Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用。

一下两种表示是等效的:

const element = (
	<h1 className="greeting">
  	Hello, world!
  </h1>
);

等效于

const element = React.createElement(
	'h1',
  {className: 'greeting'},
  'Hello, world!'
);

在背后,React.createElement()创建了这样的对象(简化后):

const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

这些对象被称为 ” React 元素 “ 。React 使用它们构建DOM。

元素渲染

假设HTML文件中有一个根节点:

<div id="root"></div>

将React元素渲染到根节点中:

const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));

组件

组件接收一些入参(存储在props中),并返回描述页面展示内容的 React 元素。

组件有两种:函数组件和class组件。

定义一个函数组件:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

定义一个class组件:

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

渲染组件

React 元素可以是DOM标签或用户自定义的组件:

const element = <div />;
const element = <Welcome name="Sara" />;

将组件渲染到页面上:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
	element,
  document.getElementById('root')
);

组合组件

组件可以在其输出中引用其他组件。

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
  	<div>
    	<Welcome name="Sara" />
      <Welcome name="Cahal" />
    </div>
  );
}

ReactDOM.render(
	<App />,
  document.getElementById('root')
);

props 的只读性

所有React组件都不能修改自身的props。

class 组件

React组件除了函数组件还有class组件,最基本的class组件包括构造函数constructor和render()方法。构造函数中必须首先使用props调用父类构造函数super(props),然后可以添加该组件的 statethis.state={}

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
  
  render() {
    return (
    	<div>
      	<h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

class组件的生命周期方法

当组件第一次被渲染到DOM中时,称为挂载mount;DOM中组件被删除时,称为卸载unmount。

可在class组件中声明一些特殊的生命周期方法,在挂载或卸载时执行。

class Clock extends React.Component {
  constructor(props) {}
  
  componentDidMount() {}// 挂载
  componentWillUnmount() {}// 卸载
  
  render() {}
}

使用this.setState()设置组件的state,例如如下的时钟组件:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
  
  componentDidMount() {
    this.timerID = setInterval(
    	() => this.tick(),
      1000
    );
  }
  
  componentWillUnmount() {
    clearInterval(this.timerID);
  }
  
  tick() {
    this.setState({
      date: new Date()
    });
  }
  
  render() {
    return (
    	<div>
      	<h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}</h2>
      </div>
    );
  }
}

ReactDOM.render(
	<Clock />,
  document.getElementById('root')
);

关于state

不要直接修改state,而应该使用setState()

this.state.comment = 'Hello';// 不会重新渲染组件
this.setState({comment: 'Hello'});// OK

构造函数是唯一可以给this.state赋值的地方。

state的更新可能是异步的,因为this.propsthis.state可能会异步更新,所以不要依赖它们更新下一个状态。

例如下面可能无法更新counter

this.setState({
  counter: this.state.counter + this.props.increment,
});

可以让setState()接收一个函数而不是对象,该函数接收上一个state作为第一个参数,props作为第二个参数:

this.setState((state, props) => ({
  counter: state.counter + props.increment
}))

// 使用普通函数
this.setState(function(state, props) {
  return {
    counter: state.counter + props.increment
  };
});

state的更新会被合并,多次setState的单独更新会合并。

state是局部的,可作为 props 向下传递。

<FormattedDate date={this.state.date} />

事件处理

函数组件绑定事件:

function A() {
  function handleClick(e) {
    e.preventDefault();
  }
  
  return (
  	<a href="" onClick={handleClick}>Click</a>
  )
}

class组件绑定事件的几种方式:

一、在构造函数中绑定this

//为了在回调中使用this,需要绑定this
constructor(props) {
  super(props);
  this.state = {isToggleOn: true};
  this.handleClick = this.handleClick.bind(this);
}

handleClick() {
  
}

//在回调中使用this
render() {
  return (
  	<button onClick={this.handleClick}>click</button>
  )
}

二、使用箭头函数作为事件回调函数

handleClick = () => {
  
}

render() {
  return (
  	<button onClick={this.handleClick}>Click</button>
  )
}

三、在回调中使用箭头函数

handleClick() {}

render() {
  return (
  	<button onClick={() => this.handleClick()}>Click</button>
  )
}

事件传参

<button onClick={(e) => this.deleteRow(id, e)}>Delete</button>

需传入的参数放在前,事件对象e可显式地作为第二个参数传递。

条件渲染

使用元素变量进行条件渲染,根据不同条件将不同元素赋值给变量。

let button;
if(...) {
   button = <LogoutButton />
}
else {
  button = <LoginButton />
}

与运算符&&,a && expression,a为true时返回 expression,为false时返回false。

三目运算符:

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
  	<div>
    	{isLoggedIn
      	? <LogoutButton />
      	: <LoginButton />
      }
    </div>
  )
}

在渲染函数中返回null表明该组件不会渲染。

列表渲染

在JSX中使用 {} 插入元素集合渲染一个列表,并给每一项添加一个key。

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) => 
  	<li key={number.toString()}>{number}</li>
  );
  return (
  	<ul>{listItems}</ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
	<NumberList numbers={numbers} />,
  document.getElementById('root')
);

在JSX中嵌入map()

上面使用变量存储元素集合后再在 JSX 中包含该变量,也可以直接嵌入map()

function NumberList(props) {
  const numbers = props.numbers;
  return (
    <ul>
      {numbers.map((number) =>
        <ListItem key={number.toString()}
      						value={number} />
      )}
    </ul>
  );
}

表单

受控组件:使React组件的state成为表单输入元素的唯一数据源,且React组件能控制表单输入元素随用户输入发生的行为,这样的表单输入元素称为受控组件。

在受控组件上指定value的值会阻止用户更改输入,如果指定value值为 null 或 undefined,则用户仍可编辑输入。

//输入已被锁定
<input value="hi" />

//输入可编辑
<input value={null} />

状态提升

当多个组件需要反应相同的数据变化时,将共享状态提升至最近的共同父组件中,即存储在父组件的state中。

这样,父组件可以通过子组件的 props 的方式为子组件提供数据源及修改数据的行为。

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.handlerA = this.handlerA.bind(this);
    ...
    this.state = {
      prop: 'value'
    }
  }
  
  handlerA() {
    this.setState({prop: 'newValue'})
  }
  handlerB() {}
  
  render() {
  	const prop = this.state.prop;
  	return (
  		<div>
      	<ChildA
          prop={prop}
          eventHandler={this.handlerA}/>
        <ChildB
          prop="" />
      </div>
  	)
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@前端攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值