React
是一个声明式,高效且灵活的用于构建用户界面的JavaScript
库。能够将一些简短、独立的代码片断组合成复杂的UI界面,这些片断被称为“组件”。javascript
React 大致包含下面这些概念:前端
能够将UI 拆分为独立且复用的代码片断,每部分均可独立维护。
组件,从概念上相似于JavaScript
函数。它接受任意的参数(即 “props”),并返回用于描述页面展现内容的React 元素
。
自定义组件命名:必须以大写字母开头,React 会将以小写字母开头的组件视为原生DOM标签。vue
import React from 'react'; // React 的核心库 import ReactDOM from 'react-dom'; // 提供与 DOM 相关的功能 class ShoppingList extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for {this.props.name}</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } ReactDOM.render( <ShoppingList name="Mark" />, document.getElementById('root') );
React 应用都是构建在组件之上。ShoppingList
就是一个React 组件类型,ReactDOM.render
函数会将组件方到页面上的某个节点元素中。(render
返回了一个 React 元素
,这是一种对渲染内容的轻量级描述。)
大多数 React
应用只会调用一次 ReactDOM.render()
。java
其中props
(是 properties 的简写) 是组件包含的两个核心概念之一,另外一个是state
。react
props
接收一些其余组件的参数(好比上方的 name ),来配置组件,全部 React
组件都必须像纯函数同样保护它们的 props
不被更改。git
state
来实现所谓“记忆”的功能。能够经过 React
组件的构造函数中设置 this.state
;this.state
应该被视为一个组件的私有属性。
修改this.state
值须要经过this.setState
方法赋值,有些 props
值或 state
值多是异步更新的,使用对象赋值的方式更改 state
可能无效,可以使用回调传参方式更新github
this.setState( (state,props)=> ({count:state.count + props.count}) );
经过
class
语法来定义组件,必须包含render()
方法,而且继承于React.Component
。
类组件必须包含render()
,而且return 只能返回一个父元素(相似vue中的template中必需要有一个父元素)。数组
class Square extends React.Component { /** * @name constructor * @param {*} props * 每次定义子类的构造函数时,都必须调用 super 方法。 * 所以,在全部含有构造函数的React组件中,构造函数必须以super(props)开头 * state 保存着组件中的数据 相似 vue 中的 data 属性 */ constructor(props) { super(props); this.state = { value:null }; } render() { return ( <button className="square" onClick = {()=>{this.setState({value:'X'})} }> {this.state.value} </button> ); } }
render方法中的onClick
事件监听函数中调用this.setState
方法,能够设置this.state
中的属性
推荐使用箭头函数,避免this 形成困扰。dom
简单组件是一个函数,不须要使用class
关键字,固然就没有constructor和state
异步
const Square = (props) => { return (<button className= "square" onClick= { props.onClick} >{ props.value } </button>) }
input
、<select>
、<textarea>
等表单的状态发生改变,都得同时经过onChange
事件改变组件中的state
值,不然表单不会发生变化。经过这种方式控制取值的表单叫作受控组件
。
class Input extends Component { constructor(props){ super(props) this.state = { value:'3s' } } render (){ return <input type="text" value = {this.state.value} /> // 用户在表单中输入任何信息都是无效的 } } // 使用事件来改变 render (){ return ( <input type="text" value = {this.state.value} onChange = {({target}) =>{ this.setState({ value:target.value }) }} /> ) }
React受控组件更新state的流程:
onChange
事件state
将组件变成数组集合放入花括号中便可渲染多个组件,一般使用数组的map()
方法
const Lis = (props) => { const lis = props.list.map((val,key)=> <li key={key}>{key+1}</li>); return <ul>{lis}</ul> } const list = Array(7).fill(null); ReactDOM.render( <Lis list = {list} />, document.getElementById('root') );
当多个组件发生数据联动时,建议将共享状态提高到最近的共同父组件中去。
/* * @Author: Owen * @Date: 2019-07-23 23:55:17 * @Last Modified by: Owen * @Last Modified time: 2019-07-29 16:06:22 */ import React,{Component} from 'react'; import {render} from 'react-dom'; // 温度转化器 let toConvert = (temperature,callback) => { let num = parseInt(temperature); if(Number.isNaN(num)) return '' num = callback(num) return Math.round(num*1000)/1000; } const BoilingVerdict = (props) =>{ let text = props.temperature > 100?'':' not'; return (<p> The water would{text} boil. </p>) } // 公共input组件只接收行为和状态 const TemperatureInput = (props) =>{ return ( <input value ={props.temperature} onChange = {props.valueChange} /> ) } // 父组件设置行为和状态 class Calculator extends Component { constructor(props){ super(props) this.state = { temperature:'', scale:'C' } } toFahrenheit({target}) { this.setState({ temperature:target.value, scale:'F' }) } toCelsius({target}) { this.setState({ temperature:target.value, scale:'C' }) } render() { let {temperature,scale} = this.state; let celsius = scale === 'F'?toConvert(temperature,(val)=>(val - 32)*5/9):temperature; let fahrenheit = scale === 'C'?toConvert(temperature,(val)=>val*9/5+32):temperature; return ( <div> <div> Celsius: <TemperatureInput scale ='C' temperature = {celsius} valueChange = {this.toCelsius.bind(this)} /> </div> <div> Fahrenheit: <TemperatureInput scale ='F' temperature = {fahrenheit} valueChange = {this.toFahrenheit.bind(this)} /> </div> <div><BoilingVerdict temperature = {this.state.temperature} /></div> </div> ); } } render(<Calculator />,document.querySelector('#root'))
在就React
应用中,任何科比数据应当只有一个相对应的数据源,一般,多个组件须要相同数据,能够将数据提高到这些组件的共同父组件中。依靠自上而下的数据流,去控制组件,而不是尝试在不一样组件同步 state
。这样会减小未来排查和隔离BUG所须要的工做量
有些组件没法提早知晓它们子组件的具体内容,须要留坑,那么也能够经过 props
来占位。
props.children
件起始标签和结束标签之间的内容都会被将{props.children}
替换。
function FancyBorder(props) { return ( <div className={'FancyBorder FancyBorder-' + props.color}> {props.children} </div> ); } function WelcomeDialog() { return ( <FancyBorder color="blue"> <h1 className="Dialog-title"> Welcome </h1> <p className="Dialog-message"> Thank you for visiting our spacecraft! </p> </FancyBorder> ); }
由于 React元素
本质就是对象,因此能够将它当中参数像其余数据同样传递。
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 /> } /> ); }
每一个 JSX 元素都是调用 React.createElement() 的语法糖。通常来讲,若是你使用了 JSX,就再也不须要调用
createElement()
或createFactory()
方法。
React 提出的一种叫 JSX 的语法,这应该是最开始接触 React 最不能接受的设定之一,由于前端被“表现和逻辑层分离”这种思想“洗脑”过久了。实际上组件的 HTML 是组成一个组件不可分割的一部分,可以将 HTML 封装起来才是组件的彻底体.
JSX是一个JavaScript语法扩展。它相似于模板语言,但它具备JavaScript 的所有能力。它最终会被编译为
React.createElement()
函数调用,返回称为React元素
的普通JavaScript`对象。
推荐使用箭头函数,避免this 形成困扰
function Square(props) { return ( < button className = "square" onClick = { props.onClick } > { props.value } </button> ); } class Board extends React.Component { constructor(props){ super(props) this.state = { squares: Array(9).fill(null), xIsNext:true, // 先落子,并确认该哪位玩家落子 } } /** * 只接受一个squares副本,而不直接修改自己数据 * 1. 这样能够简化复杂的功能,不可变性使得复杂的特性更容易实现。 * 2. 能够跟踪数据的改变,若是直接修改源数据就很难跟踪变化的数据。 * 3. 能够帮助咱们在 React 中建立 purecomponents。能够轻松的肯定不可变数据是否发生了改变, * 从而肯定什么时候对组件进行从新渲染。 * @param {*} i * @memberof Board */ handleClick(i) { const squares = this.state.squares.slice(); squares[i] = this.state.xIsNext? "X":"O"; this.setState({ squares,xIsNext:!this.state.xIsNext }) } renderSquare(i) { // 返回一个 Square 组件 return ( < Square value = { this.state.squares[i] }// 给子组件传递 value数据 onClick = {()=> this.handleClick(i)} // 给子组件传递 onClick事件 />); } render() { let {state} = this; const status = `Next player: ${state.xIsNext?'X':'O'}`; return ( <div> <div className="status">{status}</div> <div className="board-row"> {this.renderSquare(0)} {this.renderSquare(1)} {this.renderSquare(2)} </div> <div className="board-row"> {this.renderSquare(3)} {this.renderSquare(4)} {this.renderSquare(5)} </div> <div className="board-row"> {this.renderSquare(6)} {this.renderSquare(7)} {this.renderSquare(8)} </div> </div> ); } }
在 JSX 中你能够任意使用JavaScript表达式,只须要用一个大括号({})括起来;
事实上每一个 React 元素都是一个JavaScript
对象,能够把它保存在变量中或者做为参数传递。
为避免遇到自动插入分号陷阱,最好将内容包裹在小括号中,若是只有一行代码则不须要括号。
// 加括号 class App extends React.Component { render() { return ( <div className="shopping-list"> <h1>Shopping List for</h1> <ul> <li>Instagram</li> <li>WhatsApp</li> <li>Oculus</li> </ul> </div> ); } } // 不用加括号 class App extends React.Component { render() { return <li>Instagram</li>; } }
JSX 语法更接近于 JavaScript,因此 ReactDom 使用cameCase(小驼峰命名)来定义属性名称,而且不要使用引号将大括号包裹,二者是不能并存的。对于字符串值使用引号,对于表达式使用大括号
React
中没法经过 return false
的方式阻止默认行为,必须使用e.preventDefault()
阻止默认事件。可是不用担忧event事件
的兼容问题
JSX 自己就能防止XSS攻击
// 原生DOM <a href="#" onclick="console.log('The link was clicked.'); return false"> Click me </a> // JSX class App extends React.Component { render() { return ( <a href="#" onclick={(e)=>this.handleClick(e)}> //每次渲染时都会建立不一样的回调函数。该回调函数做为 prop 传入子组件时,这些组件可能会进行额外的从新渲染。 Click me </a>; <a href="#" onclick={(e)=>this.handleClick(id,e)}> // 向事件处理程序传递参数 Click me </a>; ) } }
JavaScript
中,class
的方法默认不会绑定 this
。若是你忘记绑定 this.handleClick
并把它传入了 onClick
,当你调用这个函数的时候 this
的值为 undefined
。class App extends React.Component { // 此语法确保 `handleClick` 内的 `this` 已被绑定。 // 注意: 这是 **实验性** 语法。 使用 Create React App 默认会启用此语法 handleClick = (e)=> { e.preventDefault(); console.log(e) } render() { return ( <a href="#" onclick={this.handleClick}> Click me </a>; <a href="#" onclick={this.handleClick。bind(this,id)}> // 向事件处理程序传递参数, 事件对象会被隐式传递 Click me </a>; ) } }
参考资料
react 官网
React 入门教程