React 基础语法
一、Hello World<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>React demo</title> <script src="../build/react.js"></script> <script src="../build/react-dom.js"></script> <script src="../build/browser.min.js"></script> </head> <body> <div id="root"></div> <script type="text/babel"> function Hello() { return <h1>Hello world.</h1>; } ReactDOM.render( <Hello/>,document.getElementById(‘root‘) ) </script> </body> </html> 二、JSX 简介JSX 是一种 JavaScript 的语法扩展。推荐在 React 中使用 JSX 来描述用户界面,JSX 用来声明 React 当中的元素。 2.1 在 JSX 中使用表达式在 JSX 当中的表达式要包含在大括号里。 const element = ( <h1> Hello,{formatName(user)}! </h1> ); 推荐在 JSX 代码的外面括上小括号,这样可以防止分号自动插入的 BUG。 JSX 本身其实也是一种表达式在编译之后,JSX 其实会被转化为普通的 JavaScript 对象。 JSX 属性const element = <img src={user.avatarUrl}></img>; 使用了大括号包裹的 JavaScript 表达式时就不要再到外面套引号了。 JSX 会将引号当中的内容识别为字符串而不是表达式。 JSX 嵌套如果 JSX 标签是闭合式的,那么你需要在结尾处用/>,就好像 XML/HTML 一样: const element = <img src={user.avatarUrl}/>; JSX 标签同样可以相互嵌套: const element = ( <div> <h1>Hello!</h1> <h2>Good to see you here.</h2> </div> )
JSX 代表 ObjectsBabel 转译器会把 JSX 转换成一个名为 React.createElement() 的方法调用。 下面两种代码的作用是完全相同的: const element = ( <h1 className="greeting"> Hello,world! </h1> ); const element = React.createElement( ‘h1‘,{className: ‘greeting‘},‘Hello,world!‘ ); React.createElement() 这个方法首先会进行一些避免 bug 的检查,之后返回一个类似下面例子的对象: // 注意: 以下示例是简化过的(不代表在 React 源码中是这样) const element = { type: ‘h1‘,props: { className: ‘greeting‘,children: ‘Hello,world‘ } }; 这样的对象被称为“React 元素”。 三、元素渲染元素是构成 React 应用的最小单位。 3.1 将元素渲染到 DOM 中首先定义一个 id 为 root 的 div: <div id=‘root‘></div> 在此 div 中的所有内容都将由 React DOM 来管理,所以我们将其称之为“根” DOM 节点。 我们用 React 开发应用时一般只会定义一个根节点。 要将 React 元素渲染到根 DOM 节点中,我们通过把它们都传递给 ReactDOM.render() 的方法来将其渲染到页面上: const element = <h1>Hello,world</h1>; ReactDOM.render( element,document.getElementById(‘root‘) ) 四、组件 & Props组件可以将 UI 切分为一些独立的、可复用的部件,这样你就只需专注于构建每一个单独的部件。 组件从概念上看就像是函数,它可以接收任意的输入值(称之为“props”),并返回一个需要在页面上展示的 React 元素。 4.1 函数定义/类定义组件定义一个组件最简单的方式是使用 JavaScript 函数: // 函数定义组件 function Welcome(props){ return <h1>Helle,{props.name}</h1>; } 也可以使用 ES6 class 来定义一个组件:
// 类定义组件 class Welcome extents React.Component { render(){ return <h1>Hello,{this.props.name}</h1>; } } 4.2 组件渲染第一步,定义一个 Welcome 组件: function Welcome(props) { return <h1>Hello,{props.name}</h1>; } 第二步,使用该组件创建 React 元素: const element = <Welcome name=‘kevin‘/>; 第三步,使用 ReactDOM.render() 方法将 React 元素渲染到页面上: ReactDOM.render( element,document.getElementById(‘root‘); ) 4.3 组合组件组件可以在它的输出中引用其他组件: function Welcome(props) { return <h1>Hello,{props.name}</h1>; } function App() { return ( <div> <Welcome name=‘kevin‘/> <Welcome name=‘tom‘/> <Welcome name=‘bob‘/> </div> ); } ReactDOM.render( <App/>,document.getElementById(‘root‘) );
4.4 props 的只读性props 是不可变的 五、State & 生命周期状态与属性十分相似,但是状态是私有的,完全受控于当前组件。 使用类定义组件,就可以使用局部状态、生命周期钩子等特性。 5.1 为一个类添加局部状态第一步:使用 ES6 class 定义一个组件 class Clock extents React.component { render() { return ( <div> <h1>Hello,world!</h1> <h2>It is {this.state.date.toLocaleTimeString}</h2> </div> ) } } 第二步:添加一个类构造函数来初始化状态 this.state class Clock extents 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> ) }; } 第三步:使用 ReactDOM.render() 方法渲染组件到页面 class Clock extents 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> ) }; } ReactDOM.render( <Clock/>,document.getElementById(‘root‘) ) 5.2 将生命周期方法添加到类中在 5.1 中,我们只是添加了一个状态,那么,如何更新状态呢?答案是:使用生命周期方法。 class Clock extents React.component { constructor(props) { super(props); this.state = {date : new Date()}; } componentDidMount() { this.timeID = setInterval( () => this.tick(),1000 ); } componentWillUnmount() { clearInterval(this.timeID); } tick(){ this.setState({ date : new Date() }); } render() { return ( <div> <h1>Hello,document.getElementById(‘root‘) ) 当 Clock 的输出插入到 DOM 中时,React 会调用 componentDidMount() 生命周期方法。上面代码示例中,我们在该方法中设置了一个定时器,每个 1 秒钟调用一次 tick() 方法。 在 tick() 方法中,Clock 组件通过使用包含当前时间的对象调用 setState() 来更新状态。当 React 发现状态已经更新时,会再次调用 ReactDOM.render() 方法更新 DOM。 当 Clock 组件被从 DOM 中移除,React 会调用 componentWillUnmount() 生命周期方法。 5.3 正确地使用状态
构造函数是唯一能够初始化 this.state 的地方。其他地方更薪状态只能使用 this.setState();
不太懂 TODO
不太懂 TODO 5.4 数据自顶向下流动父组件或子组件都不能知道某个组件是有状态还是无状态,并且它们不应该关心某组件是被定义为一个函数还是一个类。 所以状态通常被成为局部或封装。除了拥有并设置它的组件外,其他组件不可访问。 但组件可以选择将其状态作为属性传递给其子组件。 这通常被称为 自顶向下 或 单向 数据流。任何状态始终由某些特定组件所有,并且该状态导出的任何数据或 UI 只能影响树中 下方 的组件。 六、事件处理
例如,传统的 HTML 写法: <button onclick="activateLasers()"> Activate Lasers </button> React 写法: <button onClick={activateLasers}> Activate Lasers </button>
6.1 开关实例class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; // 绑定 this this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState( prevState => ({ isToggleOn: !prevState.isToggleOn }) ); } render () { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? ‘ON‘ : ‘OFF‘} </button> ); } } ReactDOM.render( <Toggle/>,document.getElementById(‘root‘) ) 6.2 向事件处理程序传递参数有两种方式向事件处理程序传递参数,分别是:
<button onClick={(e) => this.deleleRow(id,e)}>Delete Row</button>
<button onClick={this.deleleRow.bind(this,id)}>Delete Row</button> 参数 e 作为 React 的事件对象将会被作为第二个参数进行传递。 箭头函数的方式,事件对象必须显式传递; 绑定的方式,事件对象以及更多的参数将会被隐式传递。值得注意的是,通过绑定的方式向监听函数传参,在类组件中定义的监听组件,事件对象 e 排在所传递参数的后面。 七、条件渲染React 中的条件和 JavaScript 中的一致,使用 JavaScript 操作符 if 或 条件运算符 来创建表示当前状态的元素,然后让 React 来更新 UI。 7.1 if示例: function UserGreeting() { return <h1>Welcome back!</h1>; } function GuestGreeting() { return <h1>Please sign up.</h1> } function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn){ return <UserGreeting/> } return <GuestGreeting/> } ReactDOM.render( <Greeting isLoggedIn={true}/>,document.getElementById(‘root‘) ) 7.2 与运算符 &&function Mailbox(props) { const message = props.message; return ( <div> <h1>Hello!</h1> {message.length > 0 && <h2> You have {message.length} unread message. </h2>} </div> ) } const message = [‘React‘,‘Re:React‘,‘Re:Re:React‘]; ReactDOM.render( <Mailbox message={message}/>,document.getElementById(‘root‘) ) true && expression 总是返回 expression,而 false && expression,React 会忽略并跳过它。 7.3 三目运算符class Login extends React.Component { constructor(props) { super(props); this.state = {isLogin: false}; this.login = this.login.bind(this); } login() { this.setState( prevState => ({ isLogin: !prevState.isLogin }) ); } render (){ return ( <div> <h1> {this.state.isLogin ? ‘Welcome‘ : ‘Please Login‘} </h1> <button onClick={this.login}></button> </div> ); } } ReactDOM.render( <Login/>,document.getElementById(‘root‘) ) 7.4 阻止组件渲染让组件的 render 方法返回 null 即可阻止组件渲染。 八、列表 & Keysfunction ToDoList(props) { const things = props.things; const todolist = things.map((thing) => <li key={thing.toString()}>{thing}</li> ); return ( <ul>{todolist}</ul> ) } const things = [1,2,3,4,5]; ReactDOM.render( <ToDoList things={things}/>,document.getElementById(‘root‘) )
九、表单9.1 受控组件
class Form extends React.Component { constructor(props) { super(props); this.state = {value : ‘1‘} this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange (event) { this.setState({ value : event.target.value }) } handleSubmit (event) { alert(‘name is ‘ + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <select value={this.state.value} onChange={this.handleChange}> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> </select> </label> <input type="submit" value="Submit"></input> </form> ) }; } ReactDOM.render( <Form/>,document.getElementById(‘root‘) )
9.2 多个输入框class Form extends React.Component { constructor(props) { super(props); this.state = { name : ‘‘,age: 0 } this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { const target = event.target; const name = target.name; const value = target.value; this.setState({ [name] : value }) } handleSubmit(event) { alert(‘name is ‘ + this.state.name + ‘,and age is ‘ + this.state.age); event.preventDefault(); } render () { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" name="name" value={this.state.name} onChange={this.handleChange}/> </label> <label> age: <input type="text" name="age" value={this.state.age} onChange={this.handleChange}/> </label> <input type="submit" value="Submit"/> </form> ) } } ReactDOM.render( <Form/>,document.getElementById(‘root‘) ) 当有多个受控的元素时,可以给每个元素添加一个 name 属性,来让处理函数 event.target.name 的值区分。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |