基本语法
react对js语法进行了扩展,发明了jsx语法,通过babel转换成js语法而被浏览器认识。
想要使用jsx一定要先引入react:
//引入react
import { Component } from 'react';
import { render } from 'react-dom';
import './Student.css'
//这里以class组件为例子
class Student extends Component{
constructer(props){
super(props)
//组件的状态
this.state = {
age:16,
class:'lisi',
isShow:false
}
}
//通过入口函数render来返回jsx
render(){
return (
{/*可以进行条件判断if..else.. 、三元运算符等*/}
let showSubmitBtn = null
if(this.state.isShow){
showSubmitBtn = (<button>点击</button>)
}else{
showSubmitBtn =(<span>...</span>)
}
<div>
{/*点击事件onClick 所有的变量都要用{}包裹起来*/}
<div onClick={changeAge}>{this.state.age}</div>
{/*这里的传递参数:data- 样式名:className*/}
<div data-name="lizi" onClick={changeName} className='AgeCalss'>
{this.state.name}
</div>
{showSubmitBtn}
</div>
)
}
changeAge = () =>{
//修改数据使用setState
this.setState({
age:18
})
}
changeName = (e) =>{
//jsx上传递过来的数据
//console.log(e.target.dataset.name)
this.setState({
name:e.target.dataset.name
})
}
}
//渲染到root
render(
<Student />,
document.getElementById('root)
)
{}里面可以是基本数据类型String、Number...,也可以使dom节点(<button>按钮</button>),还可以是声明的节点变量let el = (<button>按钮</button>)
react事件
- 事件名驼命名
- 必须有个{} 传入一个函数
<button onClick={()=>{this.props.changeFun(this.state.curtitle)}}>点击向父元素传递数据</button>
事件对象:react 返回的事件对象是代理的原生的事件对象,如果想要查看事件对象的具体值,必须之间输出事件对象的属性
原生:阻止默认行为,可以直接返回return false
react 中阻止默认行为,e.preventDefault()
react 事件中传参:
如果需要获取事件对象就像下面这样使用,如果不需要获取事件对象就直接this.preventEvent
<button onClick={(e)=>this.preventEvent('msg',e)}></button>
列表渲染
将列表内容拼装成数组,放置到模板中,将数据拼装成数组的jsx对象,使用数组的map方法 对每一项数据按照jsx的形式进行加工,最终得到一个每一项都是jsx对象的数组,再将数组渲染到模板中
这里要注意key值放置到每一项中否侧会报错(组件的话放在组件上)
class Father extends Component{
constructor(props){
super(props)
this.state = {
users:[
{name:'lisi',age:'25'},
{name:'zhangsan',age:'26'},
{name:'wangwu',age:'27'},
]
}
}
render(){
return(
<div>
{this.state.users.map((item,index)=>{
return (<p key={index}>{item.name}:{item.age}</p>)
})}
</div>
)
}
}
生命周期
生命周期:组件从实例化到渲染到最终从页面销毁
整个过程就是生命周期,在生命周期中有许多可以调用的事件,俗称钩子函数
3个状态
Mounting:将组件插入到DOM中Updating:将数据更新到dom中Unmounting: 将组件移除到dom中
生命周期中的钩子函数(方法、事件)
ComponentWillMount:组件将要渲染 ajax,添加动画前的类ComponentDidMount:组件渲染完毕 添加动画ComponentWillReceiveProps:组件将要接收props数据 查看接收props的数据是ShouldComponentUpdate:组件接收到新的state或者props判断是否更新,返回布尔值ComponentWillUpdate:组件将要更新ComponentDidUpdate:组件已经更新ComponentWillUnmount: 组件将要卸载
class Lifecom extends Component{
constructor(props){
super(props) //调用继承Component的构造函数
this.state ={msg:'123'}
}
componentWillUnmount(){
console.log('组件将要渲染');
}
componentDidMount(){
console.log('组件渲染完毕');
}
componentWillReceiveProps(props){
console.log('组件将要接收props数据:'+props.Pmsg);
this.setState({
msg:props.Pmsg
})
}
shouldComponentUpdate(){
console.log('组件接收到新的state或者props判断是否更新,返回布尔值')
return true
}
componentWillUpdate(){
console.log('组件将要更新');
}
componentDidUpdate(){
console.log('组件已经更新');
}
componentWillUnmount(){
console.log('组件将要卸载');
}
render(){
return (
<div>{this.props.Pmsg}</div>
)
}
}
组件
无状态组件
即函数式组件
//clothes.js
//函数式组件返回dom
function clothes(props){
return (<div>black shirt</div>)
}
export default clothes;
类组件
import { Component } from 'react';
//组件继承Component
class Index extends Component {
render() {
return (
<div>
</div>
);
}
}
export default index;
组件间通信
父传子
通过props传递参数
//Father
import { Component } from 'react';
class Father extends Component {
render() {
return (
<div>
<Son name='传递数据' />
</div>
);
}
}
//Son.js
const Son = (props) =>{
return (<div>{props.name}</div>)
}
子传父
//Father
import { Component } from 'react';
class Father extends Component {
render() {
return (
<div>
<Son fatherback={this.fatherback} />
</div>
);
}
fatherback = (msg) =>{
console.log(msg)
}
}
//Son.js
const Son = (props) =>{
return (<div onClick={()=>props.fatherback('子组件数据')}>点击之后向父组件传递参数</div>)
}
全局状态管理redux
解决react 数据管理,用户大中型项目,数据比较庞大时候组件之间数据交互多的情况下使用, 若果你不知道是否需要redux那么你就不需要用他。
- 解决组件的数据通信
- 解决数据和交互较多的应用
redux只是一种状态管理的解决方案
store:数据仓库,保存数据的地方state:是一个对象,数据仓库里面的数据都放到一个state里面action: 一个动作,触发数据改变的方法reducer:是一个函数,通过获取动作改变数据,生成一个新的state,从而改变页面
在使用之前可以先安装调试工具:redux devtools
npm install redux react-redux --save
index.js
//provider包裹在根组件外层,使所有的子组件都可以拿到state
import { Provider } from "react-redux";
import { render } from 'react-dom';
// 创建仓库
import store from "./store";
// 业务逻辑
import Myapp from "./Myapp";
const app = (
<Provider store={store}>
<Myapp />
</Provider>
)
render(
app,
document.getElementById('root')
)
store.js
import { createStore } from "redux";
//初始化数据,处理数据的地方
import reducer from "./component/reducer";
//创建仓库
const store = createStore(
reducer,
//加上这句话为了唤起调试工具redux devtools
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
export default store;
reducer.js
const defaultState = {
inoutval:0,
list:[
{id:1,title:'看不懂操作'}
]
}
const fun = (state=defaultState,action) => {
console.log(action);
//判断action.type 来处理数据
switch (action.type) {
case "add_val":
state.inoutval++
break;
case "dec_val":
state.inoutval--
break;
default:
break;
}
//防止数据前后数据相同不进行触发
return {...state}
}
export default fun;
Myapp.js
import React, { Component } from 'react';
//把 React 组件和 Redux 的 store 真正连接起来
import { connect } from "react-redux";
class Myapp extends Component {
constructor(props){
super(props)
}
render() {
return (
<div>
//所有redux管理的数据通过props获取
<p>这里展示数据:{this.props.inoutval}</p>
<button onClick={this.props.changeClick}>改变数据</button>
</div>
);
}
}
//这个函数允许我们将`store`中的数据作为`props`绑定到组件上
const mapStateToProps = ((state)=>{
return {
//获取state上的数据
inoutval:state.inoutval
}
})
//action`作为`props`绑定到`Myapp`上
const mapDispatchToProps = ((dispatch)=>{
return {
changeClick(){
//定义调用type为* 的方法的参数
const action = {
type:'add_val',
value:1
}
dispatch(action)
}
}
})
export default connect(mapStateToProps, mapDispatchToProps)(Myapp)
想要详细了解connect的同学可以看看这位大兄弟的文章
react 插槽
与vue直接提供一个slot不同,react的插槽功能需要自己来实现
//父组件
class Father extends Component {
render() {
return (
<Child>
{/* 我们想要在子组件展示这些内容 */}
<h1 data-index="1">这是H1</h1>
<h2 data-index="2">这是H2</h2>
<h3 data-index="3">这是H3</h3>
<h4 data-index="4">这是H4</h4>
</Child>
)
}
}
//子组件
class Child extends Component {
constructor(props){
super(props)
}
render() {
let H1,H2,H3,H4;
console.log(this.props.children);
this.props.children.forEach(item=>{
if(item.props['data-index']==='1'){
H1 = item
}else
if(item.props['data-index']==='2'){
H2 = item
}else
if(item.props['data-index']==='3'){
H3 = item
}else
if(item.props['data-index']==='4'){
H4 = item
}
})
return (
<div>
<div>在这里展示插槽</div>
<span>H1</span>
{H1}
<span>H2</span>
{H2}
<span>H3</span>
{H3}
<span>H4</span>
{H4}
</div>
)
}
}
react 路由
npm install react-router-dom --save
//index.js
import { BrowserRouter as Router, Link, Route, Routes } from 'react-router-dom';
import List from "./component/list.js";
import Detail from "./component/detail.js";
class RouterDom extends Component {
render() {
let pathObj = {pathname:'/user',search:'?username=admin',hash:'#abc',state:{msg:'helloworld'}}
// console.log(User);
return (
<div>
<Router>
<Routes>
<Route path='/user' element={<div>user</div>}></Route>
</Routes>
</Router>
{/**
* basename:设置路由的根路径
* */}
<Router basename='/admin'>
<div>
<Link to='/'>index</Link>
<Link to='/home'>home</Link>
<Link to={ pathObj }>user</Link>
<Link to='list'>list</Link>
</div>
{/**
* 所有的路由要包含在routes节点中
*/}
<Routes>
{/**exact 精确匹配
*
*/}
{/**
* element 属性用来展示我们当前第值展示的组件内容
*
*/}
<Route path='/' exact element={<h1>INDEX</h1>}></Route>
<Route path='/home' exact element={<h2>HOME</h2>}></Route>
<Route path='/list' exact element={ <List /> }></Route>
<Route path='/list/:id' exact element={ <Detail /> }></Route>
</Routes>
</Router>
</div>
)
}
}
// list.js
import React from 'react';
import { Link, useNavigate } from "react-router-dom";
function List() {
let list = [
{ name: 'lisi', id: 1 },
{ name: 'zhangsan', id: 2 }
]
//自定义跳转
const to = useNavigate()
return (
<div>
{list.map(item => {
return (
<Link key={item.id} to={'/list/' + item.id}>{item.name}</Link>
)
})}
<hr />
{list.map(item => {
return (
<button key={item.id} onClick={() => {
to('/list/' + item.id, { state: item })
}}>{item.name}</button>
)
})}
</div>
);
}
//detail.js
import React from 'react';
//获取路径参数
import { useParams, useLocation } from "react-router-dom";
function Detail() {
const params = useParams();
const userlocation = useLocation()
console.log(params);
console.log(userlocation);
return (
<div>
<div>
详情
params:
{params.id}
<hr />
location:
{userlocation.state.name}
</div>
</div>
);
}
以上就是整里的react基础知识点,当然现在react主推Hooks,不过class组件官方表示没有干掉的意思,更期待组合使用。