React组件
React组件介绍
- 组件是React的一等公民,使用React就是在用组件
- 组件表示页面中的部分功能
- 组合多个组件实现完整的页面功能
- 特点:可复用、独立、可组合
React组件的两种创建方式
-
-
使用函数创建组件
-
函数组件:使用JS的函数(或箭头函数)创建的组件
-
约定1:函数名称必须以大写字母开头,React据此区分组件和普通的React元素
-
约定2:函数组件必须有返回值,表示该组件的结构
-
如果返回值为null,表示不渲染任何内容
-
渲染函数组件:用函数名作为组件标签名
-
组件标签可以是单标签也可以是双标签
-
示例:
const Hello = () => (<div>这是我的第一个函数组件!!!</div>)
-
-
使用类创建组件
-
类组件:使用ES6 的class创建的组件
-
约定1:类名称也必须以大写字母开头
-
约定2:类组件应该继承React.Component父类,从而可以使用父类中提供的方法或属性
-
约定3:类组件必须提供render()方法
-
约定4:render()方法必须有返回值,表示该组件的结构
-
示例:
class Hello extends React.Component { render() { return ( <div>这是我的第一个类组件!!!</div> ) } } // 渲染组件 ReactDOM.render(<Hello />, document.getElementById('root'))
-
-
抽离为独立JS文件
-
1、创建Hello.js
-
2、在Hello.js中导入React
-
3、创建组件(函数或类)
-
4、在Hello.js中导出该组件
-
5、在index.js中导入Hello组件
-
6、渲染组件
-
示例:
// Hello.js import React from "react"; class Hello extends React.Component{ render() { return ( <div>第一个抽离的组件</div> ) } } export default Hello // index.js import Hello from "./Hello"; ReactDOM.render(<Hello />, document.getElementById('root'))
-
-
React事件处理
-
事件绑定
-
React事件绑定语法与DOM事件语法相似
-
语法:on+事件名称={事件处理程序},比如:onClick={()=>{}}
-
注意:React事件采用驼峰命名法,比如onMouseEnter、onFocus
-
示例:
// 方式一,使用class class App extends React.Component { handleClick(){ console.log('点击成功') } render() { return ( <button onClick={this.handleClick}>点我</button> ) } } // 方式一,使用函数 function App() { function handleClick(){ console.log('点击成功') } return ( <button onClick={handleClick}>点我</button> ) } ReactDOM.render(<App/>, document.getElementById('root'))
-
-
事件对象
-
可以通过事件处理程序的参数获取到事件对象
-
React中的事件对象叫做:合成事件(对象)
-
合成事件:兼容所有浏览器,无需担心跨浏览器兼容性问题
-
示例:
class App extends React.Component{ handleClick(e){ // 阻止浏览器行为 e.preventDefault() console.log('阻止浏览器行为') } render() { return ( <a href="https://www.baidu.com/" onClick={this.handleClick}>百度</a> ) } } ReactDOM.render(<App/>, document.getElementById('root'))
-
有状态组件与无状态组件
- 函数组件又叫做无状态组件,类组件又叫做有状态组件
- 状态(state)即数据
- 函数组件没有自己的状态,只负责数据展示(静)
- 类组件有自己的状态,负责更新UI,让页面“动”起来
组件中的state和setState()
-
state的基本使用
-
状态(state)即数据,是组件内部的私有数据,只能在组件内部使用
-
state的值是对象,表示一个组件中可以有多个数据
-
通过this.state 来获取状态
-
示例:
class App extends React.Component { // constructor() { // super(); // this.state = { // count: 0 // } // } // 精简版 state = { count: 0 } render() { return ( <div>有状态组件, {this.state.count}</div> ) } } ReactDOM.render(<App/>, document.getElementById('root'))
-
-
setState()修改状态
-
状态是可变的
-
语法:this.setState({要修改的数据})
-
注意:不要直接修改state中的值,这是错误的!!!
-
setState()作用:1.修改state 2.更新UI
-
思想:数据驱动视图
-
示例:
class App extends React.Component { state = { count: 0, test: 'a' } render() { return ( <div> <h1>计数器: {this.state.count}</h1> <button onClick={ ()=> { this.setState({ count: this.state.count + 1 }) // 错误示例 // this.state.count += 1 } }>+1 </button> </div> ) } } ReactDOM.render(<App/>, document.getElementById('root'))
-
-
从JSX中抽离事件处理程序
- JSX中掺杂过多JS逻辑代码,会显得非常混乱
- 推荐:将逻辑抽离到单独的方法中,保证JSX结构清晰
- 报错原因:事件处理程序中this的值为undefined
- 希望:this指向组件实例(render方法中的this即为组件实例)
事件绑定this指向
-
1.箭头函数
-
利用箭头函数自身不绑定this的特点
-
render()方法中的this为组件实例,可以获取到setState()
-
示例:
class App extends React.Component { state = { count: 0 } onIncrement(){ console.log(this) this.setState({ count: this.state.count + 1 }) } render() { return ( <div> <h1>计数器: {this.state.count}</h1> <button onClick={() => this.onIncrement()}> +1 </button> </div> ) } } ReactDOM.render(<App/>, document.getElementById('root'))
-
-
2.Function.prototype.bind()
-
利用ES5中的bind方法,将事件处理程序中的this与组件实例绑定到一起
-
示例:
class App extends React.Component { constructor() { super(); this.state = { count: 0 } this.onIncrement = this.onIncrement.bind(this) } onIncrement(){ console.log(this) this.setState({ count: this.state.count + 1 }) } render() { return ( <div> <h1>计数器: {this.state.count}</h1> <button onClick={this.onIncrement}> +1 </button> </div> ) } } ReactDOM.render(<App/>, document.getElementById('root'))
-
-
3.class的实例方法
-
利用箭头函数形式的class实例方法
-
注意:该语法是实验性语法,但是,由于babel的存在可以直接使用
-
示例:
class App extends React.Component { state = { count: 0 } onIncrement = () => { console.log(this) this.setState({ count: this.state.count + 1 }) } render() { return ( <div> <h1>计数器: {this.state.count}</h1> <button onClick={this.onIncrement}> +1 </button> </div> ) } } ReactDOM.render(<App/>, document.getElementById('root'))
-
表单处理
-
1.受控组件
-
HTML中的表单元素是可输入的,也就是自己的可变状态
-
而,React中可变状态通常保存在state中,并且只能通过setState()方法来修改
-
React将state与表单元素值value绑定在一起,由state的值来控制表单元素的值
-
受控组件:其值受到React控制的表单元素
-
示例:
<input type="text" value={this.state.txt} />
-
步骤:
-
1.在state中添加一个状态,作为表单元素的value值(控制表单元素的来源)
-
2.给表单元素绑定change事件,将表单元素的值设置为state的值(控制表单元素值的变化)
-
示例:
class App extends React.Component{ state = { txt: '' } handleChange = (e) => { this.setState({ txt: e.target.value }) } render() { return ( <div> <input type="text" value={this.state.txt} onChange={this.handleChange} /> </div> ) } } ReactDOM.render(<App/>, document.getElementById('root'))
-
示例总结:
-
文本框、富文本框、下拉框 操作value属性
-
复选框 操作checked属性
-
示例:
class App extends React.Component{ state = { txt: '', content: '', city: 'bj', isChecked: false } // 处理文本 handleChange = e => { this.setState({ txt: e.target.value }) } // 处理富文本 handleContent = e => { this.setState({ content: e.target.value }) } // 处理下拉框 handleCity = e => { this.setState({ city: e.target.value }) } // 处理复选框 handleChecked = e => { this.setState({ isChecked: e.target.checked }) } render() { return ( <div> {/*文本框 */} <input type="text" value={this.state.txt} onChange={this.handleChange} /> <br/> {/*富文本框 */} <textarea value={this.state.content} onChange={this.handleContent}/> <br/> {/*下拉框 */} <select value={this.state.city} onChange={this.handleCity}> <option value="sh">上海</option> <option value="bj">北京</option> <option value="nj">南京</option> </select> <br/> {/*复选框 */} <input type="checkbox" checked={this.state.isChecked} onChange={this.handleChecked}/> </div> ) } } ReactDOM.render(<App/>, document.getElementById('root'))
-
-
多表单元素优化:
-
问题:每个表单元素都有一个单独的事件处理程序处理太繁琐
-
优化:使用一个事件处理程序同时处理多个表单元素
-
优化步骤:
-
1.给表单元素添加name属性,名称与state相同
-
2.根据表单元素类型获取对应值
-
3.在change事件处理程序中通过[name]来 修改对应的state
-
示例:
class App extends React.Component{ state = { txt: '', content: '', city: 'bj', isChecked: false } handleForm = e => { // 获取当然dom对象 const target = e.target // 根据类型获取值 const value = target.type === 'checkbox' ? target.checked : target.value // 获取name const name = target.name this.setState({ [name]: value }) } render() { return ( <div> {/*文本框 */} <input type="text" name="txt" value={this.state.txt} onChange={this.handleForm} /> <br/> {/*富文本框 */} <textarea name="content" value={this.state.content} onChange={this.handleForm}/> <br/> {/*下拉框 */} <select name="city" value={this.state.city} onChange={this.handleForm}> <option value="sh">上海</option> <option value="bj">北京</option> <option value="nj">南京</option> </select> <br/> {/*复选框 */} <input type="checkbox" name="isChecked" checked={this.state.isChecked} onChange={this.handleForm}/> </div> ) } } ReactDOM.render(<App/>, document.getElementById('root'))
-
-
-
-
2.非受控组件
-
说明:借助于ref,使用原生DOM方式来获取表单元素值
-
ref的作用:获取DOM或组件
-
步骤:
-
1.调用React.createRef()方法创建一个ref对象
-
2.将创建好的ref对象添加到文本框中
-
3.通过ref对象获取到文本框的值
-
示例:
class App extends React.Component { constructor() { super(); // 创建ref this.txtRef = React.createRef() } // 获取文本框的值 getTxt = () => { console.log('打印') console.log(this.txtRef.current.value) } render() { return ( <div> {/*文本框 */} <input type="text" ref={this.txtRef} /> <button onClick={this.getTxt}>获取文本框的值</button> </div> ) } } ReactDOM.render(<App/>, document.getElementById('root'))
-
-
-