前端大陆乃是技术界近年来新兴起的板块,随着人们对网站交互和性能愈来愈高, 前往前端大陆修炼 Javascript 的召唤师如过江之鲫,数不胜数,前端奇人异士之多,故修炼之法林林总总,俱不相同, Web 前端的将来尚无定论,内部却已起了门户之见, 幸而前端圈核心门派正道大昌,人气鼎盛,其中尤以 React、Vue、Angular 为三大支柱,是为领袖,今天的故事,即是从 React 峡谷开始的css
React 峡谷的每一个前端召唤师,根据对 React 技术栈 和前端的理解,分别是青铜,白银,黄金,铂金,钻石,星耀和王者段位,也对应这这个系列教程的七个模块html
ES6
,nodejs
的基础create-react-app
创建 React
开发环境React
世界里的基本玩法,例如组件化,JSX
,事件监听,内部 state
,组件的props
、生命周期函数等React
青铜升白银须要的基础知识,看完你就白银啦ant-design
的使用荣耀黄金前端
React
有了基本的认识,想进一步的提高段位,咱们须要提升本身的大局观React-Router4
来让咱们有多面做战能力BrowserRouter
,Router
,Link
等组件Redux
和队友配合,修炼大局观Redux
的各类概念,如 dispatch
,action
,reducers
react-redux
更好的和 Redux
配合有大局观意识,上铂金也是很 easy 了尊贵铂金node
React
原理剖析永恒钻石react
Redux
中间件机制,实现本身的中间件Redux
以外其余的数据解决方案如 mobx
,dva
至尊星耀程序员
Redux
原理剖析+实现本身的 Redux
React-Router
+实现本身的 React-Router
Webppack
工做机制和原理剖析Babel
工做机制和原理剖析开始以前,作个小广告,欢迎你们关注我在慕课网的React实战课程Redux+React Router+Node.js全栈开发npm
下面开始咱们的正文,倔强青铜篇目录redux
默认你们已经有 node 环境了,先安装脚手架数组
npm install create-react-app -g复制代码
而后创建项目,并启动性能优化
create-react-app bronze
cd bronze
npm start复制代码
看到下面的图,意味着第一个 React
应用已经启动起来了
咱们打开 src 目录
src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
└── registerServiceWorker.js复制代码
index.js
是入口文件,核心内容就是分别引入 React
和 ReactDom
,而后渲染了一个组件 App
在#root
这个元素上
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />,document.getElementById('root'));复制代码
而后重点看下 App.js
是咱们组件的具体内容
import React, { Component } from 'react'
class App extends Component {
render() {
return (
<div className="App"> <p> To get started, edit <code>src/App.js</code> and save to reload. </p> </div>
);
}
}
export default App;复制代码
这个基本上是最简单的 React
组件了,本身实现组件也是分这么几个步骤
import React
React.Component
,React
里每一个组件均可以写成一个类render
函数返回值,就是显示在页面的内容render
里返回的是东西有点诡异,表面上是html
其实 Babel
会把 JSX
转成 React.createElememt
来执行JSX
本质就是 js,class
是 js 的关键字,因此要用 className
代替JSX
里渲染变量,使用{}
包裹便可如今Babel官网],看下 JSX
编译后的代码,再划下重点,所谓的 JSX
,其实就是js 对象,再用 ReactDom.render
方法,渲染成dom
// jsx
<div className="App">
<p>hello react</p>
</div>
// 转换后
React.createElement(
"div",
{ className: "App" },
React.createElement(
"p",
null,
"hello react"
)
)复制代码
咱们实现本身的第一个组件,修改 App.js
为
import React, { Component } from 'react'
class App extends Component {
render() {
const level='最强王者'
return (
<div> <h2>咱们的目标是{level}</h2> </div>
)
}
}
export default App复制代码
因为JSX
本质上其实就是 js,因此咱们能够在{}
里面使用 js 的表达式等功能,好比三元、函数、变量等等,还能够把数组映射为列表,咱们把代码修改成
import React, { Component } from 'react'
class App extends Component {
render() {
const level='最强王者'
const isKing = true
const title = isKing
? <p>早睡早起,理性游戏</p>
: <h2>咱们的目标是{level}</h2>
const wordList = ['俺老孙来也','有妖气','取经之路,就在脚下']
return (
<div> {title} {isKing ? <p>我就是王者</p>: null} <ul> {wordList.map(v=><li key={v}>{v}</li>)} </ul> </div>
)
}
}
export default App复制代码
这里要稍微注意一点,就是 render
里,若是 return
多个元素,必须有一个父元素包裹,不然会有个报错
咱们在return 以外把 JSX
复制给变量,JSX
里也能够在{}
内部使用三元表达式,你们能够修改 isKing
是 false
试一试
而后就是渲染列表,咱们使用 map
函数直接映射为 JSX
的数组,记得列表里每一个元素都有一个 key
属性,关于它的做用,咱们讲虚拟dom 的时候会介绍
若是咱们继续设计咱们的应用,如今再设计一个Tank
组件,能够直接放在 App
里使用,而且能够传递一个属性,在组件内部,使用 this.props.key
获取
import React, { Component } from 'react'
class App extends Component {
render() {
const level='最强王者'
const isKing = true
const title = isKing
? <p>早睡早起,理性游戏</p>
: <h2>咱们的目标是{level}</h2>
return (
<div> {title} {isKing ? <p>我就是王者</p>: null} <Tank name='程咬金'></Tank> </div>
)
}
}
class Tank extends Component {
render() {
return (
<div> <h3>{this.props.name}是一个坦克</h3> </div>
)
}
}
export default App复制代码
若是咱们的组件只有一个 render
方法,还能够写成一个函数,props 是函数的参数,咱们称呼这种组件为无状态组件,这种组件的特色,就是返回只和 props 有关,复用性高
function Tank(props){
return (
<div> <h3>{props.name}是一个坦克</h3> </div>
)
}复制代码
这样咱们就能够把应用分红多个组件,而后用拼积木的形式拼接应用,可是如今的组件都无法变化,下一步,咱们学习 React 的状态管理,也就是 state
咱们经过在构造函数constructor里初始 state,其实就是一个普通的 js 对象,而后能够调用 this.setState函数修改 state,每次 setState,都会从新渲染组件
组件里可使用 onClick来绑定一个函数,能够监听用户的事件,话很少说看代码
class App extends Component {
constructor(props){
super(props)
this.state = {
isKing:true
}
this.handleClick = this.handleClick.bind(this)
}
handleClick(){
this.setState({
isKing: !this.state.isKing
})
}
render() {
const level='最强王者'
const title = this.state.isKing
? <p>早睡早起,理性游戏</p>
: <h2>咱们的目标是{level}</h2>
return (
<div> <button onClick={this.handleClick}>点我</button> {title} {this.state.isKing ? <p>我就是王者</p>: null} <Tank name='程咬金'></Tank> </div>
)
}
}复制代码
咱们须要关注的点,一个是constructor
,咱们称之为构造函数,组件初始化状态放在这里,设置了 isKing
是 true
,而后button
元素上的 onClick
的时候,执行handleClick
,在handleClick
内部,调用 this.setState
来修改 isKing
constructor
函数里的 bind
是强行把handleClick
的 this
绑定在组件上,不然 onClick
的时候会获取 this
引用出错,解决这个问题还有其余的形式,能够不用写 bind
这一行
import React, { Component } from 'react'
class App extends Component {
constructor(props){
super(props)
this.state = {
isKing:true
}
this.handleClick = this.handleClick.bind(this)
}
// 在constructor里手动 bind
handleClick(){
this.setState({
isKing: !this.state.isKing
})
}
// 绑定的时候传递箭头函数
handleClick1(){
this.handleClick()
}
// 定义的时候是剪头函数
handleClick2 = ()=>{
this.handleClick()
}
// onClick 的时候直接绑定
handleClick3(){
this.handleClick()
}
render() {
const level='最强王者'
const title = this.state.isKing
? <p>早睡早起,理性游戏</p>
: <h2>咱们的目标是{level}</h2>
return (
<div> <button onClick={this.handleClick}>点我</button> <button onClick={()=>this.handleClick1()}>点我1</button> <button onClick={this.handleClick2}>点我2</button> <button onClick={this.handleClick3.bind(this)}>点我3</button> {title} {this.state.isKing ? <p>我就是王者</p>: null} <Tank name='程咬金'></Tank> </div>
)
}
}复制代码
最后要介绍的,就是 React
组件的生命周期,每一个组件在不一样的时期,会有不一样的钩子函数执行,好比组件加载完毕后,会执行 componentDidMount
钩子函数
class App extends Component{
componentDidMount(){
console.log('组件渲染完毕')
}
render(){
console.log('组件正在渲染')
return <h2>倔强青铜</h2>
}
}
// 组件正在渲染
// 组件渲染完毕复制代码
React
在不一样的阶段,会执行不一样的函数,我从网上找了个图,很清晰的说明各个生命周期函数执行的时机,
class App extends Component {
constructor(props){
super(props)
this.state = {
isKing:true
}
this.handleClick = this.handleClick.bind(this)
console.log('constructor App 的构造函数,初始化先执行')
}
handleClick(){
this.setState({
isKing: !this.state.isKing
})
}
componentWillMount(){
console.log('componentWillMount,组件 App 准备渲染')
}
componentDidMount(){
console.log('componentDidMount,组件 App 渲染完毕')
}
shouldComponentUpdate(){
console.log('shouldComponentUpdate,判断 App 组件是否应该渲染, 默认返回 true')
return true
}
componentWillUpdate(){
console.log('componentWillUpdate,组件 App 准备更新了')
}
componentDidUpdate(){
console.log('componentDidUpdate, 组件 App 更新完毕了')
}
render() {
const level='最强王者'
const title = this.state.isKing
? <p>早睡早起,理性游戏</p>
: <h2>咱们的目标是{level}</h2>
const wordList = ['俺老孙来也','有妖气','取经之路,就在脚下']
console.log('组件 App 正在渲染')
return (
<div> <button onClick={this.handleClick}>点我</button> {title} {this.state.isKing ? <p>我就是王者</p>: null} <ul> {wordList.map(v=><li key={v}>{v}</li>)} </ul> <Tank name='程咬金'></Tank> </div>
)
}
}
// 首次加载打印
constructor App 的构造函数,初始化先执行
componentWillMount,组件 App 准备渲染
组件 App 正在渲染
componentDidMount,组件 App 渲染完毕
// 点击按钮修改状态时打印
shouldComponentUpdate,判断 App 组件是否应该渲染, 默认返回 true
componentWillUpdate,组件 App 准备更新了
组件 App 正在渲染
componentDidUpdate, 组件 App 更新完毕了复制代码
除了上面介绍的,还有须要注意的
React16
新增的componentDidCatch
生命周期,用来处理报错shouldComponentUpdate
返回 false
,那么组件就不会渲染componentWillReceiveProps
componentWillUnmount
,用来作资源的清理React
是真爱,恭喜你,你已是秩序白银啦,领取徽章欢迎你们关注我在慕课网的实战课程Redux+React Router+Node.js全栈开发
下期预告:秩序白银篇-- 使用 ant-design UI库,有问题留言,咱们还能够开黑,一块儿上王者