react基础重新巩固
react的初始化安装命令
1.确保安装了node和npm
2.npm install -g create-react-app
3.进入相关目录
4.create-react-app 项目名称
5.cd 项目名称 //进入项目目录
6.npm start //启动项目
JSX写法规则
JSX里面只能写js表达式,不能写js的语句.表达式就是js的方法函数等等, 语句就是for循环,if判断,switch,while等等不能出现.
JSX的用途就是更方便的写dom结构,
函数式组件
function MyComponent(params) {
console.log(this)//this等于undefined 因为上面的babel 开启了严格模式,严格模式下this不能指向window
return <h2>456</h2>
}
ReactDOM.render(<MyComponent/>,document.getElementById('test'))
类组件
class MyComponent extends React.Component{
constructor(props){
super(props )
}
render(){
return <h2>我是类组件</h2>
}
}
ReactDOM.render(<MyComponent/>,document.getElementById('test'))
组件的三大属性
render()函数在初始化 和更新组件的时候都会调用,只要值改变了 那就会进行调用的
- props: {}
- refs: {}
- state: null
state的基础调用和修改值
setState是采用的合并策略,利用传递的对象和属性,去修改原state
class MyComponent extends React.Component{
constructor(props){
super(props )
}
state = {
ishot:'炎热'
}
render(){
console.log(this)
let name = this.props.name
//这里的话因为 是返回了一个jsx 模板,然后这个模板又在外部函数里面被调用了
//所以这个return 里面的this并不是指向的组件实例了
//所以这里应该使用bind 对方法重新加引用
return <h2 onClick={this.demo}>我是类组件{this.state.ishot}</h2>
}
demo =()=>{
console.log(this)
this.setState({ishot:!ishot})
}
}
ReactDOM.render(<MyComponent name="tom"/>,document.getElementById('test'))
props基础组件传值
ReactDOM.render(<MyComponent name="tom"/>,document.getElementById('test'))
利用展开运算符传值
展开运算符用法
let arr=[1,2,3]
let arr1=[1,2,3]
let merge = [...arr,...arr1]//可以分解数组并且合并产生一个新数组
let obj1={name:'x',age:18}
let obj2 = {sex:'女'}
let obj3 = {...obj1}//可以做深拷贝
let mergeobj = {...obj1,...obj2}//可以克隆两个对象进行合并
…不能展开对象会报错
展开对象的话 必须使用 {…对象}这样才能展开对象,并且可以做深拷贝克隆的时候使用
const stu = {name:'x',age:19}
ReactDOM.render(<MyComponent {...stu}/>,document.getElementById('test'))
传入的类型限制
注意位置 是在类的外面进行定义的
![[]](https://img-blog.csdnimg.cn/f8a702bc54214ae8bcd7cd4ceb5cb47b.png)
将限制传值类型等放入类的内侧,使用static静态,给类添加限制
构造器的作用和传递props的作用
主要是在构造器里面做一些初始化的操作,操作this.props的用处,完全可以省略 构造器函数
函数式组件的props
refs的使用和作用
在react中尽量少使用ref 不管是ref的哪种方式
this.refs不被推荐使用因为效率不高
this.refs.名称,这个是获取真实dom,并且可以进行操作
class CliBtn extends React.Component{
state = {leftText:''}
render(){
return (
<div>
<input ref='input1' type="text" onChange={this.change} placeholder="请输入内容">
</input>
<button onClick={this.leftTishi}>点击提示左侧数据</button>
<input ref='input2' type="text" onBlur={this.blurC} placeholder="失去焦点提示输入内容提示"/>
</div>
)
}
leftTishi = ()=>{
alert(this.refs.input1.value)
}
blurC = ()=>{
alert(this.refs.input2.value)
}
}
ReactDOM.render(<CliBtn/>,document.getElementById('test'))
使用回调函数的方式获取节点 官方比较推荐
标签上的回调函数 只有官方定义的可以调用,自定义的回调属性会报错 例如 cc={()=>{}}这里的cc就是没有被官方定义的
class CliBtn extends React.Component{
state = {leftText:''}
render(){
return (
<div>
<input ref={(c)=>{this.input1=c}} type="text" onChange={this.change} placeholder="请输入内容">
</input>
<button onClick={this.leftTishi}>点击提示左侧数据</button>
<input ref={(c)=>{this.input2=c}} type="text" onBlur={this.blurC} placeholder="失去焦点提示输入内容提示"/>
</div>
)
}
leftTishi = ()=>{
let {input1} = this
alert(input1.value)
}
blurC = ()=>{
let {input2} = this
alert(input2.value)
}
}
react最推荐的ref方式:ref容器
使用myinput = React.createRef()的方式调用方法,然后获取节点,
使用this.myinput.current.value获取值
class CliBtn extends React.Component{
state = {leftText:''}
myinput1 = React.createRef()
myinput2 = React.createRef()
render(){
return (
<div>
<input ref={this.myinput1} type="text" onChange={this.change} placeholder="请输入内容">
</input>
<button onClick={this.leftTishi}>点击提示左侧数据</button>
<input ref={this.myinput2} type="text" onBlur={this.blurC} placeholder="失去焦点提示输入内容提示"/>
</div>
)
}
leftTishi = ()=>{
alert(this.myinput1.current.value)
}
blurC = ()=>{
alert(this.myinput2.current.value)
}
}
ReactDOM.render(<CliBtn/>,document.getElementById('test'))
react的事件代理,
react将事件都委托给了 最外层的元素,然后用过了event.target.value获取到了具体时间那个节点触发的事件
document.addEventListener("click", function (event) {
var target = event.target;
switch (target.id) {
case "doSomething":
document.title = "事件委托";
break;
case "goSomewhere":
location.href = "http://www.baidu.com";
break;
case "sayHi": alert("hi");
break;
}
})
//监听最外层元素即可
非受控组件与受控组件
就是组织表单等的默认行为.如果什么都不写的话 就会导致表单的默认行为发生不可控的事件
使用event.preventDefault()在方法里面进行阻止和控制,
非受控组件,主要是在取值的时候,使用现用现取的方式去取值,e.target的方式取值,并没有将数据维护到state里面去
受控组件:主要是将值维护到state里面去了, 改变值的时候也把值更新到state当中,
推荐还是使用受控组件,这里还是要想起vue了,vue主要就是采用的受控组件的方式进行获取的.,越学 越感觉vue好像也不错啊,react更有点像手动再实现了 vue的相关方法呢
关于函数柯里化以及 改变值传参
因为onChange={this.saveForeData()}//onChange需要得到一个函数, 所以this.saveFormData需要返回一个函数,同时还可以接受参数的传递,用来区分到底是哪一个字段.如下所示
函数柯里化 就是通过函数调用继续返回函数的方式,对参数进行统一处理的方法,下面的saveFormData就是函数的柯里化
不使用柯里化的传参形式
函数开发的简单写法
class mycomponent extends React.Component{
custructor(props){
super(props}
state = {}
clickEvent= ()=>{}//函数简单写法,可以在函数里面使用this,否则的话 使用函数声明式定义是不能获取this的,因为调用函数的时候是不在实例对象内的
}
react进阶
安装react脚手架
1.进入创建的项目,然后运行以下命令,注意在执行npm run eject之前不能修改里面的内容,如果修改了就要删除掉.git这个隐藏文件夹,才能执行以下命令.
npm run eject
2.修改配置文件
关于redux
什么是redux? 它是管理数据状态的应用工具 类似vuex的数据管理工具
组件—调用—>actionCreaturs—查找—>store(判断是否有书籍)—>有书籍直接给组件,
---->没有书籍的话就去Reducers里面查一下,将数据返回store再给组件
安装redux npm install --save-dev redux 进行安装
安装使用ant design图形库 npm install antd --save-dev
关于redux的使用
//1.创建store文件,以下方法已经被弃用,
import { createStore } from 'redux';
import reducer from './reducer';
const stoer = createStore(reducer)
export default stoer
//2.创建reducer文件
const defaultState = {
inputVal:'hhh',
List:[1,2,3,4,5,6]
}
export default (state=defaultState,action)=>{
return state
}
//3.使用store数据//在组建的构造函数中使用,获取值
import store from './store/store';
constructor(props){
super(props)
console.log(store.getState())
this.state=store.getState()
}
对应上面的流程,目前还没有action
关于react-router
前端路由原理,主要是监测地址
前端路由主要是使用history的js文件 进行的跳转
为什么用#哈希值,因为在浏览器中,#号后面的内容不会发给浏览器
关于路由的基础使用
在app.js 组件外侧使用
<BrowerRouter>
<App/>
</BrowserRouter/>包裹App文件
//链接
<Link to="/home">链接</Link>
<NavLink activeClassName="自定义类名"></NavLink>//可以添加点击样式
//渲染位置
<Route path="/home" component="home组件地址"></Route>
Switch对路由进行匹配的,如果找到了一个路由就不再继续向下找了,否则会继续向下进行匹配
<Switch>
<Route></Route>
</Switch>
关于导入文件,可能会引起刷新页面资源不匹配,所以需要修改引入文件的路径,不加点的用法,或者使用 %PUBLIC_URL%路径,或者改为哈西的匹配方法
关于模糊查询,使用exact会对路由进行精准查询,一般情况不用,因为会引发问题。在路由嵌套的时候
也是要放到Switch里面的组件,当所有路由都匹配不上的时候会走Redirect
关于多级路由匹配的时候是一级一级去寻找的,先匹配父级,在继续向内找。
路由传值
路由接收参数
关于路由传参的search方式传值
search方式的接收值
state参数传递
接收参数,state方式在地址栏不显示参数,但是刷新也能用
可以自己实现浏览器的前进和后退功能
路由的内容只能在路由组件里面使用,一般组件想用路由组件的话需要使用withRouter封装
router模式之间的区别