React学习日记
组件化方面
1.模块化:是从代码的角度来进行分析的,把一些可复用的代码,抽离为单个的模块;便于项目的开发与维护
2.组件化:是从UI界面的角度来进行分析,把一些可以复用的UI元素,抽离为单独的组件,便于项目的开发与维护
3.React是如何实现组件化的:React中有组件化概念,但是,并不是像Vue这样的组件模版文件,在React中,一切都是以JS来表现的。
React中的几个核心的概念
虚拟DOM
DOM和虚拟DOM的区别:
- DOM:浏览器中,提供的概念;用JS对象,表示页面上的元素,并提供操作元素的API
- 虚拟DOM:是框架中的概念;开发框架中的程序员手动用JS对象来模拟DOM元素和嵌套关系;
本质:用js对象来模拟DOM元素和嵌套关系;
目的:就是为了实现页面元素的高效更新;
Diff算法
- tree diff:新旧两颗DOM树,逐层对比的过程,就是Tree Diff,当整颗DOM逐层对比完毕,则所有需要按需更新的元素,必然能够找到;
- componet diif:在进行Tree Diff 的时候,每一层中,组件级别的对比,叫做Component Diff;
- 如果对比前后,组件的类型相同,则暂认为此组件不需要更新
- 如果对比后,组件类型不同,则需要移除旧组件,创建新组件,并追加到页面上
- element diff:在进行组件对比的时候,如果两个组件类型相同,则需要进行元素级别的对比,这叫做Element Diff;
在项目中使用react
1.运行npm i react react-dom
-
react:专门用于创建组件和虚拟DOM的,同时组件的生命周期都在这个包中
-
react-dom:专门进行DOM操作,最主要的应用场景,就是ReactDOM.render()
2.中index.html页面中,创建容器
<div id=“app”></div>
3.在index.js导入包:
import React from 'react';//创建组件、虚拟DOM元素,生命周期
import ReactDOM from 'react-dom';//把创建好的 组件和虚拟DOM放在页面上展示的。
4.创建虚拟DOM元素:
// 这是一个创建<h1 title="啊,五环" id="myh1">子节点</h1>
// 第一个参数 创建的标签名称
// 第二个参数 元素的属性
// 第三个参数 字节点
const myh1=React.createElement('h1',{title:'啊,五环',id:"myh1"},'子节点')
5.渲染:
ReactDOM.render(
myh1,//要渲染的虚拟DOM对象
document.getElementById('app')//指定容器
);
使用JSX语法
1.使用Babel转译器会把JSX转换成一个名为React.createElement()的方法调用。
配置Babel后可直接这样使用
const mytext="你好"
ReactDOM.render(
<h1>{mytext}</h1>,//要渲染的虚拟DOM对象
document.getElementById('app')//指定容器
);
2.jsx语法的本质:并不是直接渲染到页面上,而是内部通过Babel内部转换createElement形式,再渲染的
3.在jsx中混合写入js表达式:要把JS代码写到{}
中
4.在jsx中写注释推荐使用:{/*注释*/}
5.为jsx中的元素添加class类名:需要用className
来替代class
;htmlFor
替换label的for属性
将组件单独抽离出为.jsx文件
新建Hello.jsx文件
export default function Hello(){ //导出
return <div>这是Hello组件</div>
}
在index.js 中引入 即可使用
import Hello from "@/Hello"; //省略后缀名,是在webpack.config.js里面配置了,默认补全
- 可以在webpack.config.js通过alias配置@代表src路径
alias: {
'@':path.join(__dirname,'../src'), //表示@为根目录中src的这一层路径
}
React的组件定义与使用
通过函数定义
function Hello(){
return <div>这是Hello组件</div>
}
ReactDOM.render(
<Hello/>,
document.getElementById('root')
);
为组件传递数据:
function Hello(props){
console.log(props)
return <div>这是Hello组件 ---{props.name}</div>
}
ReactDOM.render(
<Hello name='张三' />,
document.getElementById('root')
);
通过ES6类class来定义
class Hello extends React.Component {
render() {
return (
<div className="Hello">
这是Hello组件
</div>
);
}
}
ReactDOM.render(
<Hello/>,
document.getElementById('root')
);
通过class 创建的组件中,如果想使用外界传过来的props参数,不需要接收,直接通过this.props.xxx访问即可
三大核心属性1.state
class Square extends React.Component {
constructor(props) {
super(props);
this.state={
value:undefined,
}
}
btnClick(){
this.setState({value:'x'})
};
render() {
return (
<button onClick={ ()=>this.props.onClick()} className="square">
{this.props.value}
</button>
);
}
}
三大核心属性2.props
//props是只读的
三大核心属性3.refs与事件处理
1.refs的基础使用(字符串形式的ref不建议使用,建议使用回调函数的refs)
//ref 的使用,
export default class Refs extends React.Comp1onent {
ShowInputVal=()=>{
console.log(this.refs.myInput.value)
}
render(){
return (<div>
<input ref="myInput" />
<button onClick={this.ShowInputVal}>获取inpnt的值</button>
</div>)
}
}
2.回调形式的的refs
export default class Refs extends React.Component {
ShowInputVal = () => {
console.log(this.myInput.value)
}
render() {
return (<div>
<input ref={(node)=>{this.myInput=node}} />
<button onClick={this.ShowInputVal}>获取inpnt的值</button>
</div>)
}
}
3.createRef
export default class Refs extends React.Component {
//React.createRef() 调用后可以返回一个容器,该容器可以存储ref被标记的节点,该容器是'专人专用'的
myRef=React.createRef()
ShowInputVal = () => {
console.log(this.myRef.current.value)
}
render() {
return (<div>
<input ref={this.myRef} />
<button onClick={this.ShowInputVal}>获取inpnt的值</button>
</div>)
}
}
事件处理
(1)通过onxxx属性指定事件处理函数
(2)通过event.targetdet得到发生事件等DOM元素对象
高阶函数
savaFormData=(val)=>{
//必须给一个函数给onChange作为回调
return (event)=>{
console.log(event.targetdet.value)
}
}
//必须给一个函数给onChange作为回调
<input onChange={this.savaFormData('username')} ref={this.myRef} />
两种创建组件的方式对比
注意:使用class创建的组件,有自己的私有数据(this.state)和生命周期函数;
使用function创建的组件,只有props,没有自己的私有数据和生命周期函数;
1.用构造函数创建出来的组件:叫做“无状态组件”
2.用class创建的组件:叫做"有状态组件"
3.什么情况下使用有状态组件?什么情况下使用无状态组件?
- 如果一个组件需要有自己的私有数据,则推荐使用:class创建的有状态组件;
- 如果一个组件不需要有私有数据,则推荐使用:无状态组件;
- React官方说:无状态组件,由于没有自己的state和生命周期函数,所以运行效率高
有状态组件和无状态组件的本质区别就是:有无state属性和有无生命周期函数
生命周期
1.初始化阶段:由ReactDOM.render()触发–初次渲染
- constructor() //构造器
- componentWillMount() // 组件将要挂载
- render()
- componentDidMount() //组件完成挂载
2.更新阶段:由组件内部this.setSate()或父组件render触发
- shouldComponentUpdate() //控制组件更新的阀门钩子
- componentWillUpdate() //组件将要更新
- render()
- componentDidUpdate() //组件更新完毕
3.卸载组件
- componentWillUnmount() //卸载组件钩子