React 应用

React 应用

尚硅谷 2021 版 React 技术全家桶全套完整版(零基础入门到精通/男神天禹老师亲授)

React 脚手架

  1. xxx脚手架:用来帮助程序员快速创建一个基于 xxx 库的模板项目
  2. React 提供了一个用于创建 React 项目的脚手架库:create-react-app
  3. 项目整体技术架构为:react + webpack + es6 + eslint
  4. 使用脚手架开发的项目特点:模板化、组件化、工程化

安装

  1. 全局安装:npm i -g create-react-app
  2. 切换到想创建项目的目录,create-react-app hello-react
  3. 进入项目文件夹:cd hello-react
  4. 启动项目:npm start
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<!-- 开启理想视口,用于做移动端网页的适配 -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- 用于配置浏览器页签+地址栏的颜色(仅支持安卓手机浏览器) -->
<meta name="theme-color" content="#000000" />
<!-- 用于指定网页添加到手机主屏幕后的图标 -->
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo.png" />
<!-- 应用加壳的配置文件(手机分辨率多少用什么图片) -->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!-- 如浏览器不支持JS则展示标签中的内容 -->
<noscript>You need to enable JavaScript to run this app.</noscript>
  • %PUBLIC_URL% 代表 public 文件夹的路径
  • reportWebVitals 记录页面性能,其使用 web-vitals
  • setupTests 组件单元测试,其使用 @testing-library/jest-dom

安装插件 ES7 React/Redux/GraphQL/React-Native snippets

样式模块化

  1. 使用预编译语言比如:Less、Scss

  2. 把 css 名改为 index.module.css

    import xx from './index.module.css' <h2 className={xx.xx}>

组件化编码流程

  1. 拆分组件:拆分页面,抽取组件

  2. 实现静态组件,使用组件实现静态页面效果

  3. 实现动态组件

    动态显示初始化数据(数据类型、数据名称、保存在哪个组件)

    交互(从绑定事件监听开始)

TODO List

  • 生成唯一 UUID
yarn add nanoid
  • 点击复选框切换提示是否选中及附带信息
  • 点击按钮
handleCheck = id => {
  return e => {
    this.props.updateTodo(id, e.target.checked)
  }
}
<input type="checkbox" defaultChecked={false} onChange={this.handleCheck(id)} />


handleDelete = id => {
  if (window.confirm('确定删除吗?')) {
    this.props.deleteTodo(id)
  }
}
<button onClick={() => this.handleDelete(id)}>删除</button>
  1. 拆分组件、实现静态组件,注意:className、style 的写法
  2. 动态初始化列表,如何确定将数据放在哪个组件的 state 中
    • 某个组件使用:放在自身的 state 中
    • 某个组件使用:放在他们共同的父组件 state 中(官方称此操作:状态提升)
  3. 父子之间通信
    • 【父组件】给【子组件】传递数据:通过 props 传递
    • 【子组件】给【父组件】传递数据:通过 props 传递,要求父提前给子传递一个函数
  4. 注意 defaultChecked 和 checked 区别,类似的还有:defaultValue 和 value
  5. 状态在哪里,操作状态的方法就在哪里

App.jsx

import React, { Component } from 'react'
import './index.css'
import Header from './component/Header'
import List from './component/List'
import Footer from './component/Footer'

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: true },
    ],
  }
  addTodo = todoObj => {
    const { todos } = this.state
    const newTodos = [todoObj, ...todos]
    this.setState({ todos: newTodos })
  }
  updateTodo = (id, done) => {
    const { todos } = this.state
    const newTodos = todos.map(todoObj => {
      if (todoObj.id === id) return { ...todoObj, done }
      else return todoObj
    })
    this.setState({ todos: newTodos })
  }
  deleteTodo = id => {
    const { todos } = this.state
    const newTodos = todos.filter(todoObj => todoObj.id !== id)
    this.setState({ todos: newTodos })
  }
  checkAllTodo = done => {
    const { todos } = this.state
    const newTodos = todos.map(todoObj => {
      return { ...todoObj, done }
    })
    this.setState({ todos: newTodos })
  }
  clearAllDone = () => {
    const { todos } = this.state
    const newTodos = todos.filter(todoObj => {
      return !todoObj.done
    })
    this.setState({ todos: newTodos })
  }
  render() {
    const { todos } = this.state
    return (
      <div className="todo-container">
        <div className="todo-wrap">
          <Header addTodo={this.addTodo} />
          <List todos={todos} updateTodo={this.updateTodo} deleteTodo={this.deleteTodo} />
          <Footer todos={todos} checkAllTodo={this.checkAllTodo} clearAllDone={this.clearAllDone} />
        </div>
      </div>
    )
  }
}

Header.jsx

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { nanoid } from 'nanoid'
import './index.css'

export default class Header extends Component {
  static propTypes = {
    addTodo: PropTypes.func.isRequired,
  }
  handleKeyUp = e => {
    const { keyCode, target } = e
    if (keyCode !== 13) return
    if (target.value.trim() === '') return
    const todoObj = { id: nanoid(), name: target.value, done: false }
    this.props.addTodo(todoObj)
    target.value = ''
  }
  render() {
    return (
      <div className="todo-header">
        <input onKeyUp={this.handleKeyUp} type="text" placeholder="请输入你的任务名称,按回车键确认" />
      </div>
    )
  }
}

List.jsx

import React, { Component } from 'react'
import Item from '../Item'
import PropTypes from 'prop-types'
import './index.css'

export default class List extends Component {
  static propTypes = {
    todos: PropTypes.array.isRequired,
    updateTodo: PropTypes.func.isRequired,
    deleteTodo: PropTypes.func.isRequired,
  }
  render() {
    const { todos, updateTodo, deleteTodo } = this.props
    return (
      <ul className="todo-main">
        {todos.map(todo => {
          return <Item key={todo.id} {...todo} updateTodo={updateTodo} deleteTodo={deleteTodo} />
        })}
      </ul>
    )
  }
}

Item.jsx

import React, { Component } from 'react'
import './index.css'

export default class Item extends Component {
  state = { mouse: false }
  handleMouse = flag => {
    return () => {
      this.setState({ mouse: flag })
    }
  }
  handleCheck = id => {
    return e => {
      this.props.updateTodo(id, e.target.checked)
    }
  }
  handleDelete = id => {
    if (window.confirm('确定删除吗?')) {
      this.props.deleteTodo(id)
    }
  }
  render() {
    const { id, name, done } = this.props
    const { mouse } = this.state
    return (
      <li style={
   
   { backgroundColor: mouse ? '#ddd' : '#fff' }} onMouseLeave={this.handleMouse(false)} onMouseEnter={this.handleMouse(true)}>
        <label>
          <input type="checkbox" checked={done} onChange={this.handleCheck(id)} />
          <span>{name}</span>
        </label>
        <button onClick={() => this.handleDelete(id)} className="btn btn-danger" style={
   
   { display: mouse ? 'block' : 'none' }}>
          删除
        </button>
      </li>
    )
  }
}

Footer.jsx

import React, { Component } from 'react'
import './index.css'

export default class Footer extends Component {
  handleCheckAll = e => {
    this.props.checkAllTodo(e.target.checked)
  }
  handleClearAllDone = () => {
    this.props.clearAllDone()
  }
  render() {
    const { todos } = this.props
    const doneCount = todos.reduce((pre, cur) => pre + (cur.done ? 1 : 0), 0)
    const total = todos.length
    return (
      <div className="todo-footer">
        <label>
          <input type="checkbox" onChange={this.handleCheckAll} checked={(doneCount === total) & (total !== 0) ? true : false} />
        </label>
        <span>
          <span>已完成{doneCount}</span> / 全部{total}
        </span>
        <button className="btn btn-danger" onClick={this.handleClearAllDone}>
          清除已完成任务
        </button>
      </div>
    )
  }
}

Guess you like

Origin blog.csdn.net/qq_38689395/article/details/117478647