四时宝库

程序员的知识宝库

React18内核探秘:手写React高质量源码迈向高阶开...

React18内核探秘:手写React高质量源码迈向高阶开发

download:https://www.sisuoit.com/4316.html


预备阶段-基层环境

装置node.js(官网下载即可)

node -v (检查是否装置node完结)

装置yarn新一代的包管理工具facebook开发,你也可以挑选cnpm

yarn的速度会比npm快

装置版别统一,更安全

更简洁的输出

更好的语义化

sudo cnpm install yarn -gyarn -v(检查是否装置yarn完结)

运用git在马云上进行托管,并在本地clone下来项目

git clone 你项意图地址cd 你的项目

装备gitignore(git命令忽视)

vim .gitignorei(修改命令).DS_Store(Mac自带)node_modules(node包)dist(打包的压缩文件)*.log(错误信息等)

初始化项目

yarninit/cnpminit

提交项目

gitadd.(保存到暂存区)git commit-m'补白信息'(把暂存区内容保存到分支)git pull(拉取其他分支代码)git push(将更新内容提交进入远程分支)

装置webpack打包工具(装备规矩检查webpack章节)

yarn add webpack--dev/cnpm install webpack--dev在根目录下创立一个webpack.config.js文件1.需求处理的文件类型 html=>html-webpack=plugin js es6=>babel+babel-preset-react css=>css-loader+sass-loader img=>url-loader+file-loader2.常用模块 html-webpack-plugin=>html独自打包成文件 extract-text-webpack-plugin=>款式打包成独自文件 CommonsChunkPlugin=>提出通用模块3.webpack-dev-server(1)为webpack项目提供web服务(2)更改代码主动改写,路径转发(3)yarn add webpack-dev-server--dev(4)解决多版别共存

1.装备webpack,在创立好的webpack.config.js中装备

增加模块输出口

constpath=require('path')module.exports={entry:'./src/app.js',output:{path:path.resolve(__dirname,'dist'),// __dirname代表根目录filename:'你想输出的文件姓名.js'}}

增加html插件

yarn add html-webpack-plugin--dev// 生成html5文件插件在webpack.config.js中设置constpath=require('path')constHtmlWebpackPlugin=require('html-webpack-plugin')// 引进插件module.exports={entry:'./src/app.js',output:{path:path.resolve(__dirname,'dist'),filename:'你想输出的文件姓名.js'},plugins:[// 运用插件newHtmlWebpackPlugin({template:'.src/index.html'// 引证模板自定义html文件,使打包出来的html与此文件共同})]}

增加babel插件 (将es6言语转换成es5)

yarn add babel-core@6.26.0babel-preset-env@1.6.1babel-loader@7.1.2--dev// 装置在webpack.config.js装备constpath=require('path')constHtmlWebpackPlugin=require('html-webpack-plugin')module.exports={entry:'./src/app.js',output:{path:path.resolve(__dirname,'dist'),filename:'app.js'},module:{rules:[{test:/\.js$/,exclude:/(node_modules)/,// 将不需求装换的文件夹扫除use:{loader:'babel-loader',options:{presets:['env']}}}]},plugins:[newHtmlWebpackPlugin({template:'.src/index.html'// 引证自定义html文件})// 生成html5文件]}

装置react的插件

yarn add babel-preset-react --dev / cnpm install babel-preset-react --dev

yarn add html-webpack-plugin--dev// 生成html5文件插件在webpack.config.js中设置constpath=require('path')constHtmlWebpackPlugin=require('html-webpack-plugin')// 引进插件module.exports={entry:'./src/app.js',output:{path:path.resolve(__dirname,'dist'),filename:'你想输出的文件姓名.js'},plugins:[// 运用插件newHtmlWebpackPlugin({template:'.src/index.html'// 引证模板自定义html文件,使打包出来的html与此文件共同})]}

增加babel插件 (将es6言语转换成es5)

yarn add babel-core@6.26.0babel-preset-env@1.6.1babel-loader@7.1.2--dev// 装置在webpack.config.js装备constpath=require('path')constHtmlWebpackPlugin=require('html-webpack-plugin')module.exports={entry:'./src/app.js',output:{path:path.resolve(__dirname,'dist'),filename:'app.js'},module:{rules:[{test:/\.js$/,exclude:/(node_modules)/,// 将不需求装换的文件夹扫除use:{loader:'babel-loader',options:{presets:['env','react']// 只需求在这儿引证react}}}]},plugins:[newHtmlWebpackPlugin({template:'.src/index.html'// 引证自定义html文件})// 生成html5文件]}

装置款式的插件

>装置cssyarn add style-loader@0.19.1css-loader@0.28.8--dev在项目src中新建一个index.css页面,并在app.jsx中引进页面importReactfrom'react'importReactDOMfrom'react-dom'import'./index.css'装置webpack打包css成独立文件的插件yarn add extract-text-webpack-plugin@3.0.2--dev在webpack.config.js中更改对css的装备装备引进constExtractTextPlugin=require('extract-text-webpack-plugin'){test:/\.css$/,use:ExtractTextPlugin.extract({// 这儿改动fallback:'style-loader',use:'css-loader'})}由于这是一个插件,需求在plugin中装备>装置sassyarn add sass-loader--devyarn add node-sass--dev在webpack.config.js中rules css装备下增加{test:/\.scss$/,use:ExtractTextPlugin.extract({fallback:'style-loader',use:['css-loader','sass-loader']})}

对图片的处理

yarn add url-loader --sev

在webpack.config.js中装备{test: /\.(png|jpg|gif)$/,

use: [{loader: 'url-loader',

options:{limit:8192 // 文件大于8k被作为文件}}]}

对字体图标的处理

yarn add font-awesome{test: /\.(eot|svg|ttf|woff|woff2|otf)$/,

use: [{loader: 'url-loader',

options:{limit:8192 // 文件大于8k被作为文件}}]}

对公共模块的处理

在plugin中处理

constpath=require('path')constwebpack=require('webpack')//为了引证webpack自带办法constHtmlWebpackPlugin=require('html-webpack-plugin')constExtractTextPlugin=require('extract-text-webpack-plugin')module.exports={entry:'./src/app.jsx',output:{path:path.resolve(__dirname,'dist'),filename:'js/app.js'},module:{rules:[{test:/\.jsx$/,exclude:/(node_modules)/,// 将不需求装换的文件夹扫除use:{loader:'babel-loader',options:{presets:['env','react']// 主动根据环境打包}}},{test:/\.css$/,use:ExtractTextPlugin.extract({fallback:'style-loader',use:['css-loader']})},{test:/\.scss$/,use:ExtractTextPlugin.extract({fallback:'style-loader',use:['css-loader','sass-loader']})},{test:/\.(png|jpg|gif|jpeg)$/,use:[{loader:'url-loader',options:{limit:8192,// 文件大于8k被作为文件name:'resource/[name].[ext]'}}]},{test:/\.(eot|svg|ttf|woff|woff2|otf)$/,use:[{loader:'url-loader',options:{limit:8192,// 文件大于8k被作为文件name:'resource/[name].[ext]'}}]}]},plugins:[newHtmlWebpackPlugin({template:'./src/index.html'// 引证自定义html文件}),// 生成html5文件newExtractTextPlugin('css/[name].css'),// 将款式独自打包出来生成新的css页面// 提出公共模块,webpack自带newwebpack.optimize.CommonsChunkPlugin({name:'common',// 手动指定的通用木块filename:'js/base.js'})]}

webpack 主动改写处理webpack-dev-server

yarn add webpack-dev-server

在config下与plugin同级加上

devServer:{}为了防止打包后的图片在根目录下找不到

output:{path:path.resolve(__dirname,'dist'),publicPath:'/dist/',//在这儿增加路径filename:'js/app.js'},编译打包就用webpack-dev-server就可以了

运用react环境搭建项目

yarn add react react-dom 在app.js中引证react结构,并将app.js的后缀更改为jsx,webpack.config.js中的js装备也要变成jsx,进口文件的js也要更改为jsximportReactfrom'react'importReactDOMfrom'react-dom'

package.json的装备

"scripts": { "dev": "node_modules/.bin/webpack-dev-server", "dist": "node_modules/.bin/webpack -p" },

这样就可以运用yarn dev发动项目

yarn dist 打包项目

react正式开始咯(上诉办法均为自己手打搭建一个react项目,了解每一步,接下来是react提供的项目创立办法)

react => 视图层结构 组件化 JSX表达式 虚拟DOM

Facebook 开源的一个JavaScript库

React结合生态库构成一个MVC结构(vue也是mvc)

特色:Declarative(声明式编码:只需求声明在哪里做什么,无需关心如何实现);Component-Based(组件化编码);高效-高效的DOM Diff算法,最小化页面重绘

单向数据流

生态介绍

vue生态:vue + vue-router + vuex + axios + babel + webpack

react生态: react + react-router + redux + axios + babel + webpack

项意图创立(另一种方法,但是本人喜爱上面的手动装备,看得懂)

yarnadd/cnpm installglobal/-g create-react-app(大局装置)在作业区创立项目 create-react-app 你的项目称号 cd 你的项目称号 cnpm/yarn start 发动

JSX语法

增加html

letjsx=

thisisa jsx programmer
ReactDOM.render(jsx,// 将jsx组件放到烘托的dom下document.getElementById('app))
增加款式

行内款式letstyle={color:'red'}letjsx=

引进class款式在index.scss中设置body{.jsx{font-size:16px;}}letjsx=
// react中运用className引证款式称号
增加逻辑

(1)运用变量

letname="pig"letjsx=

I am a {pig}
ReactDom.render(jsx,document.getElementById('app'))
(2)条件判别

lettruth=trueletjsx=(//加括号的意图是为了换行的时候,修改器不会给我们主动填补分号

{// 条件判别需求加上{}truth?
I am a pig

:
I am not a pig

}
)
(3)jsx中刺进注释

{/*我是一个注释*/}

(4)数组的运用

letnames=['pig','dog','chicken']letjsx=({names.map((name,index)=>I am {name}

)})
增加组件

(1)基础

functionComponent(){return

I am a pig
}ReactDom.render(,// 如果是变量直接饮用,如果是组件需求加上标签document.getElementById('app'))
(2)es6组件写法

classES6ComponentextendsReact.Component{render(){return

I am a pig in es6
}}ReactDom.render(
// 两个组件共存需求包裹在一个div中


,
document.getElementById('app')

)

(3)组件初始化变量

classComponentextendsReact.Component{constructor(props){super(props);this.state={name:'pig'}}render(){return

I am a {this.state.pig}
}}
(4)更改组件初始化变量

classComponentextendsReact.Component{constructor(props){// props在子组件中只能被运用不能被改动super(props);this.state={name:'pig'}}render(){setTimeOut(()=>{this.setState({name:'Pi g Pig'})},2000)return

I am a {this.state.pig}
}}
(5)父组件传值

classComponentextendsReact.Component{constructor(props){super(props)}render(){return

I am a {this.props.name}
}}ReactDom.render(,docuement.getElementById('app'))
(6)组件增加点击事情(办法一)

classComponent extends React.Component{constructor(props){super(props);this.state={age:18}this.addAge=this.addAge.bind(this)}addAge(){this.setState({age:this.state.age+1})}render(){return(

I am{this.state.age}years old
)}}ReactDom.render(,docuement.getElementById('app'))
(7)组件增加点击事情(办法二)

classComponentextendsReact.Component{constructor(props){super(props);this.state={age:18}}addAge(){this.setState({age:this.state.age+1})}render(){return(


I am {this.state.age} years old
{this.addAge(e)}}>

}

}

ReactDom.render(

,

docuement.getElementById('app')

)

(8)组件增加输入框更改事情

classComponentextendsReact.Component{constructor(props){super(props);this.state={age:18}}changeValue(e){this.setState({age:e.target.value})}render(){return(


I am {this.state.age} years old
{this.changeValue(e)}}/>
)}}ReactDom.render(,docuement.getElementById('app'))
(9)容器性组件嵌套组件

classComponent extends React.Component{constructor(props){super(props);this.state={age:18}}changeValue(e){this.setState({age:e.target.value})}render(){return(

I am{this.state.age}years old
{this.changeValue(e)}}/>
)}}classTitle extends React.Component{constuctor(props){super(props)}render(props){return
{this.props.title}
}}classApp extends React.Component{render(){return(
// 在这儿引证小组件component
)}}ReactDom.render(,// 这儿换成Appdocuement.getElementById('app'))
(10)组件嵌套组件

classComponentextendsReact.Component{constructor(props){super(props);this.state={age:18}}changeValue(e){this.setState({age:e.target.value})}render(){return(


I am {this.state.age} years old
{this.changeValue(e)}}/>
)}}classAppextendsReact.Component{render(){return(

app
// 在这儿引证小组件component


)}}ReactDom.render(,// 这儿换成Appdocuement.getElementById('app'))
(11)容器性组件嵌套组件,传值可以为任何html方法

classComponent extends React.Component{constructor(props){super(props);this.state={age:18}}changeValue(e){this.setState({age:e.target.value})}render(){return(

I am{this.state.age}years old
{this.changeValue(e)}}/>
)}}classTitle extends React.Component{constuctor(props){super(props)}render(props){return
{this.props.children}
// 这儿变成获取子children}}classApp extends React.Component{render(){return(
我是spanspanlink//更改为html方法
)}}ReactDom.render(,// 这儿换成Appdocuement.getElementById('app'))
(12)子组件给父组件传值

classFather extends React.Component{constructor(props){super(props);this.state={bgColor:'red'}}changeMyBgColors(color){this.setState({bgColor:color})}render(){return(

我是爸爸
{this.changeMyBgColors(color)}}/>
)}}classChild extends React.Component{constructor(props){super(props)}changeMyBgColor(){this.props.changeColor('blue')}render(){return(
我是baby
{this.changeMyBgColor(e)}}>我想改动我爸爸的背景颜色
)}}ReactDOM.render(,document.getElementById('app'))
(13)兄弟之间的组件通讯(子1传父,父在传子2)

classChild1extendsReact.Component{constructor(props){super(props)this.state={color1:'red'}}changeMyBrotherColor(props){this.props.change2Color(this.state.color1)}render(){return(


我是孩子1
{this.changeMyBrotherColor(e)}}>我要改动我弟弟的颜色咯
)}}classChild2extendsReact.Component{constructor(props){super(props)}render(){return(
我是孩子2
)}}classFatherextendsReact.Component{constructor(props){super(props)this.state={color2:'yellow'}}changColor(colorsss){this.setState({color2:colorsss})}render(){return(

这是我的孩子们
{this.changColor(color)}}/>
)}}ReactDOM.render(,document.getElementById('app'))
react生命周期

getDefaultProps // 初始化props特点,props来自其他组件

getInitialState // 初始化组件的状况

componentWillMount // 组件加载之前

render // 烘托

componentDidMount // 组件dom刺进之后

componentWillReceiveProps // 承受父组件的传递

shouldComponentUpdate // 组件的更新处罚

componentWillUpdate // 组件要更新前

componentDidUpdate // 组件更新后

componentWillUnmount // 组件的销毁

Mounting : 挂载阶段

Updating: 运行时阶段

Unmounting: 卸载阶段

Error Handling: 错误处理

importReactfrom'react'importReactDOMfrom'react-dom'import'./index.scss'classChildextendsReact.Component{// 结构函数constructor(props){super(props)this.state={data:'oldzhuzhu'}console.log('这儿是初始化数据constructor')}componentWillMount(){// 组件烘托前console.log('componentWillMount')}componentDidMount(){// 组件烘托完毕console.log('componentDidMount')}componentWillReceiveProps(){// 即将承受父组件传来的props触发console.log('componentWillReceiveProps')}shouldComponentUpdate(){// 子组件是不是应该更新console.log('shouldComponentUpdate')returntrue// 如果是false,后面的update就不会跟着更新}componentWillUpdate(){// 组件即将更新console.log('componentWillUpdate')}componentDidUpdate(){// 组件更新完结console.log('componentDidUpdate')}componentWillUnmount(){// 组件即将销毁调用console.log('componentWillUnmount')}// 点击事情handleClick(){console.log('这儿是更新数组')this.setState({data:'zhuzhuzhu'})}// 烘托render(){console.log('render')return(

{this.state.data} 接收到的props: {this.props.data} {this.handleClick()}}>更新组件
)}}classFatherextendsReact.Component{constructor(props){super(props)this.state={data:'old props'}}changeData(){this.setState({data:'new props',show:true})}byeChild(){this.setState({show:false})}render(){return(
{this.state.show?:null} {this.changeData()}}>改动子组件的props {this.byeChild()}}>
)}}ReactDOM.render(,document.getElementById('app'))
按次序输出值:

constructor// 结构函数初始化componentWillMount// 组件烘托前render// 组价烘托componentDidMount// 选件烘托完结componentWillReceiveProps// 子组件接收到父组件传来的propsshouldComponentUpdate// 是否组件进行更新,true更新,false接下来的周期不触发componentWillUpdate// 组件更新前render// 更新componentDidUpdate// 组件更新完毕componentWillUnmount// 组件被摧毁之前

react-router

1.router几种方法

页面路由

window.location.href='地址'// www.baidu.comhistory.back()//回退

hash 路由

window.location='#hash'window.onhashchange=function(){console.log('current hash'+window.location.hash)}

h5路由

history.pushState('name','title','/path')// 推进一个状况history.replaceState('name','title','/path')// 替换一个状况window.onpopstate=function(){console.log(window.location.href)console.log(window.location.pathname)console.log(window.location.hash)console.log(window.location.search)}

2. react-router几种方法

hash

importReactfrom'react'importReactDOMfrom'react-dom'import{HashRouterasRouter,Route,Link}from'react-router-dom'// 这儿是Hashimport'./index.scss'classAextendsReact.Component{constructor(props){super(props)}render(){return(

Component A
)}}classBextendsReact.Component{constructor(props){super(props)}render(){return(
Component B
)}}classWrapperextendsReact.Component{constructor(props){super(props)}render(){return(
组件A
组件B {this.props.children}
)}}ReactDOM.render( ,document.getElementById('app'))

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接