安装依赖
npm i react 核心包
npm i react-dom 渲染dom
npm i standealone 转义
//依次引入
注释
- 注释
const str = <h1>
{/*这是注释*/}
hello,react</h1>
- 声明多行标签
const div =
<div>
<h4>h4</h4>
<h4>h4</h4>
</div>
//或者
const div =
(<div>
<h4>h4</h4>
<h4>h4</h4>
</div>)
jsx中插入表达式
- 变量
- 函数
渲染数组
- 1 普通循环
let arr = [
<h4 key=1>h4</h4>,
<h4 key=2>h4</h4>,
<h4 key=3>h4</h4>,
<h4 key=4>h4</h4>
]
let array = (<div>
{arr}
</div>)
- 2 属性设置
let a="https://www.baidu.com";
let alt="点击我去百度";
let aa=<a href={a} title="123">{alt}</a>
- 3 样式设置
(jsx不能使用class属性,因为class属于js关键字,使用className替代)
let style = { color: "red" };
let sdiv = <p style={style}>嵌入式样式设置</p>
let sdiv1 = <p className="clname">类样式设置</p>
列表循环
// map()
let listarr = ["吃饭", "睡觉", "打豆豆1"]
let newDom = listarr.map((value, index) => {
return (
<p key={index}>{value}</p>
)
})
// for in 或者 forEach()
let listarr1 = ["吃饭1", "睡觉1", "打豆豆1"]
function fun() {
let newArr = [];
for (let i in listarr1) {
newArr.push(
(<p key={i}>{listarr1[i]}</p>)
);
}
return newArr;
}
组件化
- 无状态组件
// 无状态组件
function Db() {
return (
<p>p标签</p>
)
}
let dom1 =
<div>
<Db />
<Db />
<Db />
</div>
//父组件调用子组件
function Son() {
return ( <p>son组件</p> )
}
function Son1() {
return ( <p>son1组件</p> )
}
function Father() {
return (
<div>
<Son/>
<Son1/>
</div>
)
}
- 类组件
class Fn extends React.Component{
render(){
return (
<div>类组件</div>
)
}
}
props组件通信
- 传值
//props 无状态组件的通信
function ComDom(props) {
return (
<p>{props.text}</p>
)
}
ReactDOM.render(<ComDom text={"传值"} />, document.getElementById("root"))
//props 类组件的通信
class ClaDom extends React.Component {
render() {
return (
<div>{this.props.name}---------{this.props.sex}</div>
)
}
}
let obj = {
name: "小明",
sex: "男"
}
ReactDOM.render(<ClaDom {...obj} />,document.getElementById("root"))
- props默认值
//无状态组件的默认值
function ClaDom(props){
return (
<div>{props.sex}</div>
)
}
ClaDom.defaultProps={
name:"默认值",
sex:"12"
}
let obj={
name:"小明",
sex:"13"
}
//类组件的默认值
class ClaDom extends React.Component{
static defaultProps={
name:"第二种默认值"
}
render(){
return (
<div>{this.props.name}</div>
)
}
}
ReactDOM.render( <ClaDom />, document.getElementById("root"))
- 小例子
/*父传子组件,子组件渲染
点击父组件,控制子组件
*/
let flag=true;
let arr = ['猪八戒', '孙悟空', '沙和尚'];
function Son(props) {
return (
<div style={{display:flag==true? "block":"none"}}>
{
props.sonValue.map((v, i) => {
return (
<p key={i}>{v}</p>
)
})
}
</div>
)
}
function Father(props) {
return (
<div>
<p onClick={()=>{flag=!flag;render();console.log(flag)}}>西游记任务展示:</p>
<Son sonValue={props.arrs} />
</div>
)
}
function render(){
ReactDOM.render(<Father arrs={arr} />, document.getElementById("root"))
}
render();
state 状态
//state 状态
/**
props和state区别:
1、 props是组件的外部接口,state是组件的内部接口。
2、 props只读,state可读可写
*/
class Dom extends React.Component{
constructor(props){
super(props);
//使用this首先继承父类
this.state={
name:"嘻嘻"
}
}
render(){
return (
<div>
<p>{this.state.name}</p>
<button onClick={()=>{
this.setState({name:"哈哈!"})
}}>点击切换</button>
</div>
)
}
}
// this.setState({key:value},()=>{}); 是异步的,react会自动出发render函数进行再次渲染.第二个参数为回调参数。
ReactDOM.render(<Dom/>,document.getElementById("root"));
// state 异步和state状态的字符串识别为html
// 使用 dangerouslySetInnerHTML={{_html:"你要输入的html字符串"}}
class Two extends React.Component{
constructor(props){
super(props);
this.state={
name:"小明",
newHtml:"<p>我是一个p标签</p>"
}
}
//执行的匿名函数
fn=()=>{
this.setState({name:"小李子"},()=>{
console.log(this.state.name)
})
}
render(){
return(
<div>
<p>{this.state.name}</p>
<p>{this.state.newHtml}</p>
{/*__html: 是两个_*/}
<p dangerouslySetInnerHTML={{__html:this.state.newHtml}} ></p>
<button onClick={this.fn}>点击切换</button>
</div>
)
}
}
ReactDOM.render(<Two/>,document.getElementById("root"));
ref转发
(不能在无状态组件中使用,因为无状态组件没有实例)
(其实就是相当于Vue中的实例,回调函数返回的就是当前DOM)
react的三种方式引用ref
1、字符串的方式
2、回调函数(推荐) 形参作为DOM,并赋值给一个变量。
3、React.createRef() ( react16.3)
(把值赋值给一个变量,通过挂载在节点上,然后通过ref的current属性拿到这个节点)
//ref 转发
class Doms extends React.Component {
constructor(props) {
super(props);
this.myref=React.createRef();
}
fun = () => {
// console.log(this.refs.oneRef.value)
// console.log(this.values.value)
console.log(this.myref.current.value)
}
render() {
return (<div>
{/* <input readOnly ref="oneRef" type="text" value="123" />*/}
{/* <input ref={(newDom) => { this.values = newDom }} type="text" />*/}
<input ref={this.myref} type="text" />
<button onClick={this.fun}>获取value</button>
</div>
)
}
}
ReactDOM.render(<Doms />, document.getElementById("root"));
事件处理
//React事件处理 (绑定的事件采用小驼峰命名) 绑定的时间函数不能加(),因为会立即执行
/*
1、bind绑定this
2、constructor内提前绑定this
3、函数通过箭头函数创建
4、把事件的调用写成箭头函数的调用
*/
class Com extends React.Component{
constructor(props){
super(props);
this.funb=this.funb.bind(this);
}
funa(){
console.log(this)
}
funb(){
console.log(this)
}
func=()=>{
console.log(this)
}
fund(){ params
console.log(this)
}
// 参数传递
fune(params){
console.log(params)
}
funf(e,params){
console.log(e,params)
}
render(){
return (
<div>
<h1>React事件处理</h1>
<span>查看this:</span><br/>
<button onClick={this.funa.bind(this)}>bind绑定this</button><br/>
<button onClick={this.funb}>constructor内提前绑定this</button><br/>
<button onClick={this.func}>函数通过箭头函数创建</button><br/>
<button onClick={()=>{this.fund()}}>把事件的调用写成箭头函数的调用</button>
<h1>实参传递</h1>
<button onClick={this.fune.bind(this,"我是参数")}>bind绑定this</button><br/>
<button onClick={(e)=>{this.funf(e,"我是参数")}}>把事件的调用写成箭头函数的调用</button>
</div>
)
}
}
ReactDOM.render(<Com/>,document.getElementById("root"));
条件编译
//条件编译
/*
根据状态的变化渲染jsx中的内容,在jsx中不能使用if
*/
class Com extends React.Component {
constructor(props) {
super(props);
this.state = {
bool: false
}
}
fun = () => {
this.setState({ bool: !this.state.bool })
}
render() {
let text;
if (this.state.bool) {
text = "西瓜";
} else {
text = "香蕉"
}
return (
<div>
<p>{text}</p>
<p>{this.state.bool? "是":"不是"}</p>
<button onClick={this.fun}>查看state</button>
</div>
)
}
}
ReactDOM.render(<Com />, document.getElementById("root"));
状态提升
//状态提升
/*
概念:
多个组件需要反应相同的数据变化,可以提升到他们最近的一个父组件中
(两子个组件都要使用到的状态,叫做状态提升)
*/
class Demo1 extends React.Component{
constructor(props){
super(props)
}
render(){
return(
<div>
<p>我是第一个子组件——{this.props.text}</p>
</div>
)
}
}
class Demo2 extends React.Component{
constructor(props){
super(props)
}
render(){
return(
<div>
<p>我是第二个子组件——{this.props.text}</p>
</div>
)
}
}
class BigDemo extends React.Component{
constructor(props){
super(props)
this.state={
text:"公共的状态"
}
}
fun=()=>{
this.setState({text:"修改了公共的状态"});
}
render(){
return(
<div>
<Demo1 text={this.state.text}/>
<Demo2 text={this.state.text}/>
<button onClick={this.fun}>修改公共的状态</button>
</div>
)
}
}
ReactDOM.render(<BigDemo/>,document.getElementById("root"));
图片在脚手架中的三种引入以及根节点的三种写法
- 图片
1、在public中的文件可以直接使用:<img src="logo192.png" />
2、在src下的文件:import imgpath from "../asset/logo192.png" <img src={imgpath} />
3、<img src={require("../asset/logo192.png")} /> - 根节点
1、import React, { Component, Fragment } from "react" <Fragment></Fragment>
2、<div></div> 会存在实际的dom
3、<> </>
组件的传值
1、父传子
父:
<Son text={this.state.son} />
子接受:
<div>
我是子组件——{this.props.text}
</div>
2、子传父
子:
<button onClick={this.props.tofun.bind(this,"传给父组件的值")}>点击传给父组件</button>
父j接受:
<Son tofun={this.selffun} />
selffun = (value) => {
this.setState({ fdata: value })
}
3、同级组件传值
- npm install pubsub-js
//开始传参:
//抛出事件和参数
pubsub.publish("evt",text)
//接受到事件名称,和几个回调函数
pubsub.subscribe("evt", (msg, data) => {
this.setState({values: data})
console.log(msg, data)
//evt 给同级组件的值
})
数据请求与模拟
- 模拟数据使用 json-server npm install json-server -g
cd mock文件夹下
启动:json-server 模拟数据的名称(数组或对象) --port 4000
默认端口是3000 - axios 数据请求 npm install --save axios
解决跨域
1、正向代理——开发环境 (正向代理即是客户端代理, 代理客户端, 服务端不知道实际发起请求的客户端.)
2、反向代理——线上环境 (反向代理即是服务端代理, 代理服务端, 客户端不知道实际提供服务的服务端)
react-router-dom 路由
-
npm install react-router-dom
image.png
image.png - withRouter 高阶组件(HOC 参数是一个组件 返回的也是一个组件)
不是路由切换的组件也具有路由切换的三个属性 (location match history)
1、 监听路由变化
props.history.listen((link) => {
// console.log(link)
})
withRouter(App);
2、 路由传参
传参:
<NavLink to="/index02/参数值">点我去组件2</NavLink> |
<Route path="/index02/:id" component={Index02} />
接受:
componentDidMount(){
console.log(this.props.match.params.id)
}
3、编程式导航
跳转:
this.props.data.history.push("/index02")
接收:
componentDidMount(){
console.log(this.props.location.query.name)
}
4、声明式导航
<NavLink to={{pathname:"index03",query:{name:"小明"}}} >点我去组件3</NavLink>
hook
- hook是react16.7新特性,可以让无状态组件使用状态,状态的管理可以使用类组件/redux/hook等
1、useState();返回值是一个数组,第一个参数是状态,第二个参数是改变状态的函数
import React, { Component, useState } from 'react';
//单个状态值
//使用多个状态值 或者使用对象
//(声明多个)
function Home(props) {
let [val, setVal] = useState(0);
let [Bval, BsetVal] = useState({
vala: 1,
valb: 2,
valc: 3
});
return (
<div>
<span>{val}</span>
<div>{Bval.valb}</div>
<p onClick={() => { setVal(val + 1) }}>点击我状态值+1</p>
<p onClick={() => { BsetVal(Bval.valb + 1) }}>B点击我状态值+1</p>{/*无法修改状态值,只能声明多个useState*/}
</div>
)
}
export default Home;
redux
- redux是一个专门的状态管理库,(在Vue中也可以使用,但在react中使用的更多)
- 需求场景:
网友评论