React 从青铜到王者系列教程之倔强青铜篇

前端大陆乃是技术界近年来新兴起的板块,随着人们对网站交互和性能愈来愈高, 前往前端大陆修炼 Javascript 的召唤师如过江之鲫,数不胜数,前端奇人异士之多,故修炼之法林林总总,俱不相同, Web 前端的将来尚无定论,内部却已起了门户之见, 幸而前端圈核心门派正道大昌,人气鼎盛,其中尤以 React、Vue、Angular 为三大支柱,是为领袖,今天的故事,即是从 React 峡谷开始的css

React 峡谷的每一个前端召唤师,根据对 React 技术栈 和前端的理解,分别是青铜,白银,黄金,铂金,钻石,星耀和王者段位,也对应这这个系列教程的七个模块html

  1. 倔强青铜
    • 初入峡谷的初始段位,默认召唤师已经有了ES6nodejs 的基础
    • 使用 create-react-app 创建 React 开发环境
    • 学习 React 世界里的基本玩法,例如组件化,JSX,事件监听,内部 state,组件的props、生命周期函数等
    • 这篇文章主要介绍 React 青铜升白银须要的基础知识,看完你就白银啦
  2. 秩序白银
    • 到了白银段位,基本都是有了基本的操做,不会出现呆萌的站在地方塔下被打死的状况了
    • 咱们须要买一个皮肤来提高页面美观而且多加练习
    • 学习使用蚂蚁金服 ant-design 的使用
  3. 荣耀黄金前端

    • 到了这个阶段,召唤师对 React 有了基本的认识,想进一步的提高段位,咱们须要提升本身的大局观
    • 学习使用 React-Router4 来让咱们有多面做战能力
    • 学会使用 BrowserRouterRouterLink 等组件
    • 学会使用 Redux 和队友配合,修炼大局观
    • 了解单项数据流开发模式和 Redux 的各类概念,如 dispatch,action,reducers
    • 使用 react-redux 更好的和 Redux 配合有大局观意识,上铂金也是很 easy 了
  4. 尊贵铂金node

    • 不少召唤师卡在铂金上不去,由于铂金想上钻石,须要了解更多的细节和原理
    • React 原理剖析
    • 对本身技能的原理有深入的了解,上钻石必备
  5. 永恒钻石react

    • 钻石段位开始了征兆模式,召唤师的技能池要足够深才能更进一步,对本身擅长技能的理解也要更深入
    • Redux 中间件机制,实现本身的中间件
    • 常见的React 性能优化方式
    • 服务端渲染
    • Redux 以外其余的数据解决方案如 mobxdva
  6. 至尊星耀程序员

    • 这个段位已是独当一面的强者了,目标仅限于 React 这个库很难更近一层,须要了解更底层的原理
    • Redux 原理剖析+实现本身的 Redux
    • React-Router+实现本身的 React-Router
    • Webppack 工做机制和原理剖析
    • Babel 工做机制和原理剖析
  7. 最强王者
    • 达到最强王者已是顶尖召唤师,在整个 React 峡谷都是鼎鼎大名的存在,据说上面还有传说中的荣耀王者的段位,我这辈子是达不到了,也无法教大家了,囧
    • 这个阶段,我只推荐《程序员健康指南》一本书,保持身心健康,成为荣耀王者是迟早的事

开始以前,作个小广告,欢迎你们关注我在慕课网的React实战课程Redux+React Router+Node.js全栈开发npm

下面开始咱们的正文,倔强青铜篇目录redux

  1. 环境搭建
  2. 第一个组件
  3. 组件嵌套和属性传递
  4. 状态处理
  5. 生命周期

环境搭建

默认你们已经有 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是入口文件,核心内容就是分别引入 ReactReactDom,而后渲染了一个组件 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 组件了,本身实现组件也是分这么几个步骤

  1. import React
  2. 新建一个类,继承 React.ComponentReact 里每一个组件均可以写成一个类
  3. 类的 render 函数返回值,就是显示在页面的内容
  4. render 里返回的是东西有点诡异,表面上是html 其实 Babel 会把 JSX 转成 React.createElememt来执行
  5. 因为 JSX 本质就是 js,class 是 js 的关键字,因此要用 className 代替
  6. 若是想在 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 里也能够在{}内部使用三元表达式,你们能够修改 isKingfalse 试一试

而后就是渲染列表,咱们使用 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

React 状态管理和事件监听

咱们经过在构造函数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,咱们称之为构造函数,组件初始化状态放在这里,设置了 isKingtrue,而后button 元素上的 onClick 的时候,执行handleClick,在handleClick内部,调用 this.setState 来修改 isKing

constructor函数里的 bind 是强行把handleClickthis 绑定在组件上,不然 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 更新完毕了复制代码

除了上面介绍的,还有须要注意的

  1. React16新增的componentDidCatch生命周期,用来处理报错
  2. shouldComponentUpdate返回 false,那么组件就不会渲染
  3. 若是是子组件,还有个componentWillReceiveProps
  4. 组件卸载有componentWillUnmount,用来作资源的清理
  5. 合理利用生命周期,在不一样的阶段作不一样的事情
    若是你能看到这里,那真的对 React 是真爱,恭喜你,你已是秩序白银啦,领取徽章

欢迎你们关注我在慕课网的实战课程Redux+React Router+Node.js全栈开发

下期预告:秩序白银篇-- 使用 ant-design UI库,有问题留言,咱们还能够开黑,一块儿上王者

相关文章
相关标签/搜索