• React基础 (3)


    React 组件基础

    主要内容

    • 表单

    • PropTypes类型检测

    • 组合

    • 网络请求

    学习目标

    知识点要求
    表单掌握
    PropTypes类型检测掌握
    组合掌握
    网络请求掌握

    一、表单

    1.1 受控组件

    介绍:在 HTML 中,表单元素通常自己维护 value值,并根据用户输入进行更新。而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState()来更新,使 React 的 state 成为“唯一数据源”。

    语法:

    1. <input type="text" value={this.state.value}  onChange={this.handleChange} />
    2. handleChange(event) {
    3.  this.setState({value: event.target.value});
    4. }

    常见的受控组件

      input 
      textarea
      select

    提交功能,阻止form标签的默认行为

    1. <form action="https://www.baidu.com" onSubmit={this.sub}>
    2.   用户名:<input type="text" name='username' value={this.state.username} onChange={this.cname} />
    3.   密码:<input type="password" name='password' value={this.state.pwd} onChange={this.cpwd.bind(this)} />
    4.    <button type='submit'>提交</button>
    5. </form>
    6. sub =(e)=>{
    7.    // 阻止默认事件
    8.    e.preventDefault();
    9. }

    1.2 非受控组件

    在大多数情况下,我们推荐使用 受控组件 来处理表单数据。在一个受控组件中,表单数据是由 React 组件来管理的。另一种替代方案是使用非受控组件,这时表单数据将交由 DOM 节点来处理,可以使用 ref 来从 DOM 节点中获取表单数据。

    1. 创建步骤:

    创建Ref语法:this.myRef = React.createRef()

    绑定到元素上:

    获DOM元素:this.myRef.current

    2. 使用

    1. class NameForm extends React.Component {
    2.  constructor(props) {
    3.    super(props);
    4.    this.handleSubmit = this.handleSubmit.bind(this);
    5.    this.input = React.createRef();
    6. }
    7.  handleSubmit(event) {
    8.    alert('A name was submitted: ' + this.input.current.value);
    9.    event.preventDefault();
    10. }
    11.  render() {
    12.    return (
    13.      <form onSubmit={this.handleSubmit}>
    14.        <label>
    15.         Name:
    16.          <input type="text" ref={this.input} />
    17.        </label>
    18.        <input type="submit" value="Submit" />
    19.      </form>
    20.   );
    21. }
    22. }

    二、PropTypes类型检测

    2.1 介绍

    PropTypes 提供一系列验证器,可用于确保组件接收到的数据类型是有效的。

    2.2 使用步骤

    1. 导入组件

    import PropTypes from 'prop-types';
    1. 演示案例

    1. import PropTypes from 'prop-types';
    2. class Greeting extends React.Component {
    3.  render() {
    4.    return (
    5.      

      Hello, {this.props.name}

    6.   );
    7. }
    8. }
    9. Greeting.propTypes = {
    10.  name: PropTypes.string
    11. };
    1. 检验语法

    1. import PropTypes from 'prop-types';
    2. MyComponent.propTypes = {
    3.  // 你可以将属性声明为 JS 原生类型,默认情况下
    4.  // 这些属性都是可选的。
    5.  optionalArray: PropTypes.array,
    6.  optionalBool: PropTypes.bool,
    7.  optionalFunc: PropTypes.func,
    8.  optionalNumber: PropTypes.number,
    9.  optionalObject: PropTypes.object,
    10.  optionalString: PropTypes.string,
    11.  optionalSymbol: PropTypes.symbol,
    12.  // 任何可被渲染的元素(包括数字、字符串、元素或数组)
    13.  // (或 Fragment) 也包含这些类型。
    14.  optionalNode: PropTypes.node,
    15.  // 一个 React 元素。
    16.  optionalElement: PropTypes.element,
    17.  // 一个 React 元素类型(即,MyComponent)。
    18.  optionalElementType: PropTypes.elementType,
    19.  // 你也可以声明 prop 为类的实例,这里使用
    20.  // JS 的 instanceof 操作符。
    21.  optionalMessage: PropTypes.instanceOf(Message),
    22.  // 你可以让你的 prop 只能是特定的值,指定它为
    23.  // 枚举类型。
    24.  optionalEnum: PropTypes.oneOf(['News', 'Photos']),
    25.  // 一个对象可以是几种类型中的任意一个类型
    26.  optionalUnion: PropTypes.oneOfType([
    27.    PropTypes.string,
    28.    PropTypes.number,
    29.    PropTypes.instanceOf(Message)
    30. ]),
    31.  // 可以指定一个数组由某一类型的元素组成
    32.  optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
    33.  // 可以指定一个对象由某一类型的值组成
    34.  optionalObjectOf: PropTypes.objectOf(PropTypes.number),
    35.  // 可以指定一个对象由特定的类型值组成
    36.  optionalObjectWithShape: PropTypes.shape({
    37.    color: PropTypes.string,
    38.    fontSize: PropTypes.number
    39. }),
    40.  
    41.  // An object with warnings on extra properties
    42.  optionalObjectWithStrictShape: PropTypes.exact({
    43.    name: PropTypes.string,
    44.    quantity: PropTypes.number
    45. }),  
    46.  // 你可以在任何 PropTypes 属性后面加上 `isRequired` ,确保
    47.  // 这个 prop 没有被提供时,会打印警告信息。
    48.  requiredFunc: PropTypes.func.isRequired,
    49.  // 任意类型的数据
    50.  requiredAny: PropTypes.any.isRequired,
    51.  // 你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象。
    52.  // 请不要使用 `console.warn` 或抛出异常,因为这在 `onOfType` 中不会起作用。
    53.  customProp: function(props, propName, componentName) {
    54.    if (!/matchme/.test(props[propName])) {
    55.      return new Error(
    56.        'Invalid prop `' + propName + '` supplied to' +
    57.        ' `' + componentName + '`. Validation failed.'
    58.     );
    59.   }
    60. },
    61.  // 你也可以提供一个自定义的 `arrayOf` 或 `objectOf` 验证器。
    62.  // 它应该在验证失败时返回一个 Error 对象。
    63.  // 验证器将验证数组或对象中的每个值。验证器的前两个参数
    64.  // 第一个是数组或对象本身
    65.  // 第二个是他们当前的键。
    66.  customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
    67.    if (!/matchme/.test(propValue[key])) {
    68.      return new Error(
    69.        'Invalid prop `' + propFullName + '` supplied to' +
    70.        ' `' + componentName + '`. Validation failed.'
    71.     );
    72.   }
    73. })
    74. };
    1. 默认值

    组件名.defaultProps={
    props属性名:默认值
    }
    1. 代码演示

    1. import React from 'react'
    2. // 引入prop-types库
    3. import propTypes from 'prop-types'
    4. export default class Home extends React.Component{
    5.    render(){
    6.        return(
    7.            <div>
    8.                <h1>props类型检测</h1>
    9.                <p>{this.props.data}</p>
    10.            </div>
    11.       )
    12.   }
    13. }
    14. // 定义检测
    15. Home.propTypes={
    16.    data:propTypes.string.isRequired,
    17.    msg:propTypes.oneOfType([
    18.        propTypes.string,
    19.        propTypes.array
    20.   ])
    21. }
    22. // 定义默认值
    23. Home.defaultProps={
    24.    data:'默认值'
    25. }

    三、组合

    3.1 介绍

    有些组件无法提前知晓它们子组件的具体内容。在 Sidebar(侧边栏)和 Dialog(对话框)等展现通用容器(box)的组件中特别容易遇到这种情况。我们建议这些组件使用一个特殊的 children prop 来将他们的子组件传递到渲染结果中。

    3.2 语法

    1.组件定义中使用 this.props.children 接收内容。

    2.组件调用时在组件内部写具体内容

    1. //定义的组件:
    2. function FancyBorder(props) {
    3.  return (
    4.    <div className={'FancyBorder FancyBorder-' + props.color}>
    5.     {props.children}
    6.    </div>
    7. );
    8. }
    9. //组件调用:
    10. function WelcomeDialog() {
    11.  return (
    12.    <FancyBorder color="blue">
    13.      <h1 className="Dialog-title">
    14.       Welcome
    15.      </h1>
    16.      <p className="Dialog-message">
    17.       Thank you for visiting our spacecraft!
    18.      </p>
    19.    </FancyBorder>
    20. );
    21. }

    3.3 案例

    3.4 代码演示

    弹框组件

    1. import React, { Component } from 'react'
    2. import './style.css'
    3. export default class Dialog extends Component {
    4.    close =()=>{
    5.        this.props.hide();
    6.   }
    7.    render() {
    8.        return (
    9.            <div className='bg' style={ {visibility:this.props.visible } }>
    10.                <div className='box'>
    11.                    <div className='top'>
    12.                        <h4>扫码登录</h4>
    13.                        <span className='close' onClick={this.close}>X</span>
    14.                    </div>
    15.                   {/* 内容区域 不知道放什么 */}
    16.                    <div className='content'>
    17.                       { this.props.children }
    18.                    </div>
    19.                </div>
    20.            </div>
    21.       )
    22.   }
    23. }

    百度组件

    1. import React, { Component } from 'react'
    2. import Dialog from './Dialog'
    3. //导入图片
    4. import baidu from '../../assets/img/baidu.png'
    5. export default class Baidu extends Component {
    6.    //创建ref
    7.    constructor(){
    8.        super()
    9.        this.state={
    10.            visible:'hidden',
    11.            visible2:'hidden',
    12.       }
    13.   }
    14.    //定义函数
    15.    showDialog=()=>{
    16.        this.setState({
    17.            visible:'visible'
    18.       })
    19.   }
    20.    showDialog2=()=>{
    21.        this.setState({
    22.            visible2:'visible'
    23.       })
    24.   }
    25.    hide=()=>{
    26.        this.setState({
    27.            visible:'hidden',
    28.            visible2:'hidden'
    29.       })
    30.   }
    31.    //渲染页面
    32.    render() {
    33.        return (
    34.            <div>
    35.                <h3>百度登录首页--测试组合使用</h3>
    36.                <button onClick={this.showDialog}>扫码登录</button>
    37.                <button onClick={this.showDialog2}>账号登录</button>
    38.               {/* 弹框显示二维码 */}
    39.                <Dialog visible={this.state.visible} hide={this.hide}>
    40.                    <img src={baidu} alt="" />
    41.                </Dialog>
    42.               {/* 账号密码登录 */}
    43.                <Dialog visible={this.state.visible2} hide={this.hide}>
    44.                    <form action="" method="get">
    45.                       账号: <input type="text" />
    46.                        <br />
    47.                        <br />
    48.                       密码:
    49.                        <input type="text" />
    50.                    </form>
    51.                </Dialog>
    52.            </div>
    53.       )
    54.   }
    55. }

    四、网络请求

    4.1 网络请求方式

    方式如下:

    1. jquery

    2. fetch

    3. axios

    4.2 fetch网络请求

    介绍

    1. 是es6中提供的一种新的网络请求方式。Fetch API 提供了一个 JavaScript接口,用于访问和操纵HTTP管道的部分,不是ajax了。

    2. fetch方法是一个全局方法,可以在任意位置使用

    3. fetch()返回的 Promise ,使用 .then()获取请求成功的结果, 使用.catch捕获错误信息

    4. 默认情况下,fetch 不会从服务端发送或接收任何 cookies,要发送 cookies,必须设置 credentials 选项,credentials的默认值是 same-origin

    语法

    1. fetch(url, {
    2.  body: JSON.stringify(data), // must match 'Content-Type' header
    3.  cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
    4.  credentials: 'same-origin', // include, same-origin, omit
    5. //omit: 默认值,忽略cookie的发送
    6. //same-origin: 表示cookie只能同域发送,不能跨域发送
    7. //include: cookie既可以同域发送,也可以跨域发送
    8.  headers: {
    9.    'user-agent': 'Mozilla/4.0 MDN Example',
    10.    'content-type': 'application/json'
    11. },
    12.  method: 'POST', // *GET, POST, PUT, DELETE, etc.
    13.  mode: 'cors', // no-cors, cors, *same-origin
    14.  redirect: 'follow', // manual, *follow, error
    15.  referrer: 'no-referrer', // *client, no-referrer
    16. })

    参数说明:

    1.url, 网络请求地址

    2.参数2是一个大的配置项

    body:要网后台发生的数据 ,数据格式是 'key=value&key=value'

    cache:是否缓存

    credentials:是否发生和接收cookie

    headers:请求头,如果是post请求,需要配置

    {'content-type':'application/x-www-form-urlencoded'}

    method:请求方式

    mode:是否允许跨域

    返回值

    fetch()返回的 Promise对象,使用 .then()获取请求成功的结果,这个结果是一个Response 对象,使用前需要解析,解析方法有:

    blob():解析成二进制

    json():解析成JSON对象

    text():解析成文本

    代码演示

    1. fetch('http://iwenwiki.com/api/blueberrypai/getIndexBanner.php')
    2. .then(function(data){
    3.    return data.json()
    4. })
    5. .then(function(res){
    6.    console.log(res)
    7. })

    请求参数

    1. get请求
    2. fetch('url?key=value&key=value')
    3. post请求
    4. fetch('url',{
    5.    
    6.  body:'key=value&key=value',
    7.  headers:{
    8.    'content-type':'application/x-www-form-urlencoded'
    9. }
    10. })

    4.3 axios 网络请求

    Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

    特点

    • 从浏览器中创建 XMLHttpRequests

    • 从 node.js 创建 http 请求

    • 支持 [Promise] API

    • 拦截请求和响应

    • 转换请求数据和响应数据

    • 取消请求

    • 自动转换 JSON 数据

    • 客户端支持防御 [XSRF]

    安装

    使用 npm:

    $ npm install axios

    使用 bower:

    $ bower install axios

    使用 cdn:

    执行 GET 请求

    1. // 为给定 ID 的 user 创建请求
    2. axios.get('/user?ID=12345')
    3. .then(function (response) {
    4.    console.log(response);
    5. })
    6. .catch(function (error) {
    7.    console.log(error);
    8. });
    9. // 可选地,上面的请求可以这样做
    10. axios.get('/user', {
    11.    params: {
    12.      ID: 12345
    13.   }
    14. })
    15. .then(function (response) {
    16.    console.log(response);
    17. })
    18. .catch(function (error) {
    19.    console.log(error);
    20. });

    执行 POST 请求

    1. axios.post('/user', {
    2.    firstName: 'Fred',
    3.    lastName: 'Flintstone'
    4. })
    5. .then(function (response) {
    6.    console.log(response);
    7. })
    8. .catch(function (error) {
    9.    console.log(error);
    10. });
    11. // 发送 POST 请求
    12. axios({
    13.  method: 'post',
    14.  url: '/user/12345',
    15.  data: {
    16.    firstName: 'Fred',
    17.    lastName: 'Flintstone'
    18. }
    19. });

    执行多个并发请求

    1. function getUserAccount() {
    2.  return axios.get('/user/12345');
    3. }
    4. function getUserPermissions() {
    5.  return axios.get('/user/12345/permissions');
    6. }
    7. axios.all([getUserAccount(), getUserPermissions()])
    8. .then(axios.spread(function (acct, perms) {
    9.    // 两个请求现在都执行完成
    10. }));

    webpack5里面移除了nodejs模块

    需要安装依赖才可以使用

    npm install node-polyfill-webpack-plugin

    4.4 网络请求案例

    4.5 跨域请求

    cors代理

    参考地址:

    create-react-app/proxying-api-requests-in-development.md at bb64e31a81eb12d688c14713dce812143688750a · facebook/create-react-app · GitHub

    1.在package.json文件中配置

    {
      "proxy":"代理路径"
    }

    一般使用在后台接口写好了,使用时跨域的一种解决方案

    在网络请求中使用:

    fetch('/具体接口名称')

    2.使用中间件 http-proxy-middleware

    1.下载 npm i -S http-proxy-middleware

    2.在src目录下创建一个setupProxy.js文件,在这个文件中写配置

    3.配置 npm i http-proxy-middleware -S

       1. 安装: npm  i http-proxy-middleware -S 
       2. 创建文件:src/setupProxy.js
       3. const { createProxyMiddleware } = require('http-proxy-middleware');
       4. setupProxy.js
                  module.exports = function(app) {
                     app.use(
                         '/api',
                         createProxyMiddleware({
                                    target: 'http://localhost:5000',
                                    changeOrigin: true,
                            })
                     );
                  };

    4.网络请求中使用方式

    fetch('/api/具体接口名称')

    5.一般使用在后台接口还没出来,前台人员自己测试使用

    五、作业

    5.1 效果图

  • 相关阅读:
    Yolov8和Yolov10的差异以及后处理实现
    Cron正则表达式总结汇总说明
    小文件存到HDFS占用空间是文件实际大小,而非一个block块的大小
    Tire树实现
    Hive时间日期函数一文详解+代码实例
    需突破技术成本瓶颈 秸秆饲料前景如何国稻种芯现代饲料规划
    Pandas性能优化:进阶篇
    记一次HBase启动异常的恢复历程
    Ansys Optics Launcher 提升客户体验
    基于SSM框架流浪猫救援网站的设计与实现毕业设计源码201502
  • 原文地址:https://blog.csdn.net/xm1037782843/article/details/127416963