react学习笔记(3)

1、组件通讯-父到子

class Father extends React.Component {
  constructor(props) {
    super(props)

    // 组件的状态是私有的,别的组件是用不了
    this.state = {
      msg: '哈哈'
    }
  }
  render() {
    return (
      <div>
        我是父组件
        <Son msg={this.state.msg} name="zs" age="18" />
      </div>
    )
  }
}

// 需求: 在子组件中如何使用父组件的数据
// 1. 父组件通过自定义的属性把值传递给子组件
// 2. 子组件通过props属性可以获取到所有父组件传递过来的数据
class Son extends React.Component {
  // props就有所有父组件传递过来的数据
  constructor(props) {
    super(props)
  }
  render() {
    console.log(this.props)
    return (
      <div>
        我是子组件-----
        {this.props.name} ----
        {this.props.msg}
      </div>
    )
  }
}

ReactDOM.render(<Father />, document.getElementById('app'))

2、组件通讯-子到父

class Father extends React.Component {
  render() {
    return (
      <div style={{ width: 400, height: 400, backgroundColor: 'pink' }}>
        这是父组件
        {/* 2. 父组件把方法传递给子组件 */}
        <Son getData={this.getData} />
      </div>
    )
  }
  //1: 父组件提供一个方法
  getData(msg) {
    console.log(msg)
    console.log('我执行吗')
  }
}

class Son extends React.Component {
  constructor(props) {
    // 子组件通过props来接收父组件传递过来的方法
    super(props)

    this.state = {
      msg: '哈哈'
    }
  }
  render() {
    return (
      <div style={{ width: 200, height: 100, backgroundColor: 'green' }}>
        <p>{this.state.msg}</p>
        <button onClick={this.sendData}>给父组件传递数据</button>
      </div>
    )
  }

  sendData = () => {
    // 4. 给父组件传递数据
    let { getData } = this.props
    getData(this.state.msg)
  }
}

ReactDOM.render(<Father />, document.getElementById('app'))

3、组件通讯-非父子

// 对于多个组件需要共享的数据,应该把这个数据存放到他们公共的父组件中。状态提升
// 始终保持数据是单向数据流。

// 单向数据流
// 状态提升

4、评论列表-基本功能

class Comment extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      list: [
        { id: 1, name: '张三', content: '沙发' },
        { id: 2, name: '李四', content: '板凳' },
        { id: 3, name: '王五', content: '卖瓜子' }
      ],
      index: 3
    }
  }
  render() {
    return (
      <div>
        <h1>评论案例</h1>
        <CommentForm add={this.add} />
        <hr />
        {/* 1. 父组件把评论列表数据传递给了子组件 */}
        <CommentList list={this.state.list} />
      </div>
    )
  }

  // 添加评论的方法
  add = (name, content) => {
    this.state.list.push({
      id: ++this.state.index,
      name,
      content
    })
    this.setState(this.state)
  }
}

class CommentForm extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      name: '',
      content: ''
    }
  }
  render() {
    return (
      <div className="form">
        <input
          type="text"
          value={this.state.name}
          onChange={this.handleChange}
          name="name"
        />
        <br />
        <textarea
          name="content"
          value={this.state.content}
          onChange={this.handleChange}
          cols="30"
          rows="5"
        />
        <br />
        <button onClick={this.clickFn}>添加</button>
      </div>
    )
  }
  clickFn = () => {
    // 调用父组件传递过来的方法
    let { add } = this.props
    add(this.state.name, this.state.content)

    // 清空表单
    this.setState({
      name: '',
      content: ''
    })
  }
  handleChange = e => {
    let { name, value } = e.target
    this.setState({
      [name]: value
    })
  }
}

class CommentList extends React.Component {
  constructor(props) {
    super(props)
  }
  render() {
    // 2. 子组件通过props可以获取到父组件传递过来的数据
    let { list } = this.props
    return (
      <div className="list">
        <ul>
          {list.map(item => (
            <li key={item.id}>
              <h3>
                评论人:
                {item.name}
              </h3>
              <p>
                评论内容:
                {item.content}
              </p>
            </li>
          ))}
        </ul>
      </div>
    )
  }
}
ReactDOM.render(<Comment />, document.getElementById('app'))

5、react中的children属性

class Modal extends React.Component {
  render() {
    let { title, children } = this.props
    // 通过props.children就能够获取到组件的子元素
    return (
      <div>
        <h3>{title}</h3>
        <div>{children}</div>
      </div>
    )
  }
}

// vue 中 slot插槽
ReactDOM.render(
  <div>
    <Modal title="提示">你是否要退出本系统?</Modal>
    <Modal title="温馨提示">是确定要删除这条记录吗?</Modal>
    <Modal title="警告">这是一个提示的消息</Modal>
  </div>,
  document.getElementById('app')
)

6、react中发送请求-axios

class App extends React.Component {
  render() {
    return (
      <div>
        <button onClick={this.clickFn}>获取所有的书籍</button>
        <button onClick={this.add}>添加书籍</button>
      </div>
    )
  }

  clickFn = async () => {
    // 发送axios请求
    let res = await axios.get('http://localhost:9999/getBookList')
    console.log(res.data)
  }
  add = async () => {
    console.log('11')
    // 发送请求,添加书籍
    let res = await axios.post('http://localhost:9999/addBook', {
      name: '你不知道的js',
      desc: 'js程序员应该好好读一下'
    })
    console.log(res)
  }
}

ReactDOM.render(<App />, document.getElementById('app'))

7、fetch的使用

class App extends React.Component {
  render() {
    return (
      <div>
        <button onClick={this.getAll}>获取所有的书籍</button>
        <button onClick={this.add}>添加书籍</button>
        <button onClick={this.getInfo}>获取书籍详情</button>
      </div>
    )
  }

  getAll = () => {
    // 发送一个get请求,获取所有的书籍
    // fetch是window的一个方法,fetch是一个全局方法,可以直接使用
    // fetch: 返回的是promise对象
    fetch('http://localhost:9999/getBookList')
      .then(res => {
        // res是一个promise对象,表示请求的结果
        // res获取到仅仅是响应的结果,还不是我们想要的json
        // 还需要对res.json()才表示把响应结果转成json,返回的额是promise
        return res.json()
      })
      .then(data => {
        console.log(data)
      })
  }

  getInfo = async () => {
    let res = await fetch('http://localhost:9999/getBookInfo?id=1')
    let data = await res.json()
    console.log(data)
  }

  add = async () => {
    // fetch发送post请求
    // 参数1: 请求的url地址
    // 参数2: 配置对象
    let res = await fetch('http://localhost:9999/addBook', {
      method: 'POST',
      headers: {
        // 用于指定请求的数据类型
        // 'content-type': 'application/x-www-form-urlencoded'
        'content-type': 'application/json'
      },
      body: JSON.stringify({
        name: '测试',
        desc: '测试一下内容'
      })
    })
    let data = await res.json()
    console.log(data)
  }
}

ReactDOM.render(<App />, document.getElementById('app'))

8、图书馆管理案例

class Book extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      list: [],
      name: '',
      desc: '',
      id: ''
    }
  }

  getBookList = async () => {
    // 发送ajax请求,获取到所有的书籍的数据,存到list中
    let res = await fetch('http://localhost:9999/getBookList')
    let data = await res.json()
    let { status, list } = data
    if (status === 200) {
      this.setState({
        list
      })
    }
  }

  // 组件挂载好了的时候会触发
  componentDidMount() {
    this.getBookList()
  }

  delBook = async (id, e) => {
    // 组件默认行为
    e.preventDefault()
    //1. 获取到了id值
    //2. 使用fetch发送请求,删除一条数据,
    //3. 成功了,需要重新渲染页面
    if (confirm('你是否要删除这条记录')) {
      let res = await fetch(`http://localhost:9999/deleteBook?id=${id}`)
      let data = await res.json()
      if (data.status === 200) {
        // 删除成功了
        this.getBookList()
      }
    }
  }

  handleChange = e => {
    let { name, value } = e.target
    this.setState({
      [name]: value
    })
  }

  save = async () => {
    let { id, name, desc } = this.state
    let url = null
    let params = {
      name,
      desc
    }
    if (id) {
      url = 'http://localhost:9999/editBook'
      params.id = id
    } else {
      url = 'http://localhost:9999/addBook'
    }
    // 就是新增的操作
    let res = await fetch(url, {
      method: 'POST',
      headers: {
        'content-type': 'application/json'
      },
      body: JSON.stringify(params)
    })
    let data = await res.json()
    let { status } = data
    if (status === 200) {
      // 重新渲染
      this.getBookList()
      // 清空表单数据
      this.setState({
        name: '',
        desc: '',
        id: ''
      })
    }
  }

  editBook = (book, e) => {
    // 需要把书籍的信息回显到表单里面
    let { id, name, desc } = book
    e.preventDefault()
    // 数据回显
    this.setState({
      name,
      desc,
      id
    })
  }
  render() {
    let { list } = this.state
    return (
      <div className="container">
        <div className="form">
          书名:
          <input
            type="text"
            value={this.state.name}
            onChange={this.handleChange}
            name="name"
          />
          描述:
          <input
            type="text"
            name="desc"
            value={this.state.desc}
            onChange={this.handleChange}
          />
          <button onClick={this.save}>保存</button>
        </div>
        <table>
          <thead>
            <tr>
              <th>编号</th>
              <th>书名</th>
              <th>描述</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            {list.map((item, index) => (
              <tr key={item.id}>
                <td>{index + 1}</td>
                <td>{item.name}</td>
                <td>{item.desc}</td>
                <td>
                  <a href="#" onClick={this.delBook.bind(this, item.id)}>
                    删除
                  </a>
                  |
                  <a href="#" onClick={this.editBook.bind(this, item)}>
                    修改
                  </a>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    )
  }
}

ReactDOM.render(<Book />, document.getElementById('app'))

9、react-create-app

// npx create-react-app my-app

// npm i create-react-app -g
// create-react-app my-app

(1)index.css

.container {
  width: 600px;
}

table {
  margin-top: 30px;
  border: 1px solid blue;
  border-collapse: collapse;
  width: 100%;
}

table th,
table td {
  border: 1px solid blue;
  height: 50px;
  line-height: 50px;
  text-align: center;
}

(2)index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <link rel="stylesheet" href="index.css">
</head>

<body>
  <div id="app"></div>
  <script src="lib/react.development.js"></script>
  <script src="lib/react-dom.development.js"></script>
  <script src="lib/babel.min.js"></script>
  <script src="lib/axios.js"></script>
  <script type="text/babel" src="08-图书管理案例.js"></script>

</body>

</html>

(3)package-lock.json

{
  "requires": true,
  "lockfileVersion": 1,
  "dependencies": {
    "axios": {
      "version": "0.18.0",
      "resolved": "http://registry.npm.taobao.org/axios/download/axios-0.18.0.tgz",
      "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
      "requires": {
        "follow-redirects": "^1.3.0",
        "is-buffer": "^1.1.5"
      }
    },
    "debug": {
      "version": "3.1.0",
      "resolved": "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz",
      "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
      "requires": {
        "ms": "2.0.0"
      }
    },
    "follow-redirects": {
      "version": "1.5.8",
      "resolved": "http://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.5.8.tgz",
      "integrity": "sha1-Hb/hPkWtlp+BPobADlKW9SXIhaE=",
      "requires": {
        "debug": "=3.1.0"
      }
    },
    "is-buffer": {
      "version": "1.1.6",
      "resolved": "http://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz",
      "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4="
    },
    "ms": {
      "version": "2.0.0",
      "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz",
      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
    }
  }
}

10、react-demo

10.1、components

(1)Home.jsx

import React from 'react'
export default class Home extends React.Component {
  render() {
    return <div>这是home组件</div>
  }
}

(2)Login.jsx

import React from 'react'
export default class Login extends React.Component {
  render() {
    return <div>这是Login组件</div>
  }
}

(3)User.jsx

import React from 'react'
export default class User extends React.Component {
  render() {
    return <div>这是User组件</div>
  }
}

10.2、App.jsx

// react-router-dom的详解
import React from 'react'
import Home from './components/Home.jsx'
import User from './components/User.jsx'
import Login from './components/Login.jsx'
import { HashRouter, Link, Route, Switch } from 'react-router-dom'

class App extends React.Component {
  render() {
    // HashRouter和BrowserRouter都是核心的路由容器
    // HashRouter通过锚点来实现的,路径带了#
    // BrowserRouter通过H5的history模式实现,路径不带#

    // 路由匹配规则相关的组件有俩
    // Route: 表示一个匹配规则
    // Switch: 开关,
    return (
      <HashRouter>
        <div>
          <ul>
            <li>
              <Link to="/home">首页</Link>
            </li>
            <li>
              <Link to="/user">用户管理</Link>
            </li>
            <li>
              <Link to="/login">登录</Link>
            </li>
          </ul>
          {/* Switch : 使用Switch把一组route包裹起来,保证只显示一个组件 */}
          {/* 配置路由规则 一个路径会对应一个组件 */}
          <Switch>
            <Route path="/home" component={Home} />
            <Route path="/user" component={User} />
            <Route path="/login" component={Login} />
          </Switch>
        </div>
      </HashRouter>
    )
  }
}

export default App

10.3、App-基本使用.jsx

// 根组件
import React from 'react'
import Home from './components/Home.jsx'
import User from './components/User.jsx'
import Login from './components/Login.jsx'
import { HashRouter, Route, Link } from 'react-router-dom'
// 如何在react项目中使用react-router
// 1. 需要安装react-router-dom包  npm i react-router-dom
// 2. 需要引入一些组件

class App extends React.Component {
  render() {
    // HashRouter:整个路由容器,将来配置路由,是一定要有一个HashRouter
    // Link : 相当于vue中 router-link 配置路由的连接,最终会渲染成一个a标签
    // Route: 配置路由规则
    return (
      <HashRouter>
        <div>
          <ul>
            <li>
              <Link to="/home">首页</Link>
            </li>
            <li>
              <Link to="/user">用户管理</Link>
            </li>
            <li>
              <Link to="/login">登录</Link>
            </li>
          </ul>
          {/* 配置路由规则 一个路径会对应一个组件 */}
          <Route path="/home" component={Home} />
          <Route path="/user" component={User} />
          <Route path="/login" component={Login} />
        </div>
      </HashRouter>
    )
  }
}

export default App

10.3、index.js

import React from 'react'
import ReactDOM from 'react-dom'

import App from './App.jsx'

ReactDOM.render(<App />, document.getElementById('root'))

11、脚手架基本使用

11.1、components

(1)Comment.css

.container {
  width: 800px;
  margin: 0 auto;
}

(2)Comment.jsx

import React from 'react'
import CommentForm from './CommentForm.jsx'
import CommentList from './CommentList.jsx'
import './Comment.css'
class Comment extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      list: [
        { id: 1, name: '张三', content: '沙发' },
        { id: 2, name: '李四', content: '板凳' },
        { id: 3, name: '王五', content: '卖瓜子' }
      ],
      index: 3
    }
  }
  render() {
    return (
      <div className="container">
        <h1>评论案例</h1>
        <CommentForm add={this.add} />
        <hr />
        {/* 1. 父组件把评论列表数据传递给了子组件 */}
        <CommentList list={this.state.list} />
      </div>
    )
  }

  // 添加评论的方法
  add = (name, content) => {
    this.state.list.push({
      id: ++this.state.index,
      name,
      content
    })
    this.setState(this.state)
  }
}

export default Comment

(3)CommentForm.jsx

import React from 'react'
class CommentForm extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      name: '',
      content: ''
    }
  }
  render() {
    return (
      <div className="form">
        <input
          type="text"
          value={this.state.name}
          onChange={this.handleChange}
          name="name"
        />
        <br />
        <textarea
          name="content"
          value={this.state.content}
          onChange={this.handleChange}
          cols="30"
          rows="5"
        />
        <br />
        <button onClick={this.clickFn}>添加</button>
      </div>
    )
  }
  clickFn = () => {
    // 调用父组件传递过来的方法
    let { add } = this.props
    add(this.state.name, this.state.content)

    // 清空表单
    this.setState({
      name: '',
      content: ''
    })
  }
  handleChange = e => {
    let { name, value } = e.target
    this.setState({
      [name]: value
    })
  }
}

export default CommentForm

(4)CommentList.jsx

import React from 'react'
class CommentList extends React.Component {
  render() {
    // 2. 子组件通过props可以获取到父组件传递过来的数据
    let { list } = this.props
    return (
      <div className="list">
        <ul>
          {list.map(item => (
            <li key={item.id}>
              <h3>
                评论人:
                {item.name}
              </h3>
              <p>
                评论内容:
                {item.content}
              </p>
            </li>
          ))}
        </ul>
      </div>
    )
  }
}

// 导出组件
export default CommentList

11.2、App.jsx

// jsx就表示一个react组件,  jsx仅仅是后缀不一样 jsx的作用和js的作用完全一样
// 有些编辑器,看到jsx文件,提供一些高亮,提示等等
// 定义一个根组件
import React from 'react'
import Comment from './components/Comment.jsx'
class App extends React.Component {
  render() {
    return <Comment />
  }
}
// 导出根组件
export default App

11.3、index.css

body {
  margin: 0;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
    "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
    monospace;
}

11.4、index.js

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
// 导入根组件react的根组件,我们的内容都应该写到App里面
import App from './App.jsx'
// 渲染了根组件
ReactDOM.render(<App />, document.getElementById('root'))
发布了284 篇原创文章 · 获赞 45 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_31784189/article/details/103354568
今日推荐