
参考:尚硅谷React技术全家桶全套完整版(零基础入门到精通/男神天禹老师亲授)_哔哩哔哩_bilibili
GitHub - xzlaptt/React: React学习
npm( Node Package Manager ,即:node包管理器 )
是nodeJS的一个程序包管理和分发的管理工具,npm完全用 JavaScript 写成,
它可以让全世界与Web前端相关开发者共享代码,非常方便的使用各种插件、库和框架,
React用于构建用户界面的JS库。是一个将数据渲染为HTML视图的开源JS库。
eg:vue react Bootstrap jQuery Angular
优化开发流程的前端开发自动化构建工具: Grunt 、 Gulp 、 Webpack 、 Babel
npm包管理工具的安装及配置使用_雯倾浅忆的博客-CSDN博客_npm包管理器
Nodejs安装教程_彭佼的博客-CSDN博客_nodejs安装
BabelJavaScript 编译器
将es6+语法转换为浏览器兼容的语法,比如将箭头函数转换为普通函数
将jsx转换成浏览器认的js
Babel是什么?Babel到底可以用来干嘛___一文带你从零开始认识Babel_zihanzy.com的博客-CSDN博客_babel是什么
React特点
jsx注释:
html
js //注释 ctrl+/ /*注释*/ ctrl+shitf+/
{js表达式}
jsx {/*注释*/}
JSX语法详解_RockyHills的博客-CSDN博客_jsx语法
组件props
组件对外公开一个简单的属性(Props),只读
通过this.props获取属性对象,主要用来传递数据
2、Reactjs中的属性(this.props)_yubo_725的博客-CSDN博客_react this.props传递对象时
//类组件使用
//函数组件使用
function Person(props){
return (
{props.name}
{props.age}
{props.sex}
)
}
... 展开运算符
1.主要用来展开数组
arr = [1,2,3];
arr1 = [4,5,6];
arr2 = [...arr,...arr1]; //arr2 = [1,2,,3,4,5,6]
2.复制一个对象给另一个对象(值传递)
const p1 = {name:"张三",age:"18",sex:"女"}
const p2 = {...p1};
p1.name = "sss";
console.log(p2) //{name:"张三",age:"18",sex:"女"}
3.复制时,合并属性
const p1 = {name:"张三",age:"18",sex:"女"}
const p2 = {...p1,name : "111",hua:"ss"};
p1.name = "sss";
console.log(p2) //{name: "111", age: "18", sex: "女",hua:"ss"}
4. {...P}并不能展开一个对象
props传递一个对象,是因为babel+react使得{..p}可以展开对象,但是只有在标签中才能使用
2、Reactjs中的属性(this.props)_yubo_725的博客-CSDN博客_react this.props
state
组件的私有属性,值是对象(可以包含多个key-value的组合)
React控制之外的事件中调用setState是同步更新的。比如原生js绑定的事件,setTimeout/setInterval等。
大部分开发中用到的都是React封装的事件,比如onChange、onClick、onTouchMove等,这些事件处理程序中的setState都是异步处理的。
在 React 的 setState 函数实现中,会根据一个变量 isBatchingUpdates 判断是直接更新 this.state 还是放到队列中延时更新,而 isBatchingUpdates 默认是 false,表示 setState 会同步更新 this.state;
当 React 在调用事件处理函数之前就会先调用函数 batchedUpdates,
batchedUpdates会把 isBatchingUpdates 修改为 true,
如果是同步更新,每一个setState对调用一个render,
并且如果多次调用setState会以最后调用的setState为准
Refs字符串形式的ref(16.8版本以上已不推荐)
解构赋值
const {inputL}=this.refs
连续解构赋值
const {value}=this.target
<=>
const {target:{value}}=this
//将value重命名为key
const {target:{value:key}}=this
只有字符串形式时Refs才有值
回调函数形式的ref
API创建Ref
组件三大属性总结 props:单向数据流值,父子组件间的唯一通信,不可改
1.每个组件对象都会有props(properties的简写)属性
2.组件标签的所有属性都保存在props中
3.内部读取某个属性值:this.props.propertyName
state:React 把组件看成是一个状态机(State Machines),
只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要 *** 作 DOM)。
props中的数据都是外界传递过来的;state中的数据都是组件私有的;(通过Ajax获取回来的数据,一般都是私有数据)
refs:
当需要获取某一个真实的DOM元素来交互,比如文本框的聚焦、触发强制动画等
当需要 *** 作的元素和获取的元素是同一个时,无需ref
给DOM元素添加ref属性给类组件添加ref属性 React事件event.target得到发生事件的Dom元素对象
saveName = (event) =>{
this.setState({name:event.target.value});
}
组件通信
父传子:父组件的state作为子组件的props,当父组件的state改变,子组件的props也跟着改变
祖孙,需要一层层传递,组件层级嵌套到比较深,可以使用上下文getChildContext来传递信息,这样在不需要将函数一层层往下传,任何一层的子级都可以通过this.context直接访问
子传父:父组件的函数作为子组件的props,子组件调用父组件的函数来改变state
兄弟:订阅和发布机制PubSub
发布
import Pubsub from 'pubsub-js'
export const pubsubID = 'd806a360-21aa-406e-9e5f-7f375087514f' // pubsub token
Pubsub.publish(StationStatisticsID, data)
// 或
PubSub.publishSync(StationStatisticsID, data)
PubSub.publish("订阅的消息名称",传递的数据)
订阅
import Pubsub from 'pubsub-js'
import {pubsubID} from 'xxx'
componentDidMount() {
/**
* 订阅
*/
pubsub = Pubsub.subscribe(pubsubID, (msg, data) => {
console.log(msg) // 这里将会输出对应设置的 pubsubID
console.log(data) // 这里将会输出对应设置的参数
})
}
componentWillUnmount() {
/**
* 取消指定的订阅
*/
Pubsub.unsubscribe(pubsub)
/**
* 取消全部订阅
*/
PubSub.clearAllSubscriptions()
}
PubSub.subscribe("订阅的消息名称",回调函数,第一个参数是消息名称,可以使用_来占位,第二个是传递的数据
})
顶层组件通信:
只是单纯的进行视图的渲染,这时候用回调,context就行,没必要用redux,用了反而影响开发速度。
redux相当于在顶层组件之上又加了一个组件
redux是一个专门用于做状态管理的JS库(不是react插件库)。
action 动作的对象包含2个属性 type:标识属性, 值为字符串, 唯一, 必要属性data:数据属性, 值类型任意, 可选属性例子:{ type: 'ADD_STUDENT',data:{name: 'tom',age:18} }
mapStateToprops:将外部的数据(即state对象)转换为UI组件的标签属性
mapDispatchToProps:将分发action的函数转换为UI组件的标签属性
组件之间的信息还可以通过全局事件来传递。不同页面可以通过参数传递数据,下个页面可以用location.param来获取。
React事件 非受控组件现用现取,官方建议尽量少用ref,用多了有一定的效率影响
handleSubmit = (event) => {
event.preventDefault() //阻止表单提交
const {username, password} = this//拿到的是form下的username, password结点
alert(`你输入的用户名是:${username.value},你输入的密码是:${password.value}`)
}
render() {
return (
)
}
}
//渲染组件
ReactDOM.render( , document.getElementById('test'))
高阶函数
参数 或者 返回 为函数
函数的珂里化通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式
function sum(a){
return(b)=>{
return (c)=>{
return a+b+c
}
}
}
//保存表单数据到状态中
saveFormData = (dataType, event) => {
this.setState({[dataType]: event.target.value})
}
用户名: this.saveFormData('username', event)} type="text" name="username"/>
//珂里化
//返回一个函数
saveType = (type) =>{
return (event) => {
this.setState({[type]:event.target.value});
}
}
//因为事件中必须是一个函数,所以返回的也是一个函数,这样就符合规范了
render() {
return (
)
}
}
新旧生命周期总结
React组件中包含一系列钩子函数{生命周期回调函数}
key//index标识
person:[
{id:1,name:"张三",age:18},
{id:2,name:"李四",age:19}
]
//map遍历
this.state.person.map((preson,index)=>{
return {preson.name}
})
//name标识
addObject = () =>{
let {person} = this.state;
const p = {id:(person.length+1),name:"王五",age:20};
this.setState({person:[p,...person]});
}
虚拟dom是没有input.value的值的,只有在真实虚拟dom用户输入了才显示,所以diff时候就算是一样的input
Diff算法react生成的新虚拟DOM和旧虚拟DOM的比较规则:
如果旧的虚拟DOM中找到了与新虚拟DOM相同的key:
如果内容没有变化,就直接只用之前旧的真实DOM如果内容发生了变化,就生成新的真实DOM如果旧的虚拟DOM中没有找到与新虚拟DOM相同的key:
根据数据创建新的真实的DOM,随后渲染到页面上 React脚手架Webpack的基本使用_sut_uestc的博客-CSDN博客
eject暴露webpack配置
React App
react脚手架项目结构
public ---- 静态资源文件夹
favicon.icon ------ 网站页签图标
index.html -------- 主页面
logo192.png ------- logo图
logo512.png ------- logo图
manifest.json ----- 应用加壳的配置文件
robots.txt -------- 爬虫协议文件
src ---- 源码文件夹
App.css -------- App组件的样式
App.js --------- App组件(首字母大写的是组件)
App.test.js ---- 用于给App做测试
index.css ------ 样式
index.js ------- 入口文件
logo.svg ------- logo图
reportWebVitals.js
--- 页面性能分析文件(需要web-vitals库的支持)
setupTests.js
---- 组件单元测试的文件(需要jest-dom库的支持)
webpack-dev-server帮助本地内置服务器开启,所以不能关闭cmd
React.Component
等价于 将React中的Component取出来
const {Component}=React
//module.js
//定义了一个React对象
const React={a:1,b:2}
//暴露
export class Component{
}
//追加一个Component属性
React.Component=Component
//暴露了才能引入,默认暴露只能一个
export default React
//App.js
import React,{Component} from './module'
由于普通的Js和组件都是js,所一最好组件使用jsx去展示组件(组件首字母大写)
样式模块化两个组件中样式名称有可能会冲突,这样会根据引入App这个组件的先后顺序,后面的会覆盖前面的,
为了避免这样的样式冲突,我们采用下面的形式:
1.将css文件名修改: hello.css --- >hello.module.css
2.引入并使用的时候改变方式:
import React,{Component}from 'react'
import hello from './hello.module.css' //引入的时候给一个名称
//变量hello自动转换为对象
export default class Hello extends Component{
render() {
return (
Hello //通过大括号进行调用
)
}
}
组件的组合使用-TodoList
将html复制到jsx时
注意 改缩进+标签闭合+
../返回到上级目录
回调函数:被当做参数使用的函数
js 彻底理解回调函数_dkvirus的博客-CSDN博客_js回调函数
指定事件回调时,传参时调用得返回一个函数,所以要写成高阶函数
onXxx类事件,得对应函数
脚手架配置代理React本身只关注与页面,并不包含发送ajax请求的代码,所以一般都是集成第三方的一些库,或者自己进行封装。
推荐使用axios。
在使用的过程中很有可能会出现跨域的问题,这样就应该配置代理。
所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port), 当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
方法一
在package.json中追加如下配置
"proxy":"请求的地址" "proxy":"http://localhost:5000"
说明:
优点:配置简单,前端请求资源时可以不加任何前缀。缺点:不能配置多个代理。工作方式:上述方式配置代理,当请求了3000不存在的资源时,那么该请求会转发给5000 (优先匹配前端资源)方法二
1.创建代理配置文件
在src下创建配置文件:src/setupProxy.js
2.编写setupProxy.js配置具体代理规则:
const proxy = require('http-proxy-middleware')
module.exports = function(app) {
app.use(
proxy('/api1', { //api1是需要转发的请求(所有带有/api1前缀的请求都会转发给5000)
target: 'http://localhost:5000', //配置转发目标地址(能返回数据的服务器地址)
changeOrigin: true, //控制服务器接收到的请求头中host字段的值
/*
changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
changeOrigin默认值为false,但我们一般将changeOrigin值设为true
*/
pathRewrite: {'^/api1': ''} //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
}),
proxy('/api2', {
target: 'http://localhost:5001',
changeOrigin: true,
pathRewrite: {'^/api2': ''}
})
)
}
说明:
优点:可以配置多个代理,可以灵活的控制请求是否走代理。缺点:配置繁琐,前端请求资源时必须加前缀。 React路由 SPA单页Web应用(single page web application,SPA)。
整个应用只有一个完整的页面。
点击页面中的链接不会刷新页面,只会做页面的局部更新。
数据都需要通过ajax请求获取,并在前端异步展现
React 路由详解(超详细详解)_江北阳小皮~的博客-CSDN博客_react路由
react-router-dom v6 使用_别样红。的博客-CSDN博客_react router v6
Redirect V6 版本已经废弃,需要导入Hook钩子Navigate ,
{/* exact =true 开启路由精准匹配={true}可以省略 尽量不开启严格匹配*/}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)