当前位置: 首页 > news >正文

react学习笔记,ReactDOM,react-router-dom

react 学习

1. 下载与安装

下载

npm install -g create-react-app

安装

npx create-react-app xxx 推荐

npm init react-app xxx

yarn create react-app xxx

2. 创建 react 元素 indexjs 文件

import React from "react";
import ReactDOM from "react-dom";
// 1创建react元素const title = React.createElement("h1", null, "1111111hello word");
ReactDOM.render(title, document.getElementById("root"));// 2创建react元素
import React from "react";
import ReactDOM from "react-dom";const title = <h1>helloword</h1>;ReactDOM.render(title, document.getElementById("root"));

3. 类名

class => className

const title =

helloword 1111111111

4. 组件

import React from "react";
import ReactDOM from "react-dom";function Hello() {return <div>111111111111111zujian1</div>;
}const Hello = () => <div>188888888811zujian1</div>;ReactDOM.render(<Hello></Hello>, document.getElementById("root"));
### 组件拆分

index.js


import Hello from './components/Hello'ReactDOM.render(<Hello></Hello>, document.getElementById('root'))

Hello.js


import React from "react";class Hello extends React.Component {render() {return (<div>hello组件</div>)}
}export default Hello

5. 继承

 // 继承import React from "react";import ReactDOM from "react-dom";class Hello extends React.Component {render() {return (<div>111111111class继承</div>)}}ReactDOM.render(<Hello></Hello>, document.getElementById('root'))//组件式
//1   Hello.jsimport React from "react";class Hello extends React.Component {render() {return (<div>hello组件</div>)}
}export default Hello//2   index.js
import Hello from './components/Hello'ReactDOM.render(<Hello></Hello>, document.getElementById('root'))

6. 点击事件

class Hello extends React.Component {handOlick() {console.log("点击触发");}render() {return <button onClick={this.handOlick}>点击</button>;}
}ReactDOM.render(<Hello></Hello>, document.getElementById("root"));
function Hello() {function handclick() {console.log("点击触发;1");}return <button onClick={handclick}>点击</button>;
}ReactDOM.render(<Hello></Hello>, document.getElementById("root"));

7. 阻止默认事件

class Hello extends React.Component {handclick(e) {e.preventDefault(); // 阻止默认跳转   阻止a标签的默认跳转console.log("点击触发了");}render() {return (<a href="http://www.baidu.com" onClick={this.handclick}>跳转</a>);}
}ReactDOM.render(<Hello></Hello>, document.getElementById("root"));

8. state

class Hello extends React.Component {// constructor() {//   super()//   this.state = {//     num: 0//   }// }// 简化state = {num: 1,};render() {return <div>state使用 {this.state.num}</div>;}
}ReactDOM.render(<Hello></Hello>, document.getElementById("root"));

9. setState

class Hello extends React.Component {// 简化state = {num: 1,};render() {return (<div><div>state使用 {this.state.num}</div><buttononClick={() => {this.setState({ num: this.state.num + 1 });}}>+1</button></div>);}
}ReactDOM.render(<Hello></Hello>, document.getElementById("root"));
箭头函数;
class Hello extends React.Component {// 简化state = {num: 1,};onIncrement = () => {this.setState({ num: this.state.num + 1 });};render() {return (<div><div>state使用222 {this.state.num}</div>{/* 2强制改变this */}<button onClick={this.onIncrement}>+1</button></div>);}
}

10 改变 this 指向

// p31 强制改变this   用consturctorclass Hello extends React.Component {// 简化// state = {//   num: 1// }constructor() {super();this.state = {num: 1,};this.onIncrement = this.onIncrement.bind(this);}onIncrement() {this.setState({ num: this.state.num + 1 });}render() {return (<div><div>state使用222 {this.state.num}</div>{/* 2强制改变this */}<button onClick={this.onIncrement}>+1</button></div>);}
}ReactDOM.render(<Hello></Hello>, document.getElementById("root"));

11. 表单处理

受控组件

// 受控组件class Hello extends React.Component {state = {txt: "",content: "",};handlerChange = (e) => {this.setState({txt: e.target.value,});console.log(e.target.value);console.log(this.state.txt);};handlarComtent = (e) => {this.setState({context: e.target.value,});};render() {return (<div><inputtype="text"value={this.state.txt}onChange={this.handlerChange}></input><textareavalue={this.state.content}onChange={this.handlarComtent}></textarea></div>);}
}

多表单元素优化

// 多表单元素的优化class Hello extends React.Component {state = {txt: "",content: "",};handlerForm = (e) => {const target = e.target;const value = target.type === "checkbox" ? target.cheched : target.value;const name = target.name;this.setState({[name]: value,});console.log(value);console.log(name);console.log(e.target.value);console.log(this.state.txt);};render() {return (<div><inputtype="text"value={this.state.txt}onChange={this.handlerForm}></input><textareavalue={this.state.content}onChange={this.handlerForm}></textarea></div>);}
}ReactDOM.render(<Hello></Hello>, document.getElementById("root"));

非受控组件

非受控组件;class Hello extends React.Component {constructor() {super();this.txtRef = React.createRef();}getTxt = () => {console.log("文本框" + this.txtRef.current.value);};render() {return (<div><input type="text" ref={this.txtRef}></input><button onClick={this.getTxt}>获取文本框值</button></div>);}
}ReactDOM.render(<Hello></Hello>, document.getElementById("root"));

12. 组件基础案例

class Hello extends React.Component {state = {txt1: "",txt2: "",list: [{id: "1",name: "jack",content: "111111",},{id: "2",name: "jack666666",content: "222222",},{id: "3",name: "jack999999965666",content: "333333",},],};btn = () => {console.log(111);};//优化renderList() {return this.state.list.length === 0 ? (<div>暂无评论</div>) : (<ul>{this.state.list.map((item) => {return (<li key={item.id}>评论人{item.name} <br></br> 内容{item.content}</li>);})}</ul>);}handleForm = (e) => {const { name, value } = e.target;this.setState({[name]: value,});};add = () => {const { list, txt1, txt2 } = this.state;// 去除首尾空格  如果空  就提示   下面代码不执行if (txt1.trim() === "" || txt2.trim() === "") {console.log("请输入name或者content");return;}const newList = [{id: new Date().getTime(),name: txt1,content: txt2,},...list,];console.log(newList);// 更新state状态this.setState({list: newList,});// 清空文本框this.setState({txt1: "",txt2: "",});};render() {const { txt1, txt2 } = this.state;return (<div><inputtype="text"onChange={this.handleForm}value={txt1}placeholder="请输入评论人"name="txt1"></input><textareaonChange={this.handleForm}value={txt2}name="txt2"></textarea><button onClick={this.add}>发表评论</button>{/* 没优化版本 */}{/* 如果list没有数据   就是暂无评论  否则 就循环渲染 */}{/* {this.state.list.length === 0 ? (<div>暂无评论</div>) : (<ul>{this.state.list.map(item => {return <li key={item.id}>评论人{item.name} <br></br> 内容{item.content}</li>})}</ul>)} */}{/* 优化版本 */}{this.renderList()}</div>);}
}ReactDOM.render(<Hello></Hello>, document.getElementById("root"));

13. 组件通讯

props

// 2 props  接收
const Hello = (props) => {console.log(props);return (<div><span>{props.name} {props.age}</span></div>);
};// 1  传递
ReactDOM.render(<Hello name="jsck" age={22}></Hello>,document.getElementById("root")
);
// 2 props  接收
class Hello extends React.Component {render() {console.log(this.props);return (<div>{this.props.name}{this.props.age}</div>);}
}// // 1  传递
ReactDOM.render(<Hello name="jsck" age={22}></Hello>,document.getElementById("root")
);
// 推荐使用 props作为consttuctor参数
// 2 props  接收
class Hello extends React.Component {constructor(props) {super(props);console.log(props);}render() {console.log(this.props);return (<div>{this.props.name}{this.props.age}</div>);}
}// 1  传递
ReactDOM.render(<Hello name="jsck" age={22}></Hello>,document.getElementById("root")
);

父传子

// 父传子
// 父组件
class Parent extends React.Component {state = {name: "wang1",};render() {return (<div>我是父组件<Child name={this.state.name}></Child></div>);}
}// 子组件
const Child = (props) => {return (<div><p>我是子组件 接收父组件数据为:{props.name}</p></div>);
};ReactDOM.render(<Parent name="jsck" age={22}></Parent>,document.getElementById("root")
);

子传父

// 父组件
class Parent extends React.Component {state = {parentMsg: "",};getChildMsg = (data) => {console.log("接收子组件数据wei:" + data);this.setState({parentMsg: data,});};render() {return (<div>父组件 aaa {this.state.parentMsg}<hr></hr>子组件:<Child getMsg={this.getChildMsg}></Child></div>);}
}class Child extends React.Component {state = {msg: "子组件数据 ",};handClick = () => {this.props.getMsg(this.state.msg);};render() {return (<div>我是子组件<button onClick={this.handClick}>点我给父组件传递数据</button></div>);}
}ReactDOM.render(<Parent name="jsck" age={22}></Parent>,document.getElementById("root")
);

兄弟相传

//思路: 将共享状态提升到最近的公共父组件中  由公共父组件管理这个状态//子组件通过props接收
class Parent extends React.Component {// 提供共享状态state = {num: 0}// 提供修改状态方法changeNum = () => {this.setState({num: this.state.num + 1})}render() {return (<div><Child1 num={this.state.num}></Child1><Child2 changeNum={this.changeNum}></Child2></div>)}
}const Child1 = (props) => {return <h1>计数器:{props.num}</h1>
}const Child2 = (props) => {return <button onClick={props.changeNum}>+1</button>
}ReactDOM.render(<Parent name="jsck" age={22}></Parent>, document.getElementById('root'))

拆分组件式

index.js :

import Child1 from "./components/Child1";
import Child2 from "./components/Child2";class Parent extends React.Component {// 提供共享状态state = {num: 0}// 提供修改状态方法changeNum = () => {this.setState({num: this.state.num + 1})}render() {return (<div><Child1 num={this.state.num}></Child1><Child2 changeNum={this.changeNum}></Child2></div>)}
}ReactDOM.render(<Parent></Parent>, document.getElementById('root'))

Child1.js :

import React from "react";class Child1 extends React.Component {constructor(props) {super(props);console.log(props);}render() {return (<div>计数器:{this.props.num}</div>)}
}export default Child1

Child2.js :

import React from "react";class Child2 extends React.Component {constructor(props) {super(props);console.log(props);}render() {return (<button onClick={this.props.changeNum}>+1</button>)}
}export default Child2

14 Context 跨组件传递数据

类似于vue的 vuex

步骤

// 组件 app  node  subNode Child  从app组件传到Child组件
// 用props 一层一层传  繁琐用React.createContext()  简便
1. 调用 React.createContext() 创建 Provider(提供数据)  和  Consumer(消费数据)  两个组件2. 使用Provider组件作为父节点<Provide><div className="App"><Child1></Child1></div></Provide>3. 设置value属性 表示要传递的值<Provider value="pink"></Provider>4. 调用Consumer组件接收数据<Consumer Consumer >通过回调函数的参数拿到传递过来的value的值{data => <span >data参数表示接收到的数据----{data}</span >}</Consumer 

代码

const { Provider, Consumer } = React.createContext()
class App extends React.Component {render() {// 用Provide包裹内容return (<Provider value="pink"><div className="App"><Node></Node></div></Provider>)}
}const Node = props => {return (<div><SubNode></SubNode></div>)
}
const SubNode = props => {return (<div><Child1></Child1></div>)
}
const Child1 = props => {return (<div><div> 我是Child1组件</div><Consumer>{data => <span>我是接收过来的值---{data}</span>}</Consumer></div>)
}
ReactDOM.render(<App></App>, document.getElementById('root'))

15. props深入

children属性 props.children

const Parent = props => {console.log(props)// 输出为 :  children :  "我是子组件子节点"props.children()return (<div>{props.children}</div>)
}// const Text = () => {
//     return <h1>我是组件</h1>
// }//<Parent></Parent>里面可以是文字  标签  组件  react元素 等
// ReactDOM.render(<Parent>我是子组件子节点</Parent>, document.getElementById('root'))
// ReactDOM.render(<Parent><h1>h1标签</h1></Parent>, document.getElementById('root'))
// ReactDOM.render(<Parent><Text></Text></Parent>, document.getElementById('root'))
ReactDOM.render(<Parent>{() => console.log('这是一个函数子节点')}</Parent>, document.getElementById('root'))

props校验 约束规则 默认值

//校验
// 允许在创建组件的时候  指定props的类型 格式等
// 安装包 yarn add prop-types     npm i props-types
// 导入包 import PropTypes from "prop-types"; 
// 使用组件名.propTypes{}
// 检验规则通过PropTypes对象来指定import PropTypes from "prop-types";const App = props => {const arr = props.colorsconst lis = arr.map((item, index) => <li key={index}>{item.name}</li>)return <ul>{lis}</ul>
}App.propTypes = {colors: PropTypes.array
}ReactDOM.render(<App colors={[{ name: "123" }]}></App>, document.getElementById('root'))// 约束规则
//常见类型  array bool func number object string
//React元素  element
//必填项  isRequired
//特定结构的对象   .shape({})import PropTypes from "prop-types";const App = props => {return (<div><h1>props检验</h1></div>)
}App.propTypes = {num: PropTypes.number,//数字fn: PropTypes.func.isRequired,  // 函数   isRequired必填项tag: PropTypes.element,  //react元素filter: PropTypes.shape({  //filter类型  对象({})area: PropTypes.string,price: PropTypes.number})
}ReactDOM.render(<App fn={() => { }}></App>, document.getElementById('root'))// props 默认值    未传入时生效// 场景  分页组件const App = props => {console.log(props)return (<div>prpos默认值</div>)
}// 以传入的值为主
App.defaultProps = {pagSize: 10
}// pagSize   10
ReactDOM.render(<App></App>, document.getElementById('root'))// pagSize   20
ReactDOM.render(<App pagSize={20}></App>, document.getElementById('root'))

16. 生命周期

创建
钩子函数触发时机作用
constructor创建组件时
1.初始化state
2.为事件处理绑定this
render每次组件渲染时都会触发渲染UI 注意不能调用setState()
componentDidMount组件挂载后(完成DOM渲染)
1.发送网络请求
2.DOM操作
更新
钩子函数触发时机作用
render每次组件渲染都会触发
渲染UI 挂载阶段是同一个render
componentDidUpdate组件更新后
1. 发送网络请求
1. DOM操作
注意 如果要setState() 必须放在一个 if 条件中
卸载
钩子函数触发时机作用
componentWillUnmount组件卸载(从页面中消失)
执行清理工作 (清除定时器)
创建
钩子函数触发时机作用
constructor创建组件时
1.初始化state
2.为事件处理绑定this
render每次组件渲染时都会触发渲染UI 注意不能调用setState()
componentDidMount组件挂载后(完成DOM渲染)
1.发送网络请求
2.DOM操作
// 创建时
// 执行顺序  constructor() => render()  =>  componentDidMountclass App extends React.Component {constructor(props) {super(props)// 初始化statethis.state = {num: 0}console.log('1生命周期函数---constructor')}componentDidMount() {// 获取DOM操作// console.log(document.getElementById('header'))// 发送ajax请求  axios.get("")console.log('2生命周期函数---componentDidMount')}render() {// 错误演示  不要再render中调用setState()// this.setState({//     num: 1// })console.log('3生命周期函数---render')return (<div><h1 id="header">header</h1></div>)}
}ReactDOM.render(<App ></App>, document.getElementById('root'))
```js
//更新时
//执行时机  1.setState()  2. forceUpdate()  3. 组件接收的props//执行顺序  render()  =>  componentDidUpdate()
更新
钩子函数触发时机作用
render每次组件渲染都会触发
渲染UI 挂载阶段是同一个render
componentDidUpdate组件更新后
1. 发送网络请求
1. DOM操作
注意 如果要setState() 必须放在一个 if 条件中



​ class App extends React.Component {

​ constructor(props) {
​ console.log(‘constructor’)
​ super(props)
​ this.state = {
​ num: 0
​ }
​ }
​ handerNum = () => {
​ this.setState({
​ num: this.state.num + 1
​ })

​ // 演示强制更新
​ // this.forceUpdate()
​ }

render() {
console.log(‘render’)
return (



+1

)
}
}


​ class Numb extends React.Component {
​ render() {
​ console.log(‘子组件------render’)
​ return (


统计次数:{this.props.num}



​ )
​ }

​ // 如果调用setState 必须放在if中
​ componentDidUpdate(prevProps) {
​ console.log(‘子组件生命周期 componentDidUpdate’)

​ // 获取DOM
​ console.log(document.getElementById(‘title’))

// this.setState({}) 报错 会递归更新

        console.log('上次props', prevProps)console.log('当前props', this.props)// // 正确写法   比较更新前后的props是否相同  来决定重新渲染条件// if (prevProps.num !== this.props.num) {//     this.setState({})//    // 发送ajax// }




​ }
​ }



​ ReactDOM.render(, document.getElementById(‘root’))

​ ```

卸载
钩子函数触发时机作用
componentWillUnmount组件卸载(从页面中消失)
执行清理工作 (清除定时器)

// 卸载时
// 执行时机  组件从页面中消失class App extends React.Component {constructor(props) {console.log('constructor')super(props)this.state = {num: 0}}handerNum = () => {this.setState({num: this.state.num + 1})// 演示强制更新// this.forceUpdate()}render() {console.log('render')return (<div>{this.state.num > 3 ? <p>豆豆打死了</p> : <Numb num={this.state.num}></Numb>}<button onClick={this.handerNum}>+1</button></div>)}
}class Numb extends React.Component {render() {console.log('子组件------render')return (<div><h1 id="title">统计次数:{this.props.num}</h1></div>)}componentDidMount() {// 开启定时器this.inter = setInterval(() => {console.log('定时器正在执行')}, 500);}componentWillUnmount() {console.log('生命周期   componentWillUnmount')// 清除定时器clearInterval(this.inter)}}ReactDOM.render(<App ></App>, document.getElementById('root'))

17. render props 和 高阶组件

react组件复用

复用相似功能

复用什么? 1. state 2. 操作state的方法

两种方式 1. render props模式 2.高阶组件(HOC)

思路:将要复用的state和操作state的方法封装到一个组件中


// 创建Mouse组件
// class Mouse extends React.Component {
//     state = {
//         x: 0,
//         y: 0
//     }//     // 鼠标移动事件
//     handleMouseMove = e => {
//         this.setState({
//             x: e.clientX,
//             y: e.clientY,
//         })
//     }
//     // 监听鼠标移动事件
//     componentDidMount() {
//         window.addEventListener('mousemove', this.handleMouseMove)
//     }//     render() {
//         // return null;
//         // console.log(this.props.render)
//         return this.props.renderss(this.state)
//     }
// }// class App extends React.Component {
//     render() {
//         return (
//             <div>
//                 111
//                 <Mouse renderss={(mouse) => {
//                     return <p>鼠标位置:x{mouse.x},y:{mouse.y}</p>
//                 }}></Mouse>//                 <Mouse renderss={mouse => {
//                     return <p style={{ position: 'absolute', top: mouse.y, left: mouse.x }}>看我!!!</p>
//                 }}></Mouse>
//             </div>
//         )
//     }
// }// ReactDOM.render(<App ></App>, document.getElementById('root'))
render props模式 children代替render属性

// render props模式  childern代替render属性
class Mouse extends React.Component {state = {x: 0,y: 0}// 鼠标移动事件handleMouseMove = e => {this.setState({x: e.clientX,y: e.clientY,})}// 监听鼠标移动事件componentDidMount() {window.addEventListener('mousemove', this.handleMouseMove)}render() {// return null;// console.log(this.props.render)return this.props.children(this.state)}
}class App extends React.Component {render() {return (<div>111<Mouse>{mouse => {return <p>鼠标位置:x{mouse.x},y:{mouse.y}</p>}}</Mouse><Mouse>{mouse => {return <p style={{ position: 'absolute', top: mouse.y, left: mouse.x }}>看我!!!</p>}}</Mouse></div>)}
}ReactDOM.render(<App ></App>, document.getElementById('root'))
render props 代码优化 添加props校验
import PropTypes from 'prop-types'
class Mouse extends React.Component {state = {x: 0,y: 0}handleMove = (e) => {this.setState({x: e.clientX,y: e.clientY})}componentDidMount() {window.addEventListener("mousemove", this.handleMove)}// 删除监听// 在组建卸载时移除事件绑定componentWillUnmount() {window.removeEventListener("mousemove", this.handleMove())}render() {return this.props.children(this.state)}
}// 添加props校验
Mouse.propTypes = {children: PropTypes.func.isRequired
}class App extends React.Component {render() {return (<div>1111<Mouse>{mouse => {return <p>鼠标位置:x{mouse.x},y:{mouse.y}</p>}}</Mouse><Mouse>{mouse => {return <p style={{ position: 'absolute', top: mouse.y, left: mouse.x }}>看我!!!</p>}}</Mouse></div>)}
}ReactDOM.render(<App ></App>, document.getElementById('root'))
高阶组件

使用步骤

1.创建一个函数 名称以with开头

2.指定函数参数 参数以大写字母开头 (作为要渲染的组件)

3.在函数内部创建一个类组件,提供复用的状态逻辑代码 并返回

4.在该组件中 渲染参数组件 同时将状态通过prop传递给参数组件

\5. 调用该高阶组件 传入要增强的组件 通过返回值拿到增强后的组件 渲染页面

function withMouse (WrapperComponent){

class Mouse extends React.Component{}

return Mouse

}

Mouse组件的render方法中

return <WrapperComponent {…this.state}>


// // 创建高阶组件
// function withMouse(WrappenComponent) {
//     // 该组件提供付永德状态逻辑
//     class Mouse extends React.Component {
//         // 鼠标状态
//         state = {
//             x: 0,
//             y: 0
//         }
//         handleMove = e => {
//             this.setState({
//                 x: e.clientX,
//                 y: e.clientY
//             })
//         }//         // 控制鼠标状态的逻辑
//         componentDidMount() {
//             window.addEventListener("mousemove", this.handleMove)
//         }//         componentWillUnmount() {
//             window.removeEventListener("mousemove", this.handleMove)
//         }//         render() {
//             return <WrappenComponent {...this.state}></WrappenComponent>
//         }//     }//     return Mouse// }// const Position = props => {//     return <p>
//         鼠标位置:x{props.x}   y: {props.y}
//     </p>
// }// const ThisPosition = (props) => {
//     return <p style={{ position: 'absolute', top: props.y, left: props.x }}>看我!!!</p>
// }// // 获取增强后的组件
// const MousePosition = withMouse(Position)
// const ThisMousePosition = withMouse(ThisPosition)// class App extends React.Component {
//     render() {
//         return (
//             <div>
//                 高阶组件//                 {/* 渲染增强后逇组件 */}//                 <MousePosition></MousePosition>
//                 <ThisMousePosition />
//             </div>
//         )
//     }
// }// ReactDOM.render(<App />, document.getElementById('root'))
displayName属性

// 设置displayName   
// 不设置  React调试器 都显示Mouse
// 便于调试区分// 创建高阶组件
// function withMouse(WrappenComponent) {
//     // 该组件提供付永德状态逻辑
//     class Mouse extends React.Component {
//         // 鼠标状态
//         state = {
//             x: 0,
//             y: 0
//         }
//         handleMove = e => {
//             this.setState({
//                 x: e.clientX,
//                 y: e.clientY
//             })
//         }//         // 控制鼠标状态的逻辑
//         componentDidMount() {
//             window.addEventListener("mousemove", this.handleMove)
//         }//         componentWillUnmount() {
//             window.removeEventListener("mousemove", this.handleMove)
//         }//         render() {
//             return <WrappenComponent {...this.state}></WrappenComponent>
//         }//     }//     // // 设置displayName
//     Mouse.displayName = `WithMouse${getDisplayName(WrappenComponent)}`//     function getDisplayName(WrappenComponent) {
//         return WrappenComponent.displayName || WrappenComponent.name || 'Component'
//     }//     return Mouse// }// const Position = props => {//     return <p>
//         鼠标位置:x{props.x}   y: {props.y}
//     </p>
// }// const ThisPosition = (props) => {
//     return <p style={{ position: 'absolute', top: props.y, left: props.x }}>看我!!!</p>
// }// // 获取增强后的组件
// const MousePosition = withMouse(Position)
// const ThisMousePosition = withMouse(ThisPosition)// class App extends React.Component {
//     render() {
//         return (
//             <div>
//                 高阶组件//                 {/* 渲染增强后逇组件 */}//                 <MousePosition></MousePosition>
//                 <ThisMousePosition />
//             </div>
//         )
//     }
// }// ReactDOM.render(<App />, document.getElementById('root'))
高阶组件传递props

// 问题  props丢失
// 原因  高阶组件没有往下传递props
// 解决方法  渲染WrappedComponen时  讲state和this.props一起传递给组件function withMouse(WrappenComponent) {// 该组件提供付永德状态逻辑class Mouse extends React.Component {// 鼠标状态state = {x: 0,y: 0}handleMove = e => {this.setState({x: e.clientX,y: e.clientY})}// 控制鼠标状态的逻辑componentDidMount() {window.addEventListener("mousemove", this.handleMove)}componentWillUnmount() {window.removeEventListener("mousemove", this.handleMove)}render() {console.log(this.props, 'Mouse组件')// return <WrappenComponent {...this.state}></WrappenComponent>return <WrappenComponent {...this.state} {...this.props}></WrappenComponent>}}// // 设置displayNameMouse.displayName = `WithMouse${getDisplayName(WrappenComponent)}`function getDisplayName(WrappenComponent) {return WrappenComponent.displayName || WrappenComponent.name || 'Component'}return Mouse}const Position = props => {console.log(props, 'Position组件')// 拿不到传过来的a// 问题  props丢失// 原因  高阶组件没有往下传递props// 解决方法  渲染WrappedComponen时  将state和this.props一起传递给组件// return <WrappenComponent {...this.state} {...this.props}></WrappenComponent>return <p>鼠标位置:x{props.x}   y: {props.y}</p>
}// 获取增强后的组件
const MousePosition = withMouse(Position)class App extends React.Component {render() {return (<div>高阶组件{/* 渲染增强后逇组件 */}<MousePosition a="1"></MousePosition></div>)}
}ReactDOM.render(<App />, document.getElementById('root'))

18. react原理揭秘

setState的说明

// setState的说明
// setstate更新数据是异步的// 推荐使用setState((state,props)=>{})   参数state:表示最新的state   props表示最新的propsclass App extends React.Component {state = {num: 0}handleClick = () => {// 更新state 是异步的// this.setState({//     num: this.state.num + 1// })// console.log(this.state.num) //0// this.setState({//     num: this.state.num + 1// })// 后面的setState不要依赖于前面的setState// this.setState调用两次   render只调用一次// 推荐语法:   也是异步的// 调用一次   参数state还是原来的statethis.setState((state, props) => {return {num: state.num + 1}})console.log(this.state.num)  //0// 调用第二次    这次的state参数 是上次调用之后的statethis.setState((state, props) => {return {num: state.num + 1}})console.log(this.state.num)//2}render() {console.log('render')return (<div>计数器  {this.state.num}<button onClick={this.handleClick}>+1</button></div>)}
}ReactDOM.render(<App />, document.getElementById('root'))
setState 第二个参数
// setState第二个参数  propsclass App extends React.Component {state = {num: 0}handleClick = () => {this.setState((state, props) => {return {num: state.num + 1}}, () => {  //状态更新后并且更新渲染后,立即执行   可以操作DOMconsole.log('状态更新', this.state.num) //1console.log(document.getElementById('title'))document.title = '更新标题'})console.log(this.state.num) //0}render() {console.log('render')return (<div>计数器  {this.state.num}<h1 id="title">111111111111</h1><button onClick={this.handleClick}>+1</button></div>)}
}ReactDOM.render(<App />, document.getElementById('root'))

19. JSX 语法转化过程

// // jsx是createElement的语法糖    jsx被@bable/preset-react编译为createElement// // jsx
// // const element = <h1 className="eleme">helo  jsx</h1>
// // console.log(element)// // createElement
// const element = React.createElement(
//     'h1',
//     {
//         className: "elem"
//     },
//     "hello  jsx"
// )// console.log(element)// ReactDOM.render(element, document.getElementById('root'))

2. 组件性能优化

// 1) 减轻state
// 只存储跟组件渲染相关的数据 比如列表数据 loading等
// 注意 不用做渲染的数据不要放在state中  比如定时器  直接放在this当中   直接this.setinter=setInterval(() => { }, 500);// 2)避免不必要的重新渲染
// 组件更新机制  父组件更新 会引起子组件也会更新
// 问题  子组件没有任何变化时也会重新渲染
// 解决方法:使用钩子函数 shouldComponentUpdate(nextProps,nextState)
// 作用 通过返回值决定该组件是否重新渲染  返回true表示重新渲染 false表示不能
// 触发时机  更新阶段的钩子函数  组件重新渲染 前 执行 (shouldComponentUpdate => render)

// class App extends React.Component {//     // true  渲染页面   false 不渲染
//     shouldComponentUpdate(nextProps, nextState) {
//         console.log(nextProps)  //最新的props
//         console.log(nextState)  //最新的state
//         console.log(this.state)  //  更新前的状态
//         return true
//     }
//     state = {
//         num: 0
//     }//     handleClick = () => {
//         this.setState((state) => {
//             return {
//                 num: state.num + 1
//             }
//         })
//     }//     render() {
//         return (<div>{this.state.num}//             <button onClick={this.handleClick}>+1</button>
//         </div>)
//     }
// }// ReactDOM.render(<App />, document.getElementById('root'))
案例

// 案例
class App extends React.Component {state = {num: 0}handleClick = () => {this.setState((state) => {return {num: Math.floor(Math.random() * 3)  // 0-3 随机数}})}// 因为两次生成的随机数相同  就不必要重新渲染shouldComponentUpdate(nextProps, nextState) {// if (nextState.num === this.state.num) {//     return false// } else {//     return true// }return nextState.num !== this.state.num}render() {console.log('render')return (<div>{this.state.num}<button onClick={this.handleClick}>随机数</button></div>)}
}ReactDOM.render(<App />, document.getElementById('root'))
通过props避免不必要的重新渲染
 //利用props 避免不必要的重新渲染class App extends React.Component {state = {num: 0}handleClick = () => {this.setState((state) => {return {num: Math.floor(Math.random() * 3)  // 0-3 随机数}})}render() {return (<div><NumberBox number={this.state.num}></NumberBox><button onClick={this.handleClick}>随机数</button></div>)}
}class NumberBox extends React.Component {shouldComponentUpdate(nextProps) {console.log(nextProps)console.log(this.props)return nextProps.number !== this.props.number}render() {console.log('render')return (<div>随机数{this.props.number}</div>)}
}ReactDOM.render(<App />, document.getElementById('root'))
纯组件 (内部自动实现shouldComponentUpdate)

// 纯组件
// 纯组件 PureComponent  与React.Component功能相似
// 区别 PureComponent内部自动实现了 shouldComponentUpdate  不需要手动比较
// 原理  纯组件内部通过分别对比前后两次props和state的值  来决定是否重新渲染组件// import { PureComponent } from "react";
// class App extends PureComponent {  // 可以写为class App extends React.PureComponent {  就不需要引入
//     state = {
//         num: 0
//     }//     handleClick = () => {
//         this.setState((state, props) => {
//             return {
//                 num: Math.floor(Math.random() * 3)
//             }
//         })
//     }//     render() {
//         console.log('render')
//         return (
//             <div>
//                 随机数  {this.state.num}
//                 <button onClick={this.handleClick}>随机</button>
//             </div>
//         )
//     }
// }// ReactDOM.render(<App />, document.getElementById('root'))

import { PureComponent } from "react";class App extends React.Component {state = {num: 0}handleClick = () => {this.setState((state, props) => {return {num: Math.floor(Math.random() * 3)}})}render() {return (<div><NumberBox number={this.state.num}></NumberBox><button onClick={this.handleClick}>随机</button></div>)}
}class NumberBox extends PureComponent {render() {console.log('render')return <div>suijiahsu1  {this.props.number}</div>}
}ReactDOM.render(<App />, document.getElementById('root'))

21 好客租房 项目

###  1. 项目搭建

npx create-react-app hkzf

yarn start

2. 组件库 antd-mobile

​ 1 打开文档 http://ant-design-mobile.antgroup.com/zh/components/button

3. 配置基础路由

​ yarn add react-router-dom

​ import { BrowserRouter as Router, Route, Routes, Link } from ‘react-router-dom’

4. 外观和样式调整

index.css

html,
body {height: 100%;font-family: "Microsoft YaHei";color: #333;background-color: #fff;
}
* {box-sizing: border-box;
}

5. 两种布局页面

  1. 有tabber页面
  2. 无tabbar页面

6. 嵌套路由

v6版本

 render() {return <div className="home">shouye<Button size='large' color='primary'>xxxxxxxxxxxxx</Button>{/* <Route path="/news" element={<News />}></Route> */}<Link to="/home/news">news</Link><Routes>{/* <Route path="/*" ></Route> */}<Route path="/" element={<News />}></Route><Route path="/a" element={<A />}></Route></Routes></div>}

v6之前版本:

 render() {return (<div style={{ background: "red", padding: "10px" }} className="home">shouye<Button size='large' color='primary'>xxxxxxxxxxxxx</Button><Route path="/home/news" component={News}></Route></div>)}
}

附加

1.关闭 eslint

package.json 中修改

  "eslintConfig": {"extends": ["react-app","react-app/jest"],"rules": {"no-undef": "off","no-restricted-globals": "off","no-unused-vars": "off"}},

相关文章:

react学习笔记,ReactDOM,react-router-dom

react 学习 1. 下载与安装 下载 npm install -g create-react-app 安装 npx create-react-app xxx 推荐 npm init react-app xxx yarn create react-app xxx 2. 创建 react 元素 indexjs 文件 import React from "react"; import ReactDOM from "react…...

优化UVM环境(八)-整理project_common_pkg文件

书接上回&#xff1a; 优化UVM环境&#xff08;七&#xff09;-整理环境&#xff0c;把scoreboard拿出来放在project_common环境里 Prj_cmn_pkg.sv考虑到是后续所有文件的基础&#xff0c;需要引入uvm_pkg并把自身这个pkg import给后续的文件&#xff1a; 这里有3个注意事项&…...

【实战案例】Django框架连接并操作数据库MySQL相关API

本文相关操作基于上次操作基本请求及响应基础之上【实战案例】Django框架基础之上编写第一个Django应用之基本请求和响应 Django框架中默认会连接SQLite数据库&#xff0c;好处是方便无需远程连接&#xff0c;打包项目挪到其他环境安装一下依赖一会就跑起来&#xff0c;但是缺点…...

【其他】无法启动phptudy服务,提示错误2:系统找不到指定的文件

在服务中启动phpstudy服务时&#xff0c;提示“windows 无法启动phpstudy服务 服务(位于本地计算机上) 错误2:系统找不到指定的文件”的错误。导致错误的原因是可执行文件的路径不对&#xff0c;修改成正确的路径就可以了。 下面是错误的路径&#xff0c;会弹出错误窗口&#…...

AI驱动的支持截图或线框图快速生成网页应用的开源项目

Napkins.dev是什么 Napkins.dev是一个创新的开源项目&#xff0c;基于AI技术将用户的截图或线框图快速转换成可运行的网页应用程序。项目背后依托于Meta的Llama 3.1 405B大型语言模型和Llama 3.2 Vision视觉模型&#xff0c;结合Together.ai的推理服务&#xff0c;实现从视觉设…...

es集群索引是黄色

排查 GET /_cat/shards?hindex,shard,prirep,state,unassigned.reason 查询原因 发现node正常 执行重新分配 retry_failedtrue 参数告诉Elasticsearch重试那些因某种原因&#xff08;如节点故障、资源不足等&#xff09;而失败的分片分配。这个选项通常用来尝试再次分配那些…...

获取淘宝商品评论的方法分享-调用API接口item_review

在电商领域&#xff0c;商品评论是消费者了解产品、做出购买决策的重要依据。淘宝作为中国最大的电商平台之一&#xff0c;其商品评论系统涵盖了海量的用户反馈数据。为了帮助企业、电商数据分析师、市场研究人员以及普通消费者更高效地获取这些评论数据&#xff0c;淘宝开放平…...

MATLAB人脸考勤系统

MATLAB人脸考勤系统课题介绍 该课题为基于MATLAB平台的人脸识别系统。传统的人脸识别都是直接人头的比对&#xff0c;现实意义不大&#xff0c;没有一定的新意。该课题识别原理为&#xff1a;先采集待识别人员的人脸&#xff0c;进行训练&#xff0c;得到人脸特征值。测试的时…...

Spring篇(事务篇 - 基础介绍)

目录 一、JdbcTemplate&#xff08;持久化技术&#xff09; 1. 简介 2. 准备工作 2.1. 引入依赖坐标 2.2. 创建jdbc.properties 2.3. 配置Spring的配置文件 3. 测试 3.1. 在测试类装配 JdbcTemplate 3.2. 测试增删改功能 查询一条数据为实体类对象 查询多条数据为一个…...

qt EventFilter用途详解

一、概述 EventFilter是QObject类的一个事件过滤器&#xff0c;当使用installEventFilter方法为某个对象安装事件过滤器时&#xff0c;该对象的eventFilter函数就会被调用。通过重写eventFilter方法&#xff0c;开发者可以在事件处理过程中进行拦截和处理&#xff0c;实现对事…...

[ 钓鱼实战系列-基础篇-6 ] 一篇文章让你了解邮件服务器机制(SMTP/POP/IMAP)-1

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…...

wordpress伪静态规则

WordPress 伪静态规则是指将 WordPress 生成的动态 URL 转换为静态 URL 的规则&#xff0c;这样做可以提高网站的搜索引擎优化(SEO)效果&#xff0c;并且使得 URL 更加美观、易于记忆。伪静态规则通常需要在服务器的配置文件中设置&#xff0c;不同的服务器环境配置方法有所不同…...

缓存框架JetCache源码解析-缓存定时刷新

作为一个缓存框架&#xff0c;JetCache支持多级缓存&#xff0c;也就是本地缓存和远程缓存&#xff0c;但是不管是使用着两者中的哪一个或者两者都进行使用&#xff0c;缓存的实时性一直都是我们需要考虑的问题&#xff0c;通常我们为了尽可能地保证缓存的实时性&#xff0c;都…...

docker配置mysql8报错 ERROR 2002 (HY000)

通过docker启动的mysql&#xff0c;发现navicat无法连接&#xff0c;后来进入容器内部也是无法连接&#xff0c;产生以下错误 root9f3b90339a14:/var/run/mysqld# mysql -u root -p Enter password: ERROR 2002 (HY000): Cant connect to local MySQL server through socket …...

【Linux】为什么环境变量具有全局性?共享?写时拷贝优化?

环境变量表具有全局性的原因&#xff1a; 环境变量表之所以具有全局性的特征&#xff0c;主要是因为它们是在进程上下文中维护的&#xff0c;并且在大多数操作系统中&#xff0c;当一个进程创建另一个进程&#xff08;即父进程创建子进程&#xff09;时&#xff0c;子进程会继承…...

如何在Linux中找到MySQL的安装目录

前言 发布时间&#xff1a;2024-10-22 在日常管理和维护数据库的过程中&#xff0c;了解MySQL的确切安装位置对于执行配置更改、更新或者进行故障排查是非常重要的。本文将向您介绍几种在Linux环境下定位MySQL安装路径的方法。 通过命令行工具快速定位 使用 which 命令 首…...

机器人备件用在哪些领域

机器人备件&#xff0c;作为机器人技术的重要组成部分&#xff0c;被广泛应用于多个领域&#xff0c;以提高生产效率、降低成本、增强产品质量&#xff0c;并推动相关行业的智能化发展。以下是一些主要的应用领域&#xff1a; 制造业&#xff1a; 机器人备件在制造业中的应用最…...

基于单片机优先级的信号状态机设计

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、背景知识二、使用步骤1.定义相应状态和信号列表2.获取最高优先级信号3.通用状态机实现4.灯的控制函数 总结 前言 在嵌入式系统中&#xff0c;设备控制的灵…...

数字电路week3

数字电路学习 九.补充 1.Verilog和fpga verilog是一种描述电路的语言&#xff0c;出现于上世纪80年代 非&#xff1a;~与: &&#xff0c;或: |&#xff0c;异或: ^ fpga&#xff1a;一种可编程逻辑器件 FPGA 由大量的逻辑单元、查找表&#xff08;LUTs&#xff09;、触发…...

如何在 Linux 中对 USB 驱动器进行分区

如何在 Linux 中对 USB 驱动器进行分区 一、说明 为了在 Linux 上访问 USB 驱动器&#xff0c;它需要有一个或多个分区。由于 USB 驱动器通常相对较小&#xff0c;仅用于临时存储或轻松传输文件&#xff0c;因此绝大多数用户会选择只配置一个跨越整个 USB 磁盘的分区。但是&a…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...