关于react
react起初由Facebook工程师Jordan Walke创建,于2011年不属于Facebook的newsfeed,随后在2012年部署于Instagram,2013年5月宣布开源,近10年“陈酿”,react正在被腾讯、阿里等一线大厂广泛使用。react是用于构建用户界面的javascript库。简单的说,就是只关注视图,我们只需要做数据处理,react帮我们去操作dom呈现页面。
为什么学习react
1 原生javascript操作dom频繁,效率低
2 使用javascript直接操作dom,浏览器会进行大量的重绘重排
3 原生javascript没有组件化变成方案,代码复用率低
react特点
1 采用组件化模式、声明式编码,提高开发效率及组件复用率
2 在React Native中可以使用react语法进行移动端开发
3 使用虚拟dom+diffing算法,尽量减少与真实dom的交互
react入门
jsx
下面是关于jsx的一个最简单的demo及注意事项
类式组件与函数式组件
顾名思义,用函数编写的组件就是函数组件,用类编写的组件就是类组件。那什么时候需要用函数组件什么时候需要用类组件呢?下面就引出了组件三大核心属性之一,state。
state
state是用来做初始化状态的,要注意以下几点
1 state必须是一个对象
2 组件render中的this为组件实例对象
3 组件自定义的方法this是undefined 如何解决
a 强制绑定this 通过函数对象的bind()
b 箭头函数
4 状态数据不能直接修改,通过setState方法修改
eg :
class Mycomponent extends React.Component {
state = {
isHOT:true
}
demo = () => {
const {isHOT} = this.state
this.setState({
isHOT:!isHOT
})
}
render(){
const {isHOT} = this.state
return <h1 onClick={this.demo}>今天天气{this.state.isHOT?'很好':'不好'}</h1>
}
}
ReactDOM.render(<Mycomponent/>,document.querySelector('#root1'))
props
props作用于给组件传值 eg:
class Person extends React.Component {
render(){
const{name,age,sex} = this.props
return(
<ul>
<li>{name}</li>
<li>{age}</li>
<li>{sex}</li>
</ul>
)
}
}
const persons = {name:'zz',age:18,sex:'难'}
ReactDOM.render(<Person {...persons}/>,document.querySelector('#root'))
<script>
// const persons = {name:'zz',age:18,}
// console.log(...persons) Uncaught TypeError: Found non-callable @@iterator
</script>
这里要注意的是...是不能直接展开对象的,外面必须包一层{},这里是因为引用react和babel帮我们做了处理,所以可以直接用。当然我们也可以对传入的数据做限制,如限制必传,类型,默认值等。 eg:
static propTypes = {
name: PropTypes.string.isRequired,//设置name是string类型必填
age: PropTypes.number,
speak:PropTypes.func//注意设置函数不能写function 要写func 否则会报错
}
static defaultProps = {
sex:'开心就好'
}
refs
refs有三种写法
- 字符串形式 直接给dom绑定ref,通过this.refs拿到value。这种方法不推荐使用,官方给出的解释是string类型的ref存在一些效率问题,已经过时了并且可能会在未来的版本移除。
class Demo extends React.Component {
showData = ()=>{
console.log(this.refs.input1.value)
}
showBlur = ()=>{
console.log(this.refs.input2.value)
}
render(){
return(
<div>
<input ref="input1" type="text" placrholder="点击按钮展示数据"/>
<button onClick={this.showData}>点击展示</button>
<input ref="input2" onBlur={this.showBlur} type="text" placrholder="失去焦点展示数据"/>
</div>
)
}
}
- 回调函数类型的ref 通过回调函数,把当前节点作为参数传递后在通过this.xx.value取值。这里有一点要注意,回调函数类型的ref如果是内联函数定义的,如果这个组件以后被更新,那么会被执行两次,并且第一次传入的参数是null,第二次传入的才是dom节点。这是因为每次渲染的时候都会创建一个新的函数实例,所以react会清除旧的ref并且设置新的。通过将ref定义成class绑定函数的方式可以避免该问题。不过官方也解释说写成内联函数是无伤大雅的。
3. 通过createRef
调用该方法返回一个容器,该容器可以存储被ref所标识的节点。再通过this.xx.current.value可以获取数据。这种方法麻烦的点就是用多少个就要创建多少个容易,不过是目前官方最推荐的形式。
说完三大件也就可以回到上面的问题了,再类组件中,state、props、ref都可以用,而函数组件只能用props(暂时不考虑hooks)。在我们需要用到这些属性的时候可以用类组件,简单的组件可以用函数组件。
react事件
react中绑定事件是通过on+事件名进行绑定,要注意事件名的首字母要大写,之所以用自定义(合成)事件而非原生事件,有2点原因
- 为了有更高的兼容性
- 通过事件委托方式做出了,为了更高的效率
生命周期
/**
* 生命周期
* 旧版本
* 1 初始化阶段:由ReactDOM.render()触发 =>初次渲染
* 1. constructor()
* 2. componentWillMount() 废弃
* 3. render()
* * 4. componentDidMount() 一般再这个钩子做初始化 开启定时器、发送网络请求、订阅消息
*
* 2 更新阶段:由组件内部this.setState()或父组件render触发
* 1. shouldComponentUpdate()
* 2. componentWillUpdate() 废弃
* 3. render()
* 4. componentDidUpdate()
*
* 3 卸载过程
* * 1.componentWillUnmount() 收尾 关闭定时器、取消订阅消息等
*
*
* 新版本
* 1 初始化阶段:由ReactDOM.render()触发 =>初次渲染
* 1. constructor()
* 2. getDerivedStateFromProps
* 3. render()
* * 4. componentDidMount()
* 2 更新阶段:由组件内部this.setState()或父组件render触发
* 1. getDerivedStateFromProps
* 2. shouldComponentUpdate()
* 3. render()
* 4. getSnapshotBeforeUpdate
* 4. componentDidUpdate()
* 3 卸载过程 由ReactDOM.UnmountComponentAtNode()触发
* * 1.componentWillUnmount()
*
*/
hooks
hook是react16.8版本新增加的新特性,可以再函数式组件使用state以及其他react特性
State Hook:React.useState()
让函数也有state状态并进行读写操作。 参数说明:第一次初始化指定的值会在内部作缓存。返回值是两个元素的数组,第一个是内部当前状态值,第二个为更新状态值的函数
const Demo = () => {
const [count,setCount] = React.useState(0)
const add = () =>{
//setCount(count+1)
setCount(count => count+1)
}
return (
<div>
<h2>和:{count}</h2>
<button onClick={add}>点我加1</button>
</div>
)
}
ReactDOM.render(<Demo />,document.querySelector('#root'))
Effect Hook
用于模拟类组件中的生命周期
const Demo = () => {
const [count,setCount] = React.useState(0)
React.useEffect(()=>{
let timer= setInterval(()=>{
setCount(count=>count+1)
},1000)
return clearInterval(timer) //做收尾工作 相当于componentWillUnmount
},[])
/**
* 不写数组要监测所有属性 再初始化和更新时触发,相当于(componentDidMount和componentDidUpdate)
* 空数组是所有都不监测 只在第一次render后执行 相当于(componentDidMount) */
const add = () =>{
//setCount(count+1)
setCount((count)=>{
return count
})
//console.log(count)
}
return (
<div>
<h2>和:{count}</h2>
<button onClick={add}>点我加1</button>
</div>
)
}
Ref Hook
可以再函数组件中存储或者查找组件内标签或者其他数据,和React.creatRef()用法功能类似
const Demo = () => {
const myRef = React.useRef()
const clickme = ()=>{
console.log(myRef.current.value)
}
return (
<div>
<input type="text" ref={myRef}/>
<button onClick={clickme}>点我</button>
</div>
)
}
ReactDOM.render(<Demo />,document.querySelector('#root'))