目录
TODO1
React概述
React的使用
//引入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>
//创建react元素
//参数一 元素名称 参数二 元素属性 参数三 元素的子节点
const title = React.createElement('h1',null,'hello react')
// const title = React.createElement(
// 'p',
// { title: '我是标题',id:'p1'},
// 'hello react'
// React.createElement('span',null,'我是span节点')
// )
//渲染react元素 (仅针对web开发)
//参数一 要渲染的react元素 参数二 挂载点-》页面中指定的位置
ReactDOM.render(title,document.getElementById('root'))
React脚手架的使用
全局安装脚手架和npx安装脚手架的区别
全局安装
React脚手架的使用
npx安装
初始化项目
npx create-react-app my-app
启动项目
在项目的根目录下执行** 先cd项目
npm start
在脚手架中使用React
脚手架能够帮助我们自动刷新页面
//1.导入react和react-dom两个包(非script标签导入)使用es6中的模块化语法
import React from 'react'
import ReactDOM from 'react-dom'
//2. 调用React.createElement()方法创建react元素
const title = React.createElement('p',null,'hello react')
//3. 调用ReactDOM.render()方法渲染react元素到页面中
ReactDOM.render(title,document.getElementById('') //挂载点
脚手架文件介绍
脚手架文件介绍
JSX
1. JSX的基本使用
1.1 为什么用JSX
React.createElement()过于繁琐不简洁 -》和用模板字符串一样
1.2 JSX简介
1.3 使用步骤
//1.使用JSX语法创建 React元素
const title =<h1> hello jsx</h1>
//2.使用ReactDOM.render()方法渲染react元素到页面中
ReactDOM.render(title,root)
1.4 脚手架中能用JSX
1.5 注意点
2. 在JSX中使用JavaScript表达式
2.1 嵌入js表达式
2.2 注意点
const sayHi=() => 'Hi'
const title =(
<h1>可以使用任意的函数表达式</h1>
<span>{1}</span>
<span>{'a'}</span>
<span>{1+2}</span>
<span>{3>5?1:0}</span>
<span>{sayHi()}</span>
)
const h1=<h1>cc</h1>
const div=(
<div> JSX自身也是js表达式 {h1} </div>
)
3.JSX的条件渲染
//if else
const loadData=() =>{
if(isLoading){
return <div>数据加载中 请稍后 </div>
}
return (
<div>数据加载完成,这里显示的是数据</div>
)
}
const div=(
<div>
{loadData()}
</div>
)
//三元表达式
const loadData =() =>{
return isLoading ?(<div>数据加载中</div>) :(<div>数据加载完成,这里显示的是数据</div>)
}
//逻辑与运算符 --适合要么展示 要么隐藏
const loadData=() =>{
return isLoading &&( <div> loading</div>)
}
const div=(
<div>
{loadData()}
</div>
)
4.JSX的列表渲染
const targets =[
{id:1,name:'react基础'},
{id:2,name:'react进阶'},
{id:3,name:'git+移动端开发+模块化'},
]
const list =(
<ul>
{targets.map(item=> <li key={item.id>{item.name}</div>)}
</ul>
)
5.JSX的样式处理
5.1 行内样式 style
//看起来像双括号 但实际上不是 外侧的表示嵌入对象
<h1 style={{color:'red',backgroundColor: 'skyblue'}}>
jsx样式处理
</h1>
5.2 类名 className
<h1 className="title">
jsx样式处理
</h1>
//要注意引入css文件
import 'index.css'
TODO2
组件
1.组件介绍
2.组件的两种创建方式
2.1 使用函数创建组件
函数组件:使用js的函数(或箭头函数)创建的组件
//函数名称必须以大写字母开头
function Hello() {
return (
<div>函数组件是必须有返回值的,表示该组件的结构,返回值为null表示不渲染任何结构</div>
)
}
//渲染函数组件 -》用函数名作为组件标签名
//组件名要大写的原因是 react据此区分普通组件和 react元素
//组件标签名 可以是单标签 也可以是双标签
//箭头函数创建组件
const Hello =() => (<div>函数组件</div>)
ReactDOM.render(<Hello />,root)
2.2 使用类创建组件
类组件:使用ES6的class创建的组件
//类名必须用大写字母开头
//继承React.Component父类
class Hello extends React.Component{
//必须提供render()方法
render() {
//必须有返回值 表示该组件的结构
return (
<div>类组件</div>
)
}
}
ReactDOM.render(</Hello>,root)
2.3 将组件抽离为单独的js文件
每个组件放到单独的js文件中
//Cc.js
import React from 'react'
class Cc extends React.Component{
render() {
return (<div> 啊啊啊啊</div>)
}
}
//导出组件
export default Cc
//index.js
//导入组件
import Cc from '路径'
//渲染导入的组件
ReactDOM.render(<Cc />, document.getElementById('root'))
事件处理
1.事件绑定
//类创建
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'))
2.事件对象
class App extends React.Component{
handleClick(e){
e.preventDefault()
}
render(){
return(
<a href="" onClick={this.handleClick}>我没加链接</a>
)
}
}
//渲染组件
ReactDOM.render(<App/>,document.getElementById('root'))
3.有状态组件和无状态组件
4.state和setState()
4.1 state的基本使用
- state是组件内部的私有数据,只能在组件内部使用
- state的值是对象 表示一个组件中可以有多个数据
如何使用state
class Cc extends React.Component {
//es6 class语法
constructor(){
super() //必须有 是es6的要求
//初始化state
this.state ={
count :0
}
}
//简洁版 实验性的public class fields语法
state = {
count :0
}
render(){
return (
<div>
有组件状态
</div>
)
}
}
①super()函数用于访问和调用一个对象上的父对象上的函数
②在构造函数中使用时,super关键字将单独出现,并且必须在使用this关键字之前使用。
super关键字也可以调用父对象上的函数。
③ES6 class语法拯救世界了吗 为什么要用它(?)
4.2 setState修改状态
this.setState({
count:this.state.count + 1
})
//错误的
this.state.count += 1
4.3 从JSX中抽离事件处理程序
this指向
1.箭头函数
①箭头函数自身不绑定this
②render方法中的this为组件实例,可以获取到setState()
箭头函数中的this指向
class Cc extends React.Component{
onIncrement(){
this.setState({ })
}
render(){
//箭头函数中的this指向外部环境,此处为:render() 方法
return (
<button onClick={() => this.onIncrement()}></button>
)
}
}
2.Function.prototype.bind()
class Cc extends React.Component{
constructor() {
super()
this.onIncrement = this.onIncrement.bind(this)
}
//省略onIncrement
render(){
return (
<button onClick={this.onIncrement()}></button>
)
}
}
3.class的实例方法
①利用箭头函数形式的class实例方法
②该语法是实验性语法 但是由于babel的存在可以直接用(编译JSX的语法包)
class Cc extends React.Component{
onIncrement =() =>{
this.setState({...})
}
render(){
return (
<button onClick={this.onIncrement()}></button>
)
}
}
4.总结
推荐使用的顺序 class的实例方法>箭头函数>bind
表单处理
1.受控组件
推荐使用受控组件来处理表单
//1.在state中添加一个状态 作为表单元素的value值(控制表单元素值的来源)
state={txt:''}
//2.给表单元素绑定change事件,将表单元素的值设置为state的值(控制表单元素值的变化)
<input type="text" value={this.state.txt}
onChange ={e => this.setState({ txt : e.target.value })}
/>
多表单元素优化步骤
<input
type="text"
name="txt" //区分其他表单元素 名称与state相同
value={this.state.txt}
onChange={this.handleForm}
/>
//根据表单元素类型获取值
const value=target.type === 'checkbox'
?target.checked
:target.value
//根据name设置对应的state
this.setState({
//es6的属性表达式
[name]:value
})
2.非受控组件
//1.调用
constructor() {
super()
this.txtRef = React.createRef()
}
//2.将ref添加到文本框
<input type="text" ref={this.txtRef} />
//3.通过ref对象获取到文本框的值
console.log{this.txtRef.current.value}
//实践
class App extends React.Component{
constructor() {
super()
this.txtRef = React.createRef()
}
//获取文本框的值
getTxt =() =>{
console.log('文本框的值为:', this.txtRef.current)
}
render(){
return(
<div>
<input type="text" ref={this.txtRef} />
<button onClick={this.getTxt}获取文本框的值</button>
</div>
)
}
}
完全利用js语言的能力创建组件,这是React的思想
TODO3
组件通讯
1.组件通讯的定义
因为组件时独立且封闭的单元,默认情况下,只能使用组件自己的数据,在组件化的过程中,我们要将完整的功能拆分为多个组件,这里需要共享一些数据,所以应该让组件与外界进行“通讯”
2.组件通讯的三种方式
2.1 父组件 ->子组件
①父组件提供要传递的state数据
②给子组件标签添加属性,值为state中的数据
③子组件通过props接收父组件传递的数据
2.2 子组件 ->父组件
思路:利用回调函数,父组件提供回调,子组件调用。将要传递的数据作为回调函数的参数。
①父组件提供一个回调函数(用于接收数据)
②将该函数作为属性的值,传递给子组件。
③子组件通过props调用回调函数。
④将子组件的数据作为参数传递给回调函数。
2.3兄弟组件
将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态
思想:状态提升
公共父组件职责 1.提供共享状态 2.提供操作共享状态的方法
要通讯的子组件只需要通过props接收状态或操作状态的方法
props
props深入
children属性
1.表示组件标签的子节点,当组件标签有子节点时,props就会有该属性、
2.children属性与普通的props一样,值可以是任意值(文本,React元素,组件,函数)
function Hello {props}{
return {
<div>
组件的子节点:{props.children}
</div>
}
}
<Hello> 我是子节点 </Hello>
props校验
1.因为对于组件来说,props是外来的,无法保证组件使用者传入什么格式的数据
2.如果传入数据不对,会导致组件内部报错,且组件的使用者不知道明确的错误原因。
3.添加props校验,允许在创建组件的时候,就指定props的格式和类型。捕获使用组件时因为props导致的错误,增加组件的健壮性。
步骤
1.安装prop-types包
2.导入prop-type是包
3.使用组件名.propTypes={}给组件的props添加校验规则
4.校验规则通过PropTypes对象来指定
约束规则
1.常见类型:array bool func number object string
2.React元素类型 :element
3.必填项:isRequired
4.特定结构的对象: shape({})
//添加props校验
App.propTypes={
a:propTypes.number,
fn:propTypes.func.isRequired,
tag:PropTypes.element,
filter:PropTypes.shape({
area:PropTypes.string,
price:PropTypes,number
})
}
props默认值
场景:分页组件-》每页显示条数
作用:给props设置默认值,在未传入props时生效
App.defaultProps ={
pageSize:10
}
Context
跨多个组件传递数据 (eg 主题 语言)
Context提供了两个组件 Provider -》用来提供数据和Consumer-》用来消费数据
//1.调用React.creatContext() 创建Provider 和Consumer 两个组件
const { Provider,Consumer} = React.createContext()
//2.使用Provider组件作为父节点
<Provider>
<div className="App">
<Child1 />
</div>
</Provider>
//3.设置value属性,表示要传递的数据
<Provider value="pink">
//4.调用Consumer 组件接收数据
<Consumer>
{data => <span>data 参数表示接收到的数据 --{data}</span>
</Consumer>
React 官方中文文档