赞
踩
React 是一个用于构建用户界面的javaScript库,起源于facebook的内部项目,后续在13年开源了出来。
特点:
1、安装 React,在终端执行命令 npm i react react-dom
:
2、引入 react 和 react-dom 两个 js 文件:
<script src="../node_modules/react/umd/react.development.js"></script>
<script src="../node_modules/react-dom/umd/react-dom.development.js"></script>
3、创建 React 元素并渲染 React 元素到页面中:
<body>
<div id="root"></div>
</body>
<script>
const title = React.createElement('h2', null, 'React 基本使用')
ReactDOM.createRoot(document.getElementById('root')).render(title)
</script>
React.createElement
方法说明:
const title = React.createElement('h2', null, 'hello, world!', React.createElement('a', { href: 'https://www.baidu.cn/' }, '百度'))
ReactDOM.createRoot(dom).render(el)
方法说明:要渲染的React元素渲染到页面中的指定位置。
React脚手架意义:
React 脚手架初始化项目:
1、初始化项目,命令:npx create-react-app my-app
npx 命令是 npm v5.2.0 引入的一条命令:
2、 启动项目,在项目根目录执行命令:npm start
脚手架创建项目的方式:
1、推荐使用:npx create-react-app my-app
2、npm init react-app my-app
3、如果安装了 yarn,可以使用 yarn create react-app my-app
1、导入 react 和 react-dom 两个包:
import React from 'react'
import ReactDOM from 'react-dom/client'
2、调用 React.createElement() 方法创建 react 元素,并使用 ReactDOM 渲染到页面中:
const title = React.createElement('h2', null, 'hello, world!')
ReactDOM.createRoot(document.getElementById('root')).render(title)
通过createElement()方法创建的React元素有一些问题,代码比较繁琐,结构不直观,无法一眼看出描述的结构,不优雅。
JSX是JavaScript XML 的简写,表示在JavaScript代码中写HTML格式的代码,JSX优势就是声明式语法更加直观,与HTML结构相同,降低了学习成本,提升开发效率。
使用 JSX 语法创建 react 元素,并使用 ReactDOM 渲染到页面中:
const hiJSX = <h2>hello JSX!</h2>
ReactDOM.createRoot(document.getElementById('hiJSX')).render(hiJSX)
思考,为什么在脚手架中可以使用JSX语法?
使用 JSX 注意点:
/>
结束 。const note = (
<div className='note' />
)
ReactDOM.createRoot(document.getElementById('note')).render(note)
JSX 嵌入 JS 表达式,语法是 { JavaScript表达式 }
,注意事项如下:
{}
中出现语句(比如:if/for 等)const sayHi = () => { return 'hello, JSX' } const expression = ( <div> <p>{1}</p> <p>{'a'}</p> <p>{1 + 7}</p> <p>1 大于 2 吗?{1 > 2 ? '大于' : '小于或等于'}</p> <p>{sayHi()}</p> {/* 错误示例 */} {/* <p>{{ a: 'a' }}</p> */} {/* <p>{if (true) {}}</p> */} {/* <p>{for (var i = 0; i < 8; i++) {}}</p> */} </div> ) ReactDOM.createRoot(document.getElementById('expression')).render(expression)
根据条件渲染特定的 JSX 结构,可以使用if/else或三元运算符或逻辑与运算符来实现:
var flag = true // if-else const load = () => { if (flag) { return <p>loading……</p> } else { return <p>加载完成</p> } } // 三元表达式 const load1 = () => { return flag ? <p>loading……</p> : <p>加载完成</p> } // 逻辑与运算符 const load2 = () => { return flag && <p>loading……</p> } const condition = ( <div> if-else 条件语句: {load()} 三元表达式: {load1()} 逻辑与运算符: {load2()} </div> ) ReactDOM.createRoot(document.getElementById('condition')).render(condition)
如果要渲染一组数据,应该使用数组的 map() 方法:
const data = [
{ id: 0, name: 'one' },
{ id: 1, name: 'two' },
{ id: 2, name: 'three' },
{ id: 3, name: 'four' }
]
const ul = (
<ul>
{data.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
)
ReactDOM.createRoot(document.getElementById('list')).render(ul)
1、行内样式 —— style,在style里面通过对象的方式传递数据,这种方式比较的麻烦,不方便进行阅读,而且还会导致代码比较的繁琐:
const lineStyle = (
<div style={{ backgroundColor: 'red', width: '100px', height: '100px'}}></div>
)
ReactDOM.createRoot(document.getElementById('lineStyle')).render(lineStyle)
2、类名 —— className(推荐),先创建CSS文件编写样式代码,然后在js中进行引入并设置类名即可:
/* css */
.green {
background-color: green;
width: 100px;
height: 100px;
}
// js
import './index.css'
const className = (
<div className='green'></div>
)
ReactDOM.createRoot(document.getElementById('className')).render(className)
总结:React完全利用JS语言自身的能力来编写UI,而不是造轮子增强HTML功能。
组件是React的一等公民,使用React就是在用组件。组件表示页面中的部分功能,组合多个组件实现完整的页面功能。特点是可复用、独立、可组合。
1、使用函数创建组件,使用 JS 的函数(或箭头函数)创建的组件
// 渲染结构的函数组件 function FuncComOne() { return ( <div>渲染结构的函数组件</div> ) } ReactDOM.createRoot(document.getElementById('funcOne')).render(<FuncComOne></FuncComOne>) // 不渲染结构的函数组件 function FuncComTwo() { return null } ReactDOM.createRoot(document.getElementById('funcTwo')).render(<FuncComTwo></FuncComTwo>) // 使用箭头函数 const FuncComThree = () => <div>使用箭头函数创建渲染结构的函数组件</div> ReactDOM.createRoot(document.getElementById('funcThree')).render(<FuncComThree></FuncComThree>)
渲染函数组件用函数名作为组件标签名,组件标签可以是单标签也可以是双标签。
说明:
2、使用类创建组件就是使用 ES6 的 class 创建的组件
// 使用类创建组件
class ClassCom extends React.Component {
render() {
return (
<div>渲染结构的类组件</div>
)
}
}
ReactDOM.createRoot(document.getElementById('classCom')).render(<ClassCom></ClassCom>)
组件作为一个独立的个体,一般都会放到一个单独的 JS 文件中。
1、创建组件文件 SingleCom.js,在 SingleCom.js 中导入React创建组件(函数 或 类)并导出该组件:
import React from "react";
class SingleCom extends React.Component {
render() {
return (
<div>把组件抽离为独立 JS 文件</div>
)
}
}
export default SingleCom
2、在 index.js 中导入 Hello 组件并渲染组件:
import SingleCom from './SingleCom'
ReactDOM.createRoot(document.getElementById('SingleCom')).render(<SingleCom></SingleCom>)
React 事件绑定语法与 DOM 事件语法相似,语法是 on+事件名称={事件处理程序},比如:onClick={() => {}}
注意:React 事件采用驼峰命名法,比如:onMouseEnter、onFocus
事件对象,可以通过事件处理程序的参数获取到事件对象。React 中的事件对象叫做:合成事件(对象),兼容所有浏览器,无需担心跨浏览器兼容性问题。
// 函数组件事件处理 function FuncComEvent() { function clickHandle(e) { e.preventDefault() console.log('点我干嘛'); } return ( <a href='https://www.baidu.cn/' onClick={clickHandle}>点我</a> ) } ReactDOM.createRoot(document.getElementById('funcComEvent')).render(<FuncComEvent></FuncComEvent>) // 类组件事件处理 class ClassComEvent extends React.Component { clickHandle(e) { e.preventDefault() console.log('点我干嘛'); } render() { return ( <a href='https://www.baidu.cn/' onClick={this.clickHandle}>点我</a> ) } } ReactDOM.createRoot(document.getElementById('classComEvent')).render(<ClassComEvent></ClassComEvent>)
函数组件又叫做无状态组件,类组件又叫做有状态组件,状态(state)即数据:
状态(state)即数据,是组件内部的私有数据,只能在组件内部使用,state 的值是对象,表示一个组件中可以有多个数据:
this.state
来获取状态。this.setState({ 要修改的数据 })
来修改状态,setState() 的作用是修改 state 并更新UI,此思想是数据驱动视图。注意:不要直接修改 state 中的值,这是错误的!!!
JSX 中掺杂过多 JS 逻辑代码,会显得非常混乱。推荐将逻辑抽离到单独的方法中,保证 JSX 结构清晰。
注意:事件处理程序中 this 的值为 undefined。希望 this 指向组件实例(render方法中的this即为组件实例)。
class StateCom extends React.Component { // 构造方法 // constructor() { // super() // this.state = { // count: 0 // } // } // 简写,不使用构造方法 state = { count: 0 } // 事件处理程序 onDecrease() { // this 为 undefined this.setState({ count: this.state.count -1 }) } render() { // render 方法 this 为组件实例 return ( <div> <p>数据结果:{this.state.count}</p> <button onClick={() => { // 箭头函数 this 为定义时的 this 即为组件实例 // 修改 state this.setState({ count: this.state.count + 1 }) // 错误修改 state 的方法 // this.state.count++ }}>+1</button> {/* 从 JSX 中抽离事件处理程序 */} <button onClick={this.onDecrease}>-1</button> </div> ) } } ReactDOM.createRoot(document.getElementById('stateCom')).render(<StateCom></StateCom>)
1、利用箭头函数自身不绑定this的特点,render() 方法中的 this 为组件实例,可以获取到 setState()。
2、利用ES5中的bind方法,将事件处理程序中的this与组件实例绑定到一起。
3、利用箭头函数形式的class实例方法,该语法是实验性语法,但是由于babel的存在可以直接使用。
// 处理 事件中 this 指向 class EventThis extends React.Component { constructor() { super() this.state = { count: 0 } // 2、事件绑定 this 指向 this.onIncreaceTwo = this.onIncreaceTwo.bind(this) } onIncreaceOne() { this.setState({ count: this.state.count + 1 }) } onIncreaceTwo() { this.setState({ count: this.state.count + 2 }) } // 3、class 的实例方法 onIncreaceThree = () => { this.setState({ count: this.state.count + 3 }) } render() { return ( <div> <p>结果:{this.state.count}</p> {/* 1、通过箭头函数 */} <button onClick={() => this.onIncreaceOne()}>+1</button> <button onClick={this.onIncreaceTwo}>+2</button> <button onClick={this.onIncreaceThree}>+3</button> </div> ) } } ReactDOM.createRoot(document.getElementById('eventThis')).render(<EventThis></EventThis>)
推荐使用class的实例方法。
HTML 中的表单元素是可输入的,也就是有自己的可变状态,而 React 中可变状态通常保存在 state 中,并且只能通过 setState() 方法来修改。React 将 state 与表单元素值value绑定到一起,由 state 的值来控制表单元素的值。
受控组件就是其值受到 React 控制的表单元素,处理受控组件步骤:
// 受控组件 class ControlCom extends React.Component { constructor() { super() this.state = { title: '', content: '', city: 'bj', isChecked: 'true' } } // 处理 文本框、富文本框、下拉框、复选框 的变化 titleChange = e => this.setState({ title: e.target.value }) contentChange = e => this.setState({ content: e.target.value }) cityChange = e => this.setState({ city: e.target.value }) isCheckedChange = e => this.setState({ isChecked: e.target.checked }) render() { return ( <div> <input type='text' placeholder='请输入标题' value={this.state.title} onChange={this.titleChange}></input> <br/> <textarea placeholder='请输入内容' value={this.state.content} onChange={this.contentChange}></textarea> <br/> <select value={this.state.city} onChange={this.cityChange}> <option value='bj'>北京</option> <option value='sh'>上海</option> <option value='sz'>深圳</option> <option value='gz'>广州</option> </select> <br/> <input type='checkbox' checked={this.state.isChecked} onChange={this.isCheckedChange}></input> </div> ) } } ReactDOM.createRoot(document.getElementById('controlCom')).render(<ControlCom></ControlCom>)
个表单元素都有一个单独的事件处理程序处理太繁琐,可以使用一个事件处理程序同时处理多个表单元素,步骤如下:
// 受控组件 class ControlCom extends React.Component { constructor() { super() this.state = { title: '', content: '', city: 'bj', isChecked: true } } valueChage = e => { const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value this.setState({ [e.target.name]: value }) } render() { return ( <div> <p>优化受控组件</p> <input name='title' type='text' placeholder='请输入标题' value={this.state.title} onChange={this.valueChage}></input> <br/> <textarea name='content' placeholder='请输入内容' value={this.state.content} onChange={this.valueChage}></textarea> <br/> <select name='city' value={this.state.city} onChange={this.valueChage}> <option value='bj'>北京</option> <option value='sh'>上海</option> <option value='sz'>深圳</option> <option value='gz'>广州</option> </select> <br/> <input name='isChecked' type='checkbox' checked={this.state.isChecked} onChange={this.valueChage}></input> </div> ) } } ReactDOM.createRoot(document.getElementById('controlCom')).render(<ControlCom></ControlCom>)
借助于 ref,使用原生 DOM 方式来获取表单元素值,ref 的作用就是获取 DOM 或组件。使用步骤
// 非受控组件 class UncontrolCom extends React.Component { constructor() { super() // 1、调用 React.createRef() 方法创建一个 ref 对象 this.textRef = React.createRef() } render() { return ( <div> {/* 2、将创建好的 ref 对象添加到文本框中 */} <input type='text' ref={this.textRef}></input> <button onClick={this.getText}>获取文本</button> </div> ) } // 3、 通过 ref 对象获取到文本框的值 getText= () => { console.log('text: ', this.textRef.current.value); } } ReactDOM.createRoot(document.getElementById('uncontrolCom')).render(<UncontrolCom></UncontrolCom>)
class Comment extends React.Component { // 初始化状态 state = { count: 10, comments: [ { id: 1, name: 'jack', content: '沙发!!!' }, { id: 2, name: 'rose', content: '板凳~' }, { id: 3, name: 'tom', content: '楼主好人' } ], userName: '', userContent: '' } // 渲染评论列表: renderList() { const { comments } = this.state if (comments.length === 0) { return <div className='no-comment'>暂无评论,快去评论吧</div> } return comments.map(item => ( <li key={item.id}> <h4>评论人:{item.name}</h4> <p>评论内容:{item.content}</p> </li> )) } // 处理表单元素 formHandle = (e) => { const { name, value } = e.target this.setState({ [name]: value }) } // 添加评论 addComment = () => { const { userName, userContent } = this.state if (userName.trim() === '' || userContent.trim() === '') { alert('请输入评论人和评论内容!') return } const newComments = [{ id: Math.random(), name: userName, content: userContent }, ...this.state.comments] this.setState({ comments: newComments, userName: '', userContent: '' }) } render () { const { userName, userContent } = this.state return ( <div className='comment'> <div> <input className='user' type='text' placeholder='请输入评论人' value={userName} name='userName' onChange={this.formHandle}></input> <br /> <textarea className='content' cols='30' rows='10' placeholder='请输入评论内容' value={userContent} name='userContent' onChange={this.formHandle}></textarea> <br /> <button onClick={this.addComment}>发表评论</button> {this.renderList()} </div> </div> ) } } ReactDOM.createRoot(document.getElementById('comment')).render(<Comment></Comment>)
实现步骤:
1、渲染评论列表:
3、获取评论信息:使用受控组件方式处理表单元素
4、发表评论:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。