commit 639450a8c62f85adf8856fb4a264a4e236b5b90c
Author: 1708-huayu <57060237+1708-huayu@users.noreply.github.com>
Date: Thu Oct 19 14:19:45 2023 +0800
init
diff --git a/npm/npm镜像设置.md b/npm/npm镜像设置.md
new file mode 100644
index 0000000..adb2465
--- /dev/null
+++ b/npm/npm镜像设置.md
@@ -0,0 +1,14 @@
+查看当前镜像
+
+```apl
+npm help config
+npm config get registry
+```
+
+设置全局镜像
+
+```shell
+npm config set registry https://registry.npm.taobao.org --global
+```
+
+版本管理:[GitHub - nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions](https://github.com/nvm-sh/nvm#usage)
diff --git a/react/1.概述.md b/react/1.概述.md
new file mode 100644
index 0000000..f88d84f
--- /dev/null
+++ b/react/1.概述.md
@@ -0,0 +1,79 @@
+# 原生JavaScript,dom
+1. 原生JavaScript操作DOM繁琐效率低
+2. 使用JavaScript直接操作DOM,浏览器会进行大量的重绘重排.
+3. 没有组件化编码方案,代码复用率低
+# React的特点
+用于构建用户界面的javaScript库,操作DOM呈现页面
+## 声明式
+相对命令式.
+## *组件式
+
+## 学习一次随处使用
+开发web应用
+开发移动端原生应用,react-native
+VR开发react360
+
+浏览器安装React Developer Tool
+
+#### 模块
+1. 理解:向外提供特定功能的js程序,一般就是一个js文件
+2. 为什么要拆成模块:随着业务逻辑增加,代码越来越多且复杂
+3. 作用:复用js,简化js编写,提高js运行效率
+#### 组件
+1. 理解:用来实现局部功能效果的代码和资源的集合(html,css,js,image等等)
+2. 为什么:一个界面的功能更复杂
+3. 作用:复用编码,简化项目编码,提高运行效率.
+
+# 使用
+npm升级
+```shell
+npm install -g npm@9.2.0
+npm i create-create-app -g
+```
+## 创建项目
+```shell
+npx create-react-app my-app
+```
+```shell
+npm i react react-dom
+```
+## 引入 react和react-dom两个js文件
+## 创建React元素
+React.createElement('元素名称,标签h,p',属性,子节点,子节点,子节点...)
+## 渲染react元素到页面中
+ReactDOM.render(要渲染的元素,渲染挂载点)
+```html
+
+
+
+
+
+
+
+
+```
+
+# React脚手架的使用
+```shell
+npx create-react-app my-app
+npm start
+```
+引入改成导入
+```
+// es6中模块语法
+import React from 'react'
+import ReactDOM from 'react-dom'
+```
+
+```html
+import React from 'react';
+import ReactDOM from 'react-dom';
+
+const title = React.createElement('p',{title:"我是段落",id:"p1"},'hello xian',React.createElement('span',null,'hello hua'))
+ReactDOM.render(title,document.getElementById('root'))
+```
\ No newline at end of file
diff --git a/react/2.jsx.md b/react/2.jsx.md
new file mode 100644
index 0000000..7cc96e5
--- /dev/null
+++ b/react/2.jsx.md
@@ -0,0 +1,106 @@
+# createElement
+劣势
+1. 繁琐不简洁
+2. 不直观,不能一眼看出代码表述
+3. 不优雅,用户体验差
+# jsx
+语法与html类似
+JSX 是JavaScript XML的简写,表示在JavaScript代码中写xml(html)格式的代码.React的核心内容
+优势:声明式语法更加直观,与html结构相同,降低成本,提高开发效率
+React完全利用js语言自身能力来编写UI,而不是造轮子增强HTML功能(没有自定义指令).
+```html
+import React from 'react';
+import ReactDOM from 'react-dom';
+
+// const title = React.createElement('p',{title:"我是段落",id:"p1"},'hello xian',React.createElement('span',null,'hello hua'))
+// jsx
+const title = hello xianhello hua
+ReactDOM.render(title,document.getElementById('root'))
+```
+# 脚手架中使用jsx语法
+1. JSX不是标准的ECMAScript语法,是他的拓展
+2. 需要使用babel(@babel/preset-react)编译后,才能在浏览器中使用
+3. create-react-app脚手架中已经默认有了该配置无需配置.
+
+# 基本用法
+1. 使用驼峰命名规则
+2. 特殊的属性名 class->className,for->htmlFor,tabindex->tabIndex
+3. 没有子节点可以使用/结尾
+4. 推荐在小括号内写JSX
+```html
+const title = (hello xianhello hua
)
+```
+### 嵌入js
+{JavaScript表达式}
+```html
+const name = "----------------------------"
+const title = (hello xian {name}hello hua
)
+```
+### jsx条件渲染
+根据条件渲染特定的jsx结构
+if else ,三目,逻辑与运算符
+```html
+const isLoading = false
+const loadData= ()=>{
+ // if(isLoading){
+ // return loading...
+ // }
+ // return 数据加载完成,此处显示加载后的数据
+ // return isLoading?(loading...
):(数据加载完成,此处显示加载后的数据
)
+ return isLoading && (loading...
)
+}
+const title = (
+
+ 条件渲染{loadData()}
+
+)
+```
+### jsx 列表渲染
+```html
+const songs = [
+ {id:1,name:'有为歌'},
+ {id:2,name:'水手'},
+ {id:3,name:'都是月亮惹的祸'}
+]
+const list = (
+
+ {songs.map(item=>- {item.name}
)}
+
+)
+
+ReactDOM.render(list,document.getElementById('root'))
+```
+### jsx的样式处理
+#### 行内样式 style
+```html
+const listStyle = (
+ 行内样式
+ 类样式
+)
+```
+#### 类名 className
+```html
+import './index.css'
+const listStyle = (
+ 类样式
+)
+```
+css
+```html
+.title{
+ text-align: center;
+}
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/react/3.react组件.md b/react/3.react组件.md
new file mode 100644
index 0000000..b23e4cc
--- /dev/null
+++ b/react/3.react组件.md
@@ -0,0 +1,343 @@
+# 组件介绍
+组件表示页面中的部分功能
+组合多个组件实现完整的页面功能
+可复用,独立(相互之间互不影响),可组合
+# 组件的创建方式
+
+## 使用函数创建组件
+函数名称必须以大写字母开头
+必须有返回值,返回组件结构
+如果返回null表示不渲染任何内容
+
+渲染组件:使用函数名作为组件标签名
+```html
+// function Hello(){
+// return (展示的返回函数组件
)
+// }
+const Hello =()=>展示的返回函数组件
+ReactDOM.render(,document.getElementById('root'))
+```
+## 使用类创建组件
+类名称必须以大写字母开头
+类组件必须继承React.Component父类
+必须提供render方法
+render方法必须有返回值.
+```html
+class HelloClass extends React.Component{
+ render(){
+ return (leizujian
)
+ }
+}
+ReactDOM.render(,document.getElementById('root'))
+```
+## 抽离到独立的js文件
+1. 创建HelloRender.js文件
+2. 在HelloRender.js文件中导入React
+3. 创建组件
+4. 在HelloRender.js中导出该组件
+5. 在index.js中导入HelloRender组件
+6. 渲染组件
+```html
+import HelloRender from './learn/HelloRender'
+ReactDOM.render(,document.getElementById('root'))
+```
+```
+import React from "react"
+
+class HelloRender extends React.Component{
+ render(){
+ return (
+ 抽离到js文件中的组件
+ )
+ }
+}
+
+export default HelloRender
+```
+
+# 事件处理
+驼峰命名
+on+事件名称={事件处理程序}
+## 类
+```html
+class AppOnClick extends React.Component{
+ handleClick(){
+ console.log('单机')
+ }
+ render(){
+ return (
+
+ )
+ }
+}
+
+ReactDOM.render(,document.getElementById('root'))
+```
+## 函数
+```html
+function AppOnClickFun(){
+ function handleClick(){
+ console.log('单机function')
+ }
+ return (
+
+ )
+}
+ReactDOM.render(,document.getElementById('root'))
+```
+## 事件对象
+```html
+class AppOnClickUrl extends React.Component{
+ handleClick(e){
+ // 阻止浏览器默认跳转行为
+ e.preventDefault()
+ console.log('单机,阻止浏览器默认跳转行为')
+ }
+ render(){
+ return (
+ 点击
+ )
+ }
+}
+
+ReactDOM.render(,document.getElementById('root'))
+```
+
+## 有状态组件和无状态组件
+状态(state)即数据
+函数组件又叫无状态组件,只负责数据展示(静)
+类组件又叫有状态组件,负责更新UI,让页面动起来
+
+
+
+## 组件中的state和setState
+```html
+class AppState extends React.Component{
+ constructor(){
+ super()
+ this.state= {
+ count:0
+ }
+ }
+ // state= {
+ // count:0
+ // }
+ render(){
+ return (
+ 有状态组件,{this.state.count}
+ )
+ }
+}
+
+ReactDOM.render(,document.getElementById('root'))
+```
+修改状态
+```html
+class AppState extends React.Component{
+ constructor(){
+ super()
+ this.state= {
+ count:0,
+ test:'a'
+ }
+ }
+ // state= {
+ // count:0
+ // }
+ render(){
+ return (
+ 有状态组件,{this.state.count},{this.state.test}
+
+
+ )
+ }
+}
+
+ReactDOM.render(,document.getElementById('root'))
+```
+事件处理程序中this的值为undefined,希望this指向组件实例
+事件绑定this指向
+1. 箭头函数,利用箭头函数自身不绑定this的特点.
+```html
+class AppStateJTThis extends React.Component{
+ constructor(){
+ super()
+ this.state= {
+ count:0
+ }
+ }
+ onIncrement(){
+ console.info('事件处理this'+this)
+ this.setState({
+ count:this.state.count+1
+ })
+ }
+ render(){
+ return (
+ 有状态组件,{this.state.count}
+
+
+ )
+ }
+}
+
+ReactDOM.render(,document.getElementById('root'))
+```
+2. Function.prototype.bind()利用ESS中bind方法,将时间处理程序中的this与组件实例绑定到一起
+```html
+class AppStateJTThis extends React.Component{
+ constructor(){
+ super()
+ this.onIncrement= this.onIncrement.bind(this)
+ this.state= {
+ count:0
+ }
+ }
+ onIncrement(){
+ console.info('事件处理this'+this)
+ this.setState({
+ count:this.state.count+1
+ })
+ }
+ render(){
+ return (
+ 有状态组件,{this.state.count}
+
+
+ )
+ }
+}
+
+ReactDOM.render(,document.getElementById('root'))
+```
+3. class实例方法
+```html
+class AppStateJTThis extends React.Component{
+ constructor(){
+ super()
+ this.state= {
+ count:0
+ }
+ }
+ onIncrement=()=>{
+ console.info('事件处理this'+this)
+ this.setState({
+ count:this.state.count+1
+ })
+ }
+ render(){
+ return (
+ 有状态组件,{this.state.count}
+
+
+ )
+ }
+}
+
+ReactDOM.render(,document.getElementById('root'))
+```
+方法是一个特殊的属性.
+类中的方法默认开启了局部严格模式,所以changeWeather中的this为undefined,
+use strict 使用严格模式
+
+实例调用,直接调用(严格模式下,this为undefined)
+
+组件内的标签可以定义ref属性来标识自己
+
+箭头函数中的this找外层的this.
+
+## 事件处理
+1. 通过onXxx属性指定事件处理函数,必须驼峰
+ 1. React使用的是自定义合成事件,而不是使用原生DOM事件,为了更好兼容性
+ 2. React中的事件是通过事件委托方式处理的(委托给组件最外层的元素),为了更高效
+2. 可以通过event.target得到发生事件的DOM元素对象,避免过度使用ref
+
+
+# 表单处理
+## 受控组件,其值受到React控制的表单元素
+1. html中表单元素是可输入的,也就是有自己的可变状态
+2. react中可变状态通常通过state处理,并且只能通过setState()来处理
+3. react将state与表单元素值value绑定到一起,由state的值来控制表单元素的值
+4. 类似vue中双向绑定
+### 使用步骤
+1. 在state中添加一个状态,作为表单元素的value值(控制表单元素的来源)
+2. 给表单元素绑定change事件,将表单元素的值设置为state值(控制表单元素值的变化)
+### 使用一个事件处理程序同时处理多个表单元素
+1. 给表单添加一个name属性,名称与state相同
+2. 根据表单元素类型获取对应值
+3. 在change事件处理程序中通过name来修改对应的state
+```html
+class AppInput extends React.Component{
+ constructor(){
+ super()
+ this.state= {
+ txt:'请输入值',
+ context:'',
+ city:'bj',
+ isChecked:false
+ }
+ }
+ handleClick=e=>{
+ console.info('事件处理this'+this)
+ const target = e.target;
+ const value = target.type === 'checkbox'?target.checked:target.value
+ const name = target.name
+ this.setState({
+ [name]: value
+ })
+ console.info('name:'+name+',value:'+value)
+ }
+ render(){
+ return (
+
+
+
+ )
+ }
+}
+
+ReactDOM.render(,document.getElementById('root'))
+```
+### 高阶函数
+如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数.
+1. 若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数
+2. 若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数
+函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式.
+## 非受控组件
+借助于ref,使用原生DOM方式来获取表单元素值
+ref作用:获取DOM或组件
+```html
+class APPRef extends React.Component{
+ constructor(){
+ super()
+ // 创建ref对象
+ this.txtRef = React.createRef()
+ }
+ getTxt=()=>{
+ console.log('文本框值为',this.txtRef.current.value)
+ }
+ render(){
+ return(
+
+
+
+
+ )
+ }
+}
+
+ReactDOM.render(,document.getElementById('root'))
+```
diff --git a/react/4.评论列表案例.md b/react/4.评论列表案例.md
new file mode 100644
index 0000000..c621da7
--- /dev/null
+++ b/react/4.评论列表案例.md
@@ -0,0 +1,99 @@
+```html
+import React from "react";
+
+class CommentList extends React.Component {
+ state = {
+ comments: [
+ // { id: 1, name: 'shi', content: '沙发' },
+ // { id: 2, name: 'xiao', content: '板凳' },
+ // { id: 3, name: 'hua', content: '地板' }
+ ],
+ userName:'',
+ userContext:''
+ }
+ renderList() {
+ const {comments}= this.state
+ if (comments.length === 0) {
+ return (暂无评论
)
+ }
+ return (
+ {
+ comments.map(item => (
+ -
+
评论人:{item.name}
+ 评论:{item.content}
+
+ ))
+ }
+
)
+ // return this.state.comments.length === 0 ? (暂无评论
) :
+ // (
+ // {
+ // this.state.comments.map(item => (
+ // -
+ //
评论人:{item.name}
+ // 评论:{item.content}
+ //
+ // ))
+ // }
+ //
)
+
+ }
+ handleForm=(e)=>{
+ const {name,value}= e.target
+ this.setState({
+ [name]:value
+ })
+ }
+ addComment=()=>{
+ const {comments,userName,userContext}= this.state
+ // 非空校验
+ if(userName.trim()===""||userContext.trim()===""){
+ alert('请输入评论内容')
+ return
+ }
+ const newComments = [{
+ id:Math.random(),
+ name:userName,
+ content:userContext
+ },...comments]
+ this.setState({
+ comments:newComments,
+ // 清空文本空
+ userContext:'',
+ userName:''
+ })
+
+
+ }
+
+ render() {
+ const {userName,userContext}= this.state
+ return (
+
+
+
+
+
+
+
+
+ {/* {this.state.comments.length === 0 ? (
暂无评论
) :
+ (
+ {
+ this.state.comments.map(item => (
+ -
+
评论人:{item.name}
+ 评论:{item.content}
+
+ ))
+ }
+
)
+ } */}
+ {this.renderList()}
+
+ )
+ }
+}
+export default CommentList
+```
\ No newline at end of file
diff --git a/react/5.组件进阶.md b/react/5.组件进阶.md
new file mode 100644
index 0000000..5616002
--- /dev/null
+++ b/react/5.组件进阶.md
@@ -0,0 +1,294 @@
+# 组件通讯
+多组件之间共享通讯
+## props接收传递给组件的数据
+传递数据:给组件标签添加属性
+函数组件 props
+```html
+const HelloProps = (props)=>{
+ console.log(props)
+ return (
+ props:{props.name}
+ )
+}
+
+ReactDOM.render(,document.getElementById('root'))
+```
+类组件 this.props
+```html
+class HelloProps extends React.Component{
+ render(){
+ return (props:{this.props.name},{this.props.role}
)
+ }
+}
+ReactDOM.render(,document.getElementById('root'))
+
+```
+## 组件特点
+1. 可以是任意值
+```html
+class HelloProps extends React.Component{
+ render(){
+ console.log(this.props)
+ return (props:{this.props.name},{this.props.role} {this.props.tag}
)
+ }
+}
+ReactDOM.render(console.log('我可以传函数')}
+ tag={jsx
}
+
+ />,document.getElementById('root'))
+```
+2. 只读
+3. 在使用类组件时,如果写了构造函数,应该将props传递给super(),否则,无法在构造函数中获取到props
+
+```html
+class HelloProps extends React.Component{
+ constructor(props){
+ super(props)
+ console.log(this.props)
+ }
+ render(){
+ console.log(this.props)
+ return (props:{this.props.name},{this.props.role} {this.props.tag}
)
+ }
+}
+ReactDOM.render(console.log('我可以传函数')}
+ tag={jsx
}
+
+ />,document.getElementById('root'))
+```
+## 通讯的三种方式
+### 父组件传递给子组件
+1. 父组件提供传递的state数据
+2. 给子组件添加属性,值为state中的数据
+3. 子组件中通过props接收父组件中传递的数据
+```html
+class Parent extends React.Component{
+ state = {lastName:'师'}
+ render(){
+ return (
+
+ 父组件:
+
+
+ )
+ }
+}
+// 子组件
+const Child = (props)=>{
+ return (
+
+
子组件接收到父组件的数据 {props.name}
+
+ )
+}
+
+ReactDOM.render(,document.getElementById('root'))
+```
+### 子组件传递给父组件
+利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数.
+1. 父组件提供一个回调函数(用于接收数据)
+2. 将改函数作为属性的值,传递给子组件
+3. 子组件通过props调用回调函数
+4. 将子组件的数据作为参数传递给回调函数
+```html
+class Parent extends React.Component{
+ state={
+ parentMsg:''
+ }
+
+ getChildMsg = data=>{
+ console.log('接收到子组件传递过来的数据',data)
+ this.setState({
+ parentMsg:data
+ })
+ }
+ render(){
+ return (
+
+ 父组件:{this.state.parentMsg}
+
+
+ )
+ }
+}
+// 子组件
+class Child extends React.Component{
+ state = {
+ msg:"回调传递"
+ }
+ handleClick=()=>{
+ //
+ this.props.name(this.state.msg)
+ }
+ render(){
+ return (
+
+ )
+ }
+}
+
+ReactDOM.render(,document.getElementById('root'))
+```
+## 兄弟组件间的通讯
+将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态
+状态提升
+公共父组件职责:1.提供共享状态2.提供操作共享状态的方法
+要通讯的子组件只能通过props接收状态或者操作状态的方法
+```html
+class Counter extends React.Component{
+ state={
+ count:0
+ }
+ onIncrement=()=>{
+ this.setState({
+ count:this.state.count+1
+ })
+ }
+ render(){
+ return(
+
+
+
+
+ )
+ }
+}
+const Child1=(props)=>{
+ return 计数器:{props.count}
+}
+const Child2=(props)=>{
+ return
+}
+ReactDOM.render(,document.getElementById('root'))
+```
+
+# Context跨组件传递数据
+1. 使用React.createContext()创建Provider,Consumer
+2. 使用Provide组件作为父节点
+3. 设置value属性,表示要传递的数据
+4. 调用Consumer组件来接收数据
+```html
+const { Provider, Consumer } = React.createContext();
+
+class ContextApp extends React.Component {
+ render() {
+ return (
+
+
+
+
+
+ )
+ }
+}
+
+const Node = props => {
+ return (
+
+
+
+ )
+}
+
+const SubNode = props => {
+ return (
+
+
+
+ )
+}
+
+const Child = props => {
+ return {data=>我是子节点---{data}}
+}
+```
+# props深入
+## children表示组件标签的子节点.当组件标签有子节点时,props就会有该属性.
+children 属性与普通props一样,值可以是任意值(文本,React元素,组件,甚至是函数)
+```html
+class ChildProps extends React.Component{
+ render(){
+ console.log(this.props)
+ return (
+ 组件标签的子节点{this.props.children}
+ )
+ }
+}
+ReactDOM.render(传递到props的child,document.getElementById('root'))
+```
+
+```html
+class ChildProps extends React.Component{
+ render(){
+ console.log(this.props)
+ return (
+ 组件标签的子节点
{this.props.children}
+ )
+ }
+}
+const Test = ()=>
+ReactDOM.render(传递到props的child
,document.getElementById('root'))
+```
+函数
+```html
+class ChildProps extends React.Component{
+ render(){
+ this.props.children()
+ console.log(this.props)
+ return (
+ 组件标签的子节点
+ )
+ }
+}
+ReactDOM.render({()=>console.info("这是一个函数")},document.getElementById('root'))
+```
+## prop 校验
+1. 安装prop-types (npm i prop-types 或者 yarn add prop-types)
+2. 导入prop-types包
+3. 使用组件名.propTypes={}来给组件的props添加校验规则
+4. 校验规则通过PropTypes对象指定
+```html
+import React from "react"
+import PropTypes from "prop-types"
+class PropCheck extends React.Component{
+ render(){
+ const arr = this.props.colors
+ console.info(arr)
+ const lis = arr.map((item,index)=>{item})
+ return (
+
+ )
+ }
+}
+PropCheck.protoTypes= {
+ colors:PropTypes.array
+}
+export default PropCheck
+ReactDOM.render(,document.getElementById('root'))
+```
+## prop 默认值
+```html
+class LPropCheck extends React.Component{
+ render(){
+ // const arr = this.props.colors
+ // console.info(arr)
+ // const lis = arr.map((item,index)=>{item})
+ // return (
+ //
+ // )
+ return test
{this.props.colors}
+ }
+}
+LPropCheck.propTypes= {
+ colors:PropTypes.array
+}
+LPropCheck.defaultProps= {
+ colors:["red"]
+}
+```
diff --git a/react/6.组件生命周期.md b/react/6.组件生命周期.md
new file mode 100644
index 0000000..bbec454
--- /dev/null
+++ b/react/6.组件生命周期.md
@@ -0,0 +1,269 @@
+只有类组件才有生命周期
+1. 创建
+```html
+class LifeCreate extends React.Component{
+ constructor(props){
+ super(props)
+ console.warn('1.生命周期钩子函数constructor')
+ }
+ componentDidMount(){
+ console.warn('3.生命周期钩子函数componentDidMount')
+ }
+ render(){
+ console.warn('2.生命周期钩子函数render')
+ return (hello
)
+ }
+}
+```
+2. 更新
+New props,setState,forceUpdate
+```html
+class LifeUpdate extends React.Component{
+ constructor(props){
+ super(props)
+ console.warn('1.生命周期钩子函数constructor')
+ this.state = {
+ count:0
+ }
+ }
+ componentDidMount(){
+ console.log(document.getElementById('root'))
+ console.warn('3.生命周期钩子函数componentDidMount')
+ }
+ handlerClick= ()=>{
+ // this.setState({
+ // count:this.state.count+1
+ // })
+ this.forceUpdate()
+ }
+ render(){
+ console.warn('2.生命周期钩子函数render')
+ return (
)
+ }
+}
+class Counter extends React.Component{
+ componentDidUpdate(prevProps){
+ console.warn('---------------2生命周期钩子函数componentDidUpdate')
+ if(prevProps.count!=this.props.count){
+ this.setState({})
+ }
+ }
+ render(){
+ console.warn('---------------1生命周期钩子函数render')
+ return (点击次数{this.props.count}
)
+ }
+}
+```
+3. 卸载
+```html
+class LifeEnd extends React.Component{
+ constructor(props){
+ super(props)
+ console.warn('1.生命周期钩子函数constructor')
+ this.state = {
+ count:0
+ }
+ }
+ componentDidMount(){
+ console.log(document.getElementById('root'))
+ console.warn('3.生命周期钩子函数componentDidMount')
+ }
+ handlerClick= ()=>{
+ this.setState({
+ count:this.state.count+1
+ })
+ // this.forceUpdate()
+ }
+ render(){
+ console.warn('2.生命周期钩子函数render')
+ return (
+ {this.state.count>3?("goodby"):}
+
)
+ }
+}
+class Counter extends React.Component{
+ componentDidUpdate(prevProps){
+ console.warn('---------------2生命周期钩子函数componentDidUpdate')
+
+ if(prevProps.count!==this.props.count){
+ this.setState({})
+ }
+ }
+ componentDidMount(){
+ this.timerId = setInterval(()=>{
+ console.log("定时器在执行")
+ },500)
+ }
+ componentWillUnmount(){
+ clearInterval(this.timerId)
+ console.warn("结束")
+ }
+ render(){
+ console.warn('---------------1生命周期钩子函数render')
+ return (点击次数{this.props.count}
)
+ }
+}
+```
+# 组件复用
+复用组件的状态逻辑1.state2.操作state的方法.
+## render props
+将要复用的state和操作state的方法封装到一个组件中
+添加一个值为函数的prop,通过函数参数来获取(需要组件内部来实现)
+使用该函数的返回值,作为要渲染的UI内容
+```html
+import img from './img/20200205205324.jpg'
+import PropTypes from "prop-types"
+class RepeatUse extends React.Component {
+ render(){
+ return (
+
+
render props 复用模式
+
{mouse=>{return (X:{mouse.x},Y{mouse.y}
)}}
+
{mouse=>{return
}}
+
+ )
+ }
+}
+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)
+ }
+ componentWillUnmount(){
+ window.removeEventListener('mousemove', this.handleMouseMove)
+ }
+ render(){
+ return this.props.children(this.state)
+ }
+}
+Mouse.propTypes={
+ children:PropTypes.func.isRequired
+}
+```
+## 高阶组件HOC
+是一个函数,接收要包装的组件,返回增强后的组件
+1. 创建函数以with开头
+2. 指定函数参数,参数大写开头
+3. 函数内部创建类组件,提供复用状态逻辑代码
+4. 在组件中渲染参数组件,同时通过prop传递给参数组件(high order component)
+5. 调用高阶组件,传入要增强的组件,通过返回值拿到增强后的组件并将其渲染到页面.
+```html
+class RepeatUse extends React.Component {
+ render(){
+ return (
+
+
render props 复用模式
+
+
+ )
+ }
+}
+
+function withMouse(WrappedComponent){
+ 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)
+ }
+ componentWillUnmount(){
+ window.removeEventListener('mousemove', this.handleMouseMove)
+ }
+ render(){
+ // return this.props.children(this.state)
+ return
+ }
+ }
+
+ return Mouse
+}
+
+const Position = props=>(
+
+ 鼠标当前位置(x:{props.x},y:{props.y})
+
+)
+const MoousePosition = withMouse(Position)
+
+```
+### 设置displayName便于区分
+```html
+class RepeatUse extends React.Component {
+ render(){
+ return (
+
+
render props 复用模式
+
+ {/*
{mouse=>{return (X:{mouse.x},Y{mouse.y}
)}} */}
+ {/*
{mouse=>{return
}} */}
+
+ )
+ }
+}
+
+function getDisplayName(WrappedComponent){
+ return WrappedComponent.displayName || WrappedComponent.name || 'Component'
+}
+
+function withMouse(WrappedComponent){
+
+ 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)
+ }
+ componentWillUnmount(){
+ window.removeEventListener('mousemove', this.handleMouseMove)
+ }
+ render(){
+ // return this.props.children(this.state)
+ return
+ }
+ }
+ // 设置展示名称
+ Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}`
+ return Mouse
+}
+
+const Position = props=>(
+
+ 鼠标当前位置(x:{props.x},y:{props.y})
+
+)
+const MoousePosition = withMouse(Position)
+```
+## 高阶组件传递 props
+```html
+ render(){
+ // return this.props.children(this.state)
+ return
+ }
+```
+## 组件极简模型
+(state,props)=>UI
\ No newline at end of file
diff --git a/react/react原理/7.1.Diff算法.md b/react/react原理/7.1.Diff算法.md
new file mode 100644
index 0000000..1f3c70f
--- /dev/null
+++ b/react/react原理/7.1.Diff算法.md
@@ -0,0 +1 @@
+diff对比最小粒度:标签
\ No newline at end of file
diff --git a/react/react原理/7.setState说明.md b/react/react原理/7.setState说明.md
new file mode 100644
index 0000000..9731991
--- /dev/null
+++ b/react/react原理/7.setState说明.md
@@ -0,0 +1,56 @@
+setState异步更新(同一方法中多次调用只会render一次),设置值后立即获取,只能获取到原始值
+获取最新的state
+```html
+ this.setState((state,props)=> {
+ return {
+ count:state.count+1
+ }
+ })
+```
+setState第二个参数作为回调参数,在状态更新,后立即执行.
+```html
+class StateApp extends React.Component{
+ constructor(){
+ super()
+ this.state= {
+ count:0
+ }
+ }
+ onIncrement=()=>{
+ console.info('事件处理this'+this)
+ // this.setState({
+ // count:this.state.count+1
+ // })
+ // this.setState({
+ // count:this.state.count+1
+ // })
+ this.setState((state,props)=> {
+ return {
+ count:state.count+1
+ }
+ })
+ this.setState((state,props)=> {
+ return {
+ count:state.count+1
+ }
+ },()=>{
+ console.log('状态更新后回调函数',this.state.count)//4
+ console.log(document.getElementById('root').innerText)
+ })
+ console.info(this.state.count)///2
+ }
+ render(){
+ return (
+ 有状态组件,{this.state.count}
+
+
+ )
+ }
+ }
+```
+
+
+
+
+
+
diff --git a/react/react原理/8.jsx语法转换过程.md b/react/react原理/8.jsx语法转换过程.md
new file mode 100644
index 0000000..37e8653
--- /dev/null
+++ b/react/react原理/8.jsx语法转换过程.md
@@ -0,0 +1,58 @@
+jsx语法->createElement()->React元素
+父组件更新,子组件跟着更新.
+# 组件优化
+### 减轻state,与渲染无关的不要放在state中.
+### 避免不必要的重新渲染.
+钩子函数 shouldComponentUpdate(nextProps,nextState)
+根据返回值判断是否需要渲染该值.
+触发时机:更新阶段的钩子函数,组件重新渲染前执行(shouldComponentUpdate->render)
+或者使用纯组件
+```html
+class StateApp extends React.Component{
+ constructor(){
+ super()
+ this.state= {
+ count:0
+ }
+ }
+ shouldComponentUpdate(nextProps,nextState){
+ console.info('最新是内容'+nextState.count)
+ console.info('上次是内容'+this.state.count)
+ return nextState.count!==this.setState.count
+ }
+ onIncrement=()=>{
+ console.info('事件处理this'+this)
+ this.setState((state,props)=> {
+ return {
+ count:state.count+1
+ }
+ })
+ console.info(this.state.count)
+ }
+ render(){
+ return (
+ 有状态组件,{this.state.count}
+
+
+ )
+ }
+ }
+```
+
+## 纯组件 PureComponent
+比较props和state,只有这两者变化才会更新.
+纯组件内部的对比是shallow compare 浅层对比
+对于引用类型来说:只比较对象地址.
+# 虚拟DOM和Diff算法
+虚拟DOM=state+jsx
+虚拟DOM:本质上就是一个js对象,用来描述你希望在屏幕上看到的内容(UI)
+虚拟DOM让react脱离了浏览器的束缚
+## diff算法
+1. 初次渲染是,React会根据初始state(Model),创建一个虚拟DOM对象(树)
+2. 根据虚拟DOM生成真正的DOM,渲染到页面中
+3. 当数据变化后(setState),重新根据新的数据,创建新的虚拟DOM对象树
+4. 与上一次得到的虚拟DOM对象,使用Diff算法对比(找不同),得到需要更新的内容
+5. 最终,React只将变化的内容(patch)到DOM中,重新渲染到页面.
+
+
+
diff --git a/react/react原理/img/key选择.png b/react/react原理/img/key选择.png
new file mode 100644
index 0000000..d344753
Binary files /dev/null and b/react/react原理/img/key选择.png differ
diff --git a/react/react原理/img/遍历中key.png b/react/react原理/img/遍历中key.png
new file mode 100644
index 0000000..87fd173
Binary files /dev/null and b/react/react原理/img/遍历中key.png differ
diff --git a/react/redux/img/react-redux模型图.png b/react/redux/img/react-redux模型图.png
new file mode 100644
index 0000000..9718d07
Binary files /dev/null and b/react/redux/img/react-redux模型图.png differ
diff --git a/react/redux/img/redux原理图.png b/react/redux/img/redux原理图.png
new file mode 100644
index 0000000..7aa355c
Binary files /dev/null and b/react/redux/img/redux原理图.png differ
diff --git a/react/route-v6/1.项目.md b/react/route-v6/1.项目.md
new file mode 100644
index 0000000..4756668
--- /dev/null
+++ b/react/route-v6/1.项目.md
@@ -0,0 +1,21 @@
+1. 使用vite创建自己的项目
+
+```shell
+npm create vite@latest react-route-v6-learn -- --template react
+```
+
+2. 安装路由
+
+```
+npm install react-router-dom localforage match-sorter sort-by
+```
+
+3. 启动
+
+```
+npm run dev
+```
+
+nested 嵌套
+
+navigate 导航
\ No newline at end of file
diff --git a/react/生命周期/生命周期new.png b/react/生命周期/生命周期new.png
new file mode 100644
index 0000000..5122856
Binary files /dev/null and b/react/生命周期/生命周期new.png differ
diff --git a/react/生命周期/生命周期old.png b/react/生命周期/生命周期old.png
new file mode 100644
index 0000000..ec52ba5
Binary files /dev/null and b/react/生命周期/生命周期old.png differ
diff --git a/react/生命周期/生命周期函数.png b/react/生命周期/生命周期函数.png
new file mode 100644
index 0000000..6ed7c92
Binary files /dev/null and b/react/生命周期/生命周期函数.png differ
diff --git a/react/生命周期/生命周期函数new.png b/react/生命周期/生命周期函数new.png
new file mode 100644
index 0000000..f7e99f5
Binary files /dev/null and b/react/生命周期/生命周期函数new.png differ
diff --git a/react/目录1.png b/react/目录1.png
new file mode 100644
index 0000000..128667d
Binary files /dev/null and b/react/目录1.png differ
diff --git a/react/目录2.png b/react/目录2.png
new file mode 100644
index 0000000..3c23a08
Binary files /dev/null and b/react/目录2.png differ
diff --git a/react/路由/9.1.配置代理.md b/react/路由/9.1.配置代理.md
new file mode 100644
index 0000000..c20c7e0
--- /dev/null
+++ b/react/路由/9.1.配置代理.md
@@ -0,0 +1,44 @@
+# 代理:
+### 方式一
+只能使用一种代理
+package.json文件中添加
+"proxy":"http://localhost:5000"
+自身没有的资源会请求5000,自身请求http://localhost:3000/
+### 方式二
+src根目录下创建文件setupProxy.js
+```html
+const proxy = require('http-proxy-middleware')
+module.exports=function(app){
+ app.use(
+ proxy('/api1',{
+ target:'http://localhost:5000',
+ changeOrigin:true,
+ pathRewrite:{'^/api1':''}
+ }),
+ proxy('/api2',{
+ target:'http://localhost:5001',
+ changeOrigin:true,
+ pathRewrite:{'^/api2':''}
+ })
+ )
+}
+```
+
+
+```
+const {createProxyMiddleware} = require('http-proxy-middleware')
+module.exports=function(app){
+ app.use(
+ createProxyMiddleware('/api1',{
+ target:'https://github.com',
+ changeOrigin:false,
+ pathRewrite:{'^/api1':''}
+ }),
+ createProxyMiddleware('/api2',{
+ target:'http://localhost:5001',
+ changeOrigin:true,
+ pathRewrite:{'^/api2':''}
+ })
+ )
+}
+```
\ No newline at end of file
diff --git a/react/路由/9.路由.md b/react/路由/9.路由.md
new file mode 100644
index 0000000..8037cac
--- /dev/null
+++ b/react/路由/9.路由.md
@@ -0,0 +1,39 @@
+npm i react-router-dom@5
+为有效使用单页面管理原来的多页面的功能,前端路由应运而生.
+从一个视图跳转到另一个视图,是URL路径与组件的对应关系.
+1. 安装路由 npm i react-router-dom
+2. 导入 import { BrowserRouter as Router,Route,Link } from 'react-router-dom';
+3. 使用Router包裹整个组件
+4. 使用Link(解析为a标签)组件作为导航菜单路由入口
+5. 使用Route配置路由的规则和要展示的组件路由出口
+## 路由执行过程
+1. 点击Link组件(a标签),修改了浏览器地址栏中url
+2. React路由监听到地址栏url的变化
+3. React路由内部遍历所有Route组件,使用路由规则(path)与pathname进行匹配
+4. 当路由规则(path)能够匹配地址栏中的pathname时,就展示改route组件内容
+## 编程式导航
+通过js代码来实现页面跳转 this.pops.history.push('/home')
+history是react路由提供的,用于获取浏览器历史记录的相关信息
+push(path):跳转到某个页面,参数path表示要跳转的路径
+go(n)前进或者后退到某个页面(后退用-)
+
+
+
+## 默认路由
+```
+ } >
+```
+默认情况下React是模糊匹配模式
+精确匹配添加exact
+```html
+ } >
+```
+
+React路由一切都是组件,可以像思考组件一样思考路由.
+
+HashRouter 路径中包含#,#后所有资源都不发送服务器.
+
+路由组件():放到pages文件夹下,传入大量props信息
+一般组件():放到components,默认不传props内容,无history
+
+NavLink 默认点击高亮(activeClassName)
\ No newline at end of file
diff --git a/react/项目/10.技术栈.md b/react/项目/10.技术栈.md
new file mode 100644
index 0000000..d58e173
--- /dev/null
+++ b/react/项目/10.技术栈.md
@@ -0,0 +1,34 @@
+1. React核心库:react,react-dom,react-router-dom
+2. 脚手架:create-react-app
+3. 数据请求:axios
+4. ui组件库:antd-mobile
+5. 其他组件库:react-virtualized长列表,formik-yup表单和表单验证,react-spring动画功能
+6. 百度地图api
+
+创建并导入数据库 hkzf
+在api目录中执行 npm start
+8080
+
+npx create-react-app hkzf-mobile
+
+npm install antd-mobile --save
+
+npm install react-router-dom
+
+对象简写方式
+```
+{message:message}=>{message}
+```
+
+
+
+
+
+
+
+
+
+09
+14
+15
+27
\ No newline at end of file
diff --git a/react/项目/11.获取数据.md b/react/项目/11.获取数据.md
new file mode 100644
index 0000000..e87e0d7
--- /dev/null
+++ b/react/项目/11.获取数据.md
@@ -0,0 +1,7 @@
+获取数据
+1. 安装axios:npm i axios
+2. 在Index组件中导入axios
+3. 在state中添加轮播图数据:swipers
+4. 新建一个方法getSwipers用来获取轮播图数据,并更新swipers状态
+5. 在componentDidMount钩子函数中调用该方法
+6. 使用获取到的数据渲染轮播图
\ No newline at end of file
diff --git a/react/项目/12.sass文件使用.md b/react/项目/12.sass文件使用.md
new file mode 100644
index 0000000..43104fc
--- /dev/null
+++ b/react/项目/12.sass文件使用.md
@@ -0,0 +1,5 @@
+安装
+```
+npm i node-sass
+```
+修改文件名为scss
\ No newline at end of file
diff --git a/react/项目/13.租房小组.md b/react/项目/13.租房小组.md
new file mode 100644
index 0000000..dc9fbea
--- /dev/null
+++ b/react/项目/13.租房小组.md
@@ -0,0 +1,23 @@
+1. state中添加租房小组数据group
+2. 新建一个方法getGroups用来获取数据,并更新groups状态
+3. 在componentDidMount钩子函数中调用该方法
+4. 使用过去到的数据渲染租房小组数据
+# H5中的地理位置API
+```html
+navigator.geolocation.getCurrentPosition(position=>{
+ console.log("当前位置信息",position)
+})
+```
+
+懒渲染
+可视区域渲染,大列表
+
+react-virtualized
+
+1. 将获取到的cityList和cityIndex添加为组件的状态数据
+2. 修改List组件的rowCount为cityIndex的长度
+3. 将rowRender函数添加到组件内部,以便在函数中获取到状态数据cityList和cityIndex
+4. 修改List组件的RowRender为组件中的rowRender方法
+5. 修改rowRender方法中渲染的每行格式结构和样式.
+6. 修改list组件的rowHeight为函数,动态计算每一行的高度
+7.
\ No newline at end of file
diff --git a/react/项目/14.cssInJs.md b/react/项目/14.cssInJs.md
new file mode 100644
index 0000000..4efb451
--- /dev/null
+++ b/react/项目/14.cssInJs.md
@@ -0,0 +1,19 @@
+使用JavaScript编写CSS的统称,用来解决CSS样式冲突,覆盖的问题.
+CSS-Model:BEM(Block 块,Element元素,Modifier三部分组成)
+```
+import styles from './index.module.css'
+测试样式覆盖
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vue/1-vue官网学习.md b/vue/1-vue官网学习.md
new file mode 100644
index 0000000..7a39340
--- /dev/null
+++ b/vue/1-vue官网学习.md
@@ -0,0 +1,206 @@
+#### 绑定 v-bind
+
+v-bind attribute :将这个元素节点的 `title` attribute 和 Vue 实例的 `message` property 保持一致
+
+```javascript
+
+
+ 鼠标悬停几秒钟查看此处动态绑定的提示信息!
+
+
+var app2 = new Vue({
+ el: '#app-2',
+ data: {
+ message: '页面加载于 ' + new Date().toLocaleString()
+ }
+})
+```
+
+在控制台输入改变信息:app2.message = '新消息'
+
+#### 控制元素显示 v-if
+
+```js
+
+var app3 = new Vue({
+ el: '#app-3',
+ data: {
+ seen: true
+ }
+})
+```
+
+直接在控制台改变属性:app3.seen = false
+
+#### 循环展示 v-for
+
+```js
+
+
+ -
+ {{ todo.text }}
+
+
+
+
+var app4 = new Vue({
+ el: '#app-4',
+ data: {
+ todos: [
+ { text: '学习 JavaScript' },
+ { text: '学习 Vue' },
+ { text: '整个牛项目' }
+ ]
+ }
+})
+```
+
+在控制台改变内容:app4.todos.push({ text: '新项目' })
+
+#### 添加一个事件监听器 v-on
+
+```javascript
+
+var app5 = new Vue({
+ el: '#app-5',
+ data: {
+ message: 'Hello Vue.js!'
+ },
+ methods: {
+ reverseMessage: function () {
+ this.message = this.message.split('').reverse().join('')
+ }
+ }
+})
+```
+
+#### 表单输入和应用状态之间的双向绑定 v-model
+
+```js
+
+
+var app6 = new Vue({
+ el: '#app-6',
+ data: {
+ message: 'Hello Vue!'
+ }
+})
+```
+
+#### 组件
+
+- 任意类型的应用界面都可以抽象为一个组件树。
+
+- 子单元通过 prop 接口与父单元进行了良好的解耦。
+
+- 所有的 Vue 组件都是 Vue 实例。
+
+```js
+Vue.component('todo-item', {
+ // todo-item 组件现在接受一个
+ // "prop",类似于一个自定义 attribute。
+ // 这个 prop 名为 todo。
+ props: ['todo'],
+ template: '{{ todo.text }}'
+})
+
+
+
+var app7 = new Vue({
+ el: '#app-7',
+ data: {
+ groceryList: [
+ { id: 0, text: '蔬菜' },
+ { id: 1, text: '奶酪' },
+ { id: 2, text: '随便其它什么人吃的东西' }
+ ]
+ }
+})
+
+```
+
+#### 响应式
+
+- 当一个 Vue 实例被创建时,它将 `data` 对象中的所有的 property 加入到 Vue 的**响应式系统**中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
+- 值得注意的是只有当实例被创建时就已经存在于 `data` 中的 property 才是**响应式**的。
+- `Object.freeze()`,这会阻止修改现有的 property,也意味着响应系统无法再*追踪*变化。
+
+```js
+var obj = {
+ foo: 'bar'
+}
+
+Object.freeze(obj)
+
+new Vue({
+ el: '#app',
+ data: obj
+})
+
+
+
{{ foo }}
+
+
+
+```
+
+- 除了数据 property,Vue 实例还暴露了一些有用的实例 property 与方法。它们都有前缀 `$`,以便与用户定义的 property 区分开来。
+
+```js
+var data = { a: 1 }
+var vm = new Vue({
+ el: '#example',
+ data: data
+})
+
+vm.$data === data // => true
+vm.$el === document.getElementById('example') // => true
+
+// $watch 是一个实例方法
+vm.$watch('a', function (newValue, oldValue) {
+ // 这个回调将在 `vm.a` 改变后调用
+})
+```
+
+#### 生命周期钩子
+
+- 生命周期钩子的 `this` 上下文指向调用它的 Vue 实例。
+- 不要在选项 property 或回调上使用箭头函数
+
+```js
+new Vue({
+ data: {
+ a: 1
+ },
+ created: function () {
+ // `this` 指向 vm 实例
+ console.log('a is: ' + this.a)
+ }
+})
+// => "a is: 1"
+```
+
+
+
diff --git a/vue/2-模板语法.md b/vue/2-模板语法.md
new file mode 100644
index 0000000..e20016c
--- /dev/null
+++ b/vue/2-模板语法.md
@@ -0,0 +1,110 @@
+如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,你也可以不用模板,[直接写渲染 (render) 函数](https://cn.vuejs.org/v2/guide/render-function.html),使用可选的 JSX 语法。
+
+#### 数据绑定
+
+- 数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值。
+- 通过使用 [v-once 指令](https://cn.vuejs.org/v2/api/#v-once),你也能执行一次性地插值,当数据改变时,插值处的内容不会更新,类似Object.freeze()。但请留心这会影响到该节点上的其它数据绑定。
+
+```js
+Message: {{ msg }}
+这个将不会改变: {{ msg }}
+```
+
+#### v-html
+
+- 双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令
+
+```js
+Using mustaches: {{ rawHtml }}
+Using v-html directive:
+```
+
+#### v-bind
+
+- Mustache 语法不能作用在 HTML attribute 上,遇到这种情况应该使用 v-bind
+
+```js
+
+// 如果 isButtonDisabled 的值是 null、undefined 或 false,则 disabled attribute 甚至不会被包含在渲染出来的