1.构建项目
- npm install create-react-app 安装脚手架
安装失败,解决方法:
//换源
npm config set registry https://registry.npm.taobao.org
//配置后通过以下方法验证是否成功
npm config get registry - create-react-app react-demo 创建项目react-demo
- cd react-demo
- npm i
- npm start 项目启动
2.定义组件
- 使用函数定义组件
import React from 'react'
import ReactDom from 'react-dom'
使用函数定义组件
const App1=(props)=>{
return <h1>{props.title}</h1>
}
ReactDom.render(
<App1 title="app1"></App1>,
document.querySelector('#root')
)
- 使用类定义组件
import React from 'react'
import ReactDom from 'react-dom'
//使用类定义组件
class App2 extends React.Component{
render(){
return (
<div>
<h1>{this.props.desc}</h1>
</div>
)
}
}
ReactDom.render(
<App2 desc="类组件是继承react.Component"/>,
document.querySelector('#root')
)
3.组件中的样式
- 使用style内联style={{color:“red”}}
- 增加index.css里面写样式text-style,index.js中使用className=“text-style”
- 使用第三方包classNames。npm i classnames -s.
- 使用styled。npm i styled-components -s。styled.元素名 模板字符串中写样式
import React from 'react'
import ReactDom from 'react-dom'
import classNames from 'classnames'
import styled from 'styled-components'
import './index.css'
//使用类定义组件
const style={color:'red'}
const title=styled.h1`
color:#f00
`
class App2 extends React.Component{
render(){
return (
<div>
<h1>{this.props.desc}</h1>
<ol>
<li style={style}>使用style内联样式</li>
<li className="text-style">使用className的方式</li>
<li className={classNames('a',{'b':true,'c':false})}>动态添加不同的className可使用第三方包classNames</li>
</ol>
</div>
)
}
}
ReactDom.render(
<App2 desc="类组件是继承react.Component"/>,
document.querySelector('#root')
)
4.组件的创建
- 下载vscode插件
- 新建App.js.直接输入rcc创建出class定义组件的模板,输入rfc创建出函数定义组件的模板
- 在APP.js中先用rcc即先用class创建一个组件。别忘了在index.js中导入
App.js
import React, { Component } from 'react'
export default class App extends Component {
render() {
return (
<div>
<h1>创建我的第一个组件</h1>
</div>
)
}
}
index.js
import React from 'react'
import ReactDom from 'react-dom'
import App from './App.js'
ReactDom.render(
<App/>,
document.querySelector('#root')
)
5.公共组件的管理
目录结构。在components下创建文件index.js用于统一导出组件,这样在APP.js中引入是只需引入components下的index.js文件就可以 了,这样避免大量导入各种组件。
每次引入时如果文件名是index.js则写他的上级目录就自动查找到,例如
import {TodoHeader} from ‘./components’====import {TodoHeader} from ‘./components/index.js’
6.根标签
在return()中只能允许一个根标签。
- 元素外层加入div。缺点增加了多于的div标签
- 元素外层加入Fragment标签。需要先引入
import React, { Component,Fragment} from ‘react’. - 元素外加空的<></>
7.数据传递
- 函数创建的组件通过props传递
- 类创建的组件通过this.props传递
8.state
函数组件又叫无状态组件,类组件又叫有状态组件
类组件state有两种写法,一种直接state={},另一种写在构造函数constructor里
修改state用setState({}),里面传对象或方法
import React, { Component } from 'react'
export default class Like extends Component {
constructor(){
super()
this.state={
isLiked:true
}
}
handClick=()=>{
//方法一setState里使用对象
// this.setState({
// isLiked:!this.state.isLiked
// })
//方法二使用异步方法
this.setState((prevState)=>{
return{
isLiked:!prevState.isLiked
}
},()=>{
//由于setState是异步的,如果想要获取到最新的state,应该在这个回调里来获取
console.log(this.state.isLiked)
})
}
render() {
return (
<div>
<span onClick={this.handClick}>
{
this.state.isLiked?'yes':'no'
}
</span>
</div>
)
}
}
8.事件
事件用箭头函数写,若不用箭头函数,则用bind绑定this对象,传参也用bind
import React, { Component,createRef } from 'react'
export default class index extends Component {
constructor(){
super()
this.state={
inputValue:''
}
this.inputDom=createRef()
}
//输入框
handInput=(e)=>{
console.log(e)
this.setState({
inputValue:e.currentTarget.value
})
}
//添加按钮
handAddClick(){
this.props.addTodo(this.state.inputValue)
this.setState({
inputValue:''
},()=>{
this.inputDom.current.focus()
})
}
//键盘事件
handKeyUp=(e)=>{
if(e.keyCode===13){
this.handAddClick()
}
}
render() {
return (
<div>
{this.props.title}
<input type="text"
value={this.state.inputValue}
onChange={this.handInput}
onKeyUp={this.handKeyUp}
ref={this.inputDom}
></input>
<button onClick={this.handAddClick.bind(this,3434)}>add</button>
</div>
)
}
}
9. react-hooks
常用api.useState和useEffect
import React ,{useState,useEffect}from 'react'
export default function TodoHeader(props) {
//useState是一个方法,这个方法的参数是一个默认值,结果是一个数组,数组的第一个就是初始值,第二个相当于setState
//解构出来数组中的两个值
const [count,setCount]=useState(0)
//useEffect是一个回调,不管是组件挂载还是更新都会触发回调方法,类似于componentDidMount和componentDidUpdate
useEffect(() => {
console.log('更新了')
})
return (
<div>
<button onClick={()=>{setCount(count-1)}}>-</button>
<span>{count}</span>
<button onClick={()=>{setCount(count+1)}}>+</button>
</div>
)
}
10.路由
npm install react-router-dom
在index.js中导入BrowerRouter或者HashRouter,其中HashRouter为带#的路由。在入口文件写Router组件,则其他地方不用写
import React from 'react'
import ReactDom from 'react-dom'
import App from './App.js'
//路由
import {HashRouter as Router,Route} from 'react-router-dom'
ReactDom.render(
<Router>
<Route component={App} path='/'/>
</Router>,
document.querySelector('#root')
)
)
App.js.导入Route组件。Link组件为点击跳转.Route中的组件传递参数可用render
import React, { Component} from 'react'
import {Like} from './components'
import {Route,Link} from 'react-router-dom'
export default class App extends Component {
render() {
return (
<div>
//<Route component={Like} path='/like'></Route>
<Route path='/path' render={(routeProps)=>{
return <Like x={1}/>
}}>
<ul>
<li><Link to='/like'>like页面入口</Link></li>
</ul>
</div>
)
}
}
除了用Link组件进行点击跳转,还可用事件
组件中onClick={this.goHome}
goHome=()=>{
this.props.history.push(’/home’)
}