• React 全栈体系(五)


    第三章:React 应用(基于 React 脚手架)

    一、使用 create-react-app 创建 react 应用

    1. react 脚手架

    • xxx 脚手架: 用来帮助程序员快速创建一个基于 xxx 库的模板项目
      • 包含了所有需要的配置(语法检查、jsx 编译、devServer…)
      • 下载好了所有相关的依赖
      • 可以直接运行一个简单效果
    • react 提供了一个用于创建 react 项目的脚手架库: create-react-app
    • 项目的整体技术架构为: react + webpack + es6 + eslint
    • 使用脚手架开发的项目的特点: 模块化,组件化,工程化

    2. 创建项目并启动

    • 第一步,全局安装:npm i -g create-react-app
    • 第二步,切换到想创项目的目录,使用命令:create-react-app hello-react
    • 第三步,进入项目文件夹:cd hello-react
    • 第四步,启动项目:npm start
    # 新版安装方法!
    
    npx create-react-app myapp
    cd my-app
    npm start
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3. react 脚手架项目结构

    public ---- 静态资源文件夹
    		favicon.icon ------ 网站页签图标
    		index.html -------- 主页面
    		logo192.png ------- logo图
    		logo512.png ------- logo图
    		manifest.json ----- 应用加壳的配置文件
    		robots.txt -------- 爬虫协议文件
    src ---- 源码文件夹
    		App.css -------- App组件的样式
    		App.js --------- App组件
    		App.test.js ---- 用于给App做测试
    		index.css ------ 样式
    		index.js ------- 入口文件
    		logo.svg ------- logo图
    		reportWebVitals.js
    			--- 页面性能分析文件(需要web-vitals库的支持)
    		setupTests.js
    			---- 组件单元测试的文件(需要jest-dom库的支持)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    请添加图片描述

    4. 功能界面的组件化编码流程(通用)

    • 拆分组件:拆分界面,抽取组件
    • 实现静态组件:使用组件实现静态页面效果(class -> className, style…)
    • 实现动态组件
      • 动态显示初始化数据
        • 数据类型
        • 数据名称
        • 保存在哪个组件?
      • 交互(从绑定事件监听开始)

    5. 代码

    请添加图片描述
    请添加图片描述

    /* src/index.js */
    //引入react核心库
    import React from 'react'
    //引入ReactDOM
    import ReactDOM from 'react-dom'
    //引入App组件
    import App from './App'
    
    //渲染App到页面
    ReactDOM.render(<App/>,document.getElementById('root'))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    /* src/App.jsx */
    //创建“外壳”组件App
    import React,{Component} from 'react'
    import Hello from './components/Hello'
    import Welcome from './components/Welcome'
    
    //创建并暴露App组件
    export default class App extends Component{
    	render(){
    		return (
    			<div>
    				<Hello/>
    				<Welcome/>
    			</div>
    		)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    /* src/components/Hello/index.jsx */
    import React,{Component} from 'react'
    import hello from './index.module.css'
    
    export default class Hello extends Component{
    	render(){
    		return <h2 className={hello.title}>Hello,React!</h2>
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    /* src/components/Hello/index.module.css */
    .title{
    	background-color: orange;
    }
    
    • 1
    • 2
    • 3
    • 4
    /* src/components/Welcome/index.jsx */
    import React,{Component} from 'react'
    import './index.css'
    
    export default class Welcome extends Component{
    	render(){
    		return <h2 className="title">Welcome</h2>
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    /* src/components/Welcome/index.css */
    .title{
    	background-color: skyblue;
    }
    
    • 1
    • 2
    • 3
    • 4

    二、组件的组合使用 - TodoList

    • 功能:组件化实现此功能
      • 显示所有 todo 列表
      • 输入文本, 点击按钮显示到列表的首位, 并清除输入的文本

    请添加图片描述

    请添加图片描述

    • 静态页面源码
    
    doctype html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <title>React Apptitle>
    
      <link rel="stylesheet" href="index.css">
    head>
    <body>
    <div id="root">
      <div class="todo-container">
        <div class="todo-wrap">
          <div class="todo-header">
            <input type="text" placeholder="请输入你的任务名称,按回车键确认"/>
          div>
          <ul class="todo-main">
            <li>
              <label>
                <input type="checkbox"/>
                <span>xxxxxspan>
              label>
              <button class="btn btn-danger" style="display:none">删除button>
            li>
            <li>
              <label>
                <input type="checkbox"/>
                <span>yyyyspan>
              label>
              <button class="btn btn-danger" style="display:none">删除button>
            li>
          ul>
          <div class="todo-footer">
            <label>
              <input type="checkbox"/>
            label>
            <span>
              <span>已完成0span> / 全部2
            span>
            <button class="btn btn-danger">清除已完成任务button>
          div>
        div>
      div>
    div>
    
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    /* index.css */
    /*base*/
    body {
      background: #fff;
    }
    
    .btn {
      display: inline-block;
      padding: 4px 12px;
      margin-bottom: 0;
      font-size: 14px;
      line-height: 20px;
      text-align: center;
      vertical-align: middle;
      cursor: pointer;
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
      border-radius: 4px;
    }
    
    .btn-danger {
      color: #fff;
      background-color: #da4f49;
      border: 1px solid #bd362f;
    }
    
    .btn-danger:hover {
      color: #fff;
      background-color: #bd362f;
    }
    
    .btn:focus {
      outline: none;
    }
    
    .todo-container {
      width: 600px;
      margin: 0 auto;
    }
    .todo-container .todo-wrap {
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 5px;
    }
    
    /*header*/
    .todo-header input {
      width: 560px;
      height: 28px;
      font-size: 14px;
      border: 1px solid #ccc;
      border-radius: 4px;
      padding: 4px 7px;
    }
    
    .todo-header input:focus {
      outline: none;
      border-color: rgba(82, 168, 236, 0.8);
      box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
    }
    
    /*main*/
    .todo-main {
      margin-left: 0px;
      border: 1px solid #ddd;
      border-radius: 2px;
      padding: 0px;
    }
    
    .todo-empty {
      height: 40px;
      line-height: 40px;
      border: 1px solid #ddd;
      border-radius: 2px;
      padding-left: 5px;
      margin-top: 10px;
    }
    /*item*/
    li {
      list-style: none;
      height: 36px;
      line-height: 36px;
      padding: 0 5px;
      border-bottom: 1px solid #ddd;
    }
    
    li label {
      float: left;
      cursor: pointer;
    }
    
    li label li input {
      vertical-align: middle;
      margin-right: 6px;
      position: relative;
      top: -1px;
    }
    
    li button {
      float: right;
      display: none;
      margin-top: 3px;
    }
    
    li:before {
      content: initial;
    }
    
    li:last-child {
      border-bottom: none;
    }
    
    /*footer*/
    .todo-footer {
      height: 40px;
      line-height: 40px;
      padding-left: 6px;
      margin-top: 5px;
    }
    
    .todo-footer label {
      display: inline-block;
      margin-right: 20px;
      cursor: pointer;
    }
    
    .todo-footer label input {
      position: relative;
      top: -1px;
      vertical-align: middle;
      margin-right: 5px;
    }
    
    .todo-footer button {
      float: right;
      margin-top: 5px;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136

    1. 静态组件

    1.1 index.js
    /* src/index.js */
    //引入react核心库
    import React from 'react'
    //引入ReactDOM
    import ReactDOM from 'react-dom'
    //引入App组件
    import App from './App'
    
    //渲染App到页面
    ReactDOM.render(<App/>,document.getElementById('root'))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1.2 App
    /* src/App.jsx */
    //创建“外壳”组件App
    import React,{Component} from 'react'
    import Header from './components/Header'
    import List from './components/List'
    import Footer from './components/Footer'
    import './App.css'
    
    //创建并暴露App组件
    export default class App extends Component{
    	render(){
    		return (
    			<div className="todo-container">
    				<div className="todo-wrap">
    					<Header/>
    					<List />
    					<Footer />
    				</div>
    			</div>
    		)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    /* src/App.css */
    /*base*/
    body {
        background: #fff;
      }
    
      .btn {
        display: inline-block;
        padding: 4px 12px;
        margin-bottom: 0;
        font-size: 14px;
        line-height: 20px;
        text-align: center;
        vertical-align: middle;
        cursor: pointer;
        box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
        border-radius: 4px;
      }
    
      .btn-danger {
        color: #fff;
        background-color: #da4f49;
        border: 1px solid #bd362f;
      }
    
      .btn-danger:hover {
        color: #fff;
        background-color: #bd362f;
      }
    
      .btn:focus {
        outline: none;
      }
    
      .todo-container {
        width: 600px;
        margin: 0 auto;
      }
      .todo-container .todo-wrap {
        padding: 10px;
        border: 1px solid #ddd;
        border-radius: 5px;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    1.3 Header
    /* src/components/Header/index.jsx */
    import React, { Component } from 'react'
    import './index.css'
    
    export default class Header extends Component {
      render() {
        return (
            <div className="todo-header">
                <input type="text" placeholder="请输入你的任务名称,按回车键确认"/>
            </div>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    /* src/components/Header/index.css */
    .todo-header input {
        width: 560px;
        height: 28px;
        font-size: 14px;
        border: 1px solid #ccc;
        border-radius: 4px;
        padding: 4px 7px;
      }
    
      .todo-header input:focus {
        outline: none;
        border-color: rgba(82, 168, 236, 0.8);
        box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    1.4 List
    /* src/components/List/index.jsx */
    import React, { Component } from 'react'
    import Item from '../Item'
    import './index.css'
    
    export default class List extends Component {
      render() {
        return (
            <ul className="todo-main">
              <Item />
              <Item />
              <Item />
              <Item />
              <Item />
            </ul>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    /* src/components/List/index.css */
    .todo-main {
        margin-left: 0px;
        border: 1px solid #ddd;
        border-radius: 2px;
        padding: 0px;
      }
    
      .todo-empty {
        height: 40px;
        line-height: 40px;
        border: 1px solid #ddd;
        border-radius: 2px;
        padding-left: 5px;
        margin-top: 10px;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    1.5 Item
    /* src/components/Item/index.jsx */
    import React, { Component } from 'react'
    import './index.css'
    
    export default class Item extends Component {
      render() {
        return (
            <li>
            <label>
                <input type="checkbox"/>
                <span>xxxxx</span>
            </label>
            <button className="btn btn-danger" style={{display: "none"}}>删除</button>
            </li>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    /* src/components/Item/index.css */
    li {
        list-style: none;
        height: 36px;
        line-height: 36px;
        padding: 0 5px;
        border-bottom: 1px solid #ddd;
      }
    
      li label {
        float: left;
        cursor: pointer;
      }
    
      li label li input {
        vertical-align: middle;
        margin-right: 6px;
        position: relative;
        top: -1px;
      }
    
      li button {
        float: right;
        display: none;
        margin-top: 3px;
      }
    
      li:before {
        content: initial;
      }
    
      li:last-child {
        border-bottom: none;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    1.6 Footer
    /* src/components/Footer/index.jsx */
    import React, { Component } from 'react'
    import './index.css'
    
    export default class Footer extends Component {
      render() {
        return (
            <div className="todo-footer">
            <label>
            <input type="checkbox"/>
            </label>
            <span>
            <span>已完成0</span> / 全部2
            </span>
            <button className="btn btn-danger">清除已完成任务</button>
        </div>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    /* src/components/Footer/index.css */
    .todo-footer {
        height: 40px;
        line-height: 40px;
        padding-left: 6px;
        margin-top: 5px;
      }
    
      .todo-footer label {
        display: inline-block;
        margin-right: 20px;
        cursor: pointer;
      }
    
      .todo-footer label input {
        position: relative;
        top: -1px;
        vertical-align: middle;
        margin-right: 5px;
      }
    
      .todo-footer button {
        float: right;
        margin-top: 5px;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    2. 动态初始化列表

    2.1 App
    /* src/App.jsx */
    //创建“外壳”组件App
    import React,{Component} from 'react'
    import Header from './components/Header'
    import List from './components/List'
    import Footer from './components/Footer'
    import './App.css'
    
    //创建并暴露App组件
    export default class App extends Component{
    
    	//初始化状态
    	state = {todos:[
    		{id:'001',name:'吃饭',done:true},
    		{id:'002',name:'睡觉',done:true},
    		{id:'003',name:'打代码',done:false},
    		{id:'004',name:'逛街',done:false}
    	]}
    
    	render(){
    		const {todos} = this.state
    		return (
    			<div className="todo-container">
    				<div className="todo-wrap">
    					<Header/>
    					<List todos={todos}/>
    					<Footer />
    				</div>
    			</div>
    		)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    2.2 List
    /* src/components/List/index.jsx */
    import React, { Component } from 'react'
    import Item from '../Item'
    import './index.css'
    
    export default class List extends Component {
      render() {
        const {todos} = this.props
        return (
            <ul className="todo-main">
              {
                todos.map(todo=> {
                  return <Item key={todo.id} {...todo}/>
                })
              }
            </ul>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    2.3 Item
    /* src/components/Item/index.jsx */
    import React, { Component } from 'react'
    import './index.css'
    
    export default class Item extends Component {
      render() {
        const {name,done} = this.props
        return (
            <li>
    	        <label>
    	            <input type="checkbox" defaultChecked={done}/>
    	            <span>{name}</span>
    	        </label>
    	        <button className="btn btn-danger" style={{display: "none"}}>删除</button>
            </li>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    【Python】os模块路径处理
    10.springboot拦截器实例
    大数据组件-Flink环境搭建
    作为测试工程师的发展之路-如何做好测试开开发?
    95- 后程序员一出校门就拿年薪 -30 多万?,android 开发文档百度云
    anaconda ( jupyter notebook ) 虚拟环境安装 lazypredict
    号外号外!首届开源 AI 游戏挑战赛圆满结束!
    C: . 与 -> 的区别
    web 前端面试题
    el-select组件绑定change怎么获取label和value值
  • 原文地址:https://blog.csdn.net/sgsgkxkx/article/details/132818621