react版本:16.13.1
-
React 会将以小写字母开头的组件视为原生 DOM 标签,所以自定义组件名称规范是大写字母开头。
-
JSX 里的 class 变成了 className
-
JSX 防止注入攻击:React DOM 在渲染所有输入内容之前,默认会进行转义。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(cross-site-scripting, 跨站脚本)攻击。
-
React DOM 会将元素和它的子元素与它们之前的状态进行比较,并只会进行必要的更新来使 DOM 达到预期的状态。
-
组件无论是使用函数声明还是通过 class 声明,都决不能修改自身的 props,props是只读的,直接修改会报错。React 组件都必须像纯函数一样保护它们的 props 不被更改
-
纯函数定义:
函数不会尝试更改入参,且多次调用下相同的入参始终返回相同的结果。它不依赖于程序执行期间函数外部任何状态或数据的变化,必须只依赖于其输入参数。 -
State 与 props 类似,但是 state 是私有的,并且完全受控于当前组件。
-
componentDidMount() 方法会在组件已经被渲染到 DOM 中后运行
-
关于 setState() 你应该了解三件事:
-不要直接修改 State
-State 的更新可能是异步的:
React 可能会把多个 setState() 调用合并成一个调用。因为 this.props 和 this.state 可能会异步更新,所以你不要依赖他们的值来更新下一个状态。
要解决这个问题,可以让 setState() 接收一个函数而不是一个对象。// Wrong this.setState({ counter: this.state.counter + this.props.increment, }); // Correct this.setState((state, props) => ({ counter: state.counter + props.increment }));
-State 的更新会被合并:
当你调用 setState() 的时候,React 会把你提供的对象合并到当前的 state。这里的合并是浅合并 -
在 React 中你不能通过返回 false 的方式阻止默认行为。你必须显式的使用 preventDefault:
function ActionLink() { function handleClick(e) { e.preventDefault(); console.log('The link was clicked.'); } return ( <a href="#" onClick={handleClick}> Click me </a> ); }
-
JSX 回调函数中的 this,在 JavaScript 中,class 的方法默认不会绑定 this。
//方法一:在构造函数中绑定(ES2015) constructor(props) { super(props); this.handleClick = this.handleClick.bind(this);//将对象原型上的handleClick绑定到对象实例上 } handleClick() {//对象原型上绑定handleClick } render() { return ( <button onClick={this.handleClick}></button> ); } //方法二:class 属性(第三阶段提案) handleClick = () => {//直接在对象实例上绑定 console.log('this is:', this); } render() { return ( <button onClick={this.handleClick}></button> ); } //方法三:在 Render 中使用箭头函数 handleClick() { console.log('this is:', this); } render() { // 此语法确保 `handleClick` 内的 `this` 已被绑定。 return ( <button onClick={() => this.handleClick()}></button> ); } //方法四:在 Render 中的绑定 handleClick() { console.log('this is:', this); } render() { // 此语法确保 `handleClick` 内的 `this` 已被绑定。 return ( <button onClick={this.handleClick.bind(this)}></button> ); }
方法三问题在于每次渲染都会创建不同的回调函数,如果该回调函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。可能会带来性能问题。
方法四在 render 方法中使用 Function.prototype.bind 会在每次组件渲染时创建一个新的函数,可能会影响性能。所以最好用方法一或者二。 -
向事件处理程序传递参数
//在这两种情况下,React 的事件对象 e 会被作为第二个参数传递。 <button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button> <button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
-
阻止组件渲染:可以让 render 方法直接返回 null,而不进行任何渲染。
-
在组件的 render 方法中返回 null 并不会影响组件的生命周期。
-
使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
-
渲染列表:
元素的 key 只有放在就近的数组上下文中才有意义。const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => <li key={number.toString()}>{number}</li> ); ReactDOM.render( <ul>{listItems}</ul>, document.getElementById('root') );
-
如果列表项目的顺序可能会变化,我们不建议使用索引来用作 key 值,因为这样做会导致性能变差,还可能引起组件状态的问题。
-
key 会传递信息给 React ,但不会传递给你的组件。
//Post 组件可以读出 props.id,但是不能读出 props.key。 const content = posts.map((post) => <Post key={post.id} id={post.id} title={post.title} /> );
-
在 select 标签中选择多个选项:
<select multiple={true} value={['B', 'C']}>
-
ES6 计算属性名称的语法更新给定输入名称对应的 state 值:
this.setState({ [name]: value }); //等同 ES5: var partialState = {}; partialState[name] = value; this.setState(partialState);
-
在受控组件上指定 value 的 prop 会阻止用户更改输入。如果你指定了 value,但输入仍可编辑,则可能是你意外地将value 设置为 undefined 或 null。
//input输入值不可被修改,1秒后可以被修改 ReactDOM.render(<input value="hi" />, mountNode); setTimeout(function() { ReactDOM.render(<input value={null} />, mountNode); }, 1000);
-
通常,多个组件需要反映相同的变化数据,这时我们建议将共享状态提升到最近的共同父组件中去。
-
JSX 标签中的所有内容都会作为一个 children prop 传递给JSX 标签。
function FancyBorder(props) { return ( <div> {props.children} </div> ); } 这使得别的组件可以通过 JSX 嵌套,将任意组件作为子组件传递给它们。 function WelcomeDialog() { return ( <FancyBorder> <h1 className="Dialog-title"> Welcome </h1> </FancyBorder> ); } //也可以自行约定 function SplitPane(props) { return ( <div className="SplitPane"> <div className="SplitPane-left"> {props.left} </div> <div className="SplitPane-right"> {props.right} </div> </div> ); } function App() { return ( <SplitPane left={ <Contacts /> } right={ <Chat /> } /> ); }