React入门(三)

Hooks

Hook就是“钩子”的意思。在React中,Hooks就是把某个目标结果钩到某个可能会变化的数据源或者事件源上,那么当被钩到的数据或者事件发生变化时,产生这个目标结果的代码会重新执行,产生更新后的结果。

常用钩子

  1. React.useState()
  2. React.useEffect()
  3. React.useRef()
  4. React.useReducer()
  5. React.useContext()

  • useState():状态钩子

useState()用于为函数组件引入状态(state)。纯函数不能有状态,所以把状态放在钩子里面。

const [ XXX,  setXXX ] = React.useState(initValue)

示例:

import React, { useState } from 'react';
const useStateDemo = () => {
  const [count, setCount] = useState(1);
  return (
    <div>  
      {count}
      <Button onClick={() => setCount(count+1)}>count+1</Button>
    </div>
  )
}
export default useStateDemo;

1为count的初始化值,count是一个变量,setCount是用来更新变量count值的一个函数,通常以set + 变量名命名。 

  • useEffect():副作用钩子

useEffect()在函数组件中执行副作用操作,类似于组件中的生命周期钩子。

useEffect(() => { getXXX() },  [XXX]);

示例:

import React, { useState, useEffect } from 'react';
const useEffectDemo = () => {
  const [count, setCount] = useState(1);

  const getCount = () => {
    console.log('count', count)
  }

  useEffect(() => {
    getCount()
  }, [count]);

  return (
    <div>  
      {count}
      <Button onClick={() => setCount(count + 1)}>count+1</Button>
    </div>
  )
}
export default useEffectDemo;

第一个参数getCount是一个函数,通常将异步操作的代码放在里面。第二个参数是一个数组,用于给出 Effect 的依赖项,每当变量count的值发生变化时,useEffect()就会执行。组件第一次渲染时,useEffect()也会执行。

  • useRef(): 变量钩子

useRef 是一个对象,它拥有一个 current 属性,并且不管函数组件执行多少次,返回的对象永远都是原来那一个。useRef不仅可以用来管理 DOM ref 的,还可以相当于 this存放任何变量。useRefuseState不同,如果一个状态或者数据会影响DOM的渲染结果,一定要避免使用useRef来保持引用

const useRefDemo = () => {
  const inputRef = useRef(null)
  const refTest = useRef(0);
  console.log('refTest', refTest)
  const getInputValue=()=>{
    console.log('inputValue:', inputRef.current.value);
  }
  const add = () => {
    refTest.current += 1;
    console.log('add', refTest);
  };
  return (
    <div>
      <div>
        <input ref={inputRef} type='text'/>
        <Button onClick={getInputValue}>点击获取input值</Button>
      </div>
      <div>
        <h1>当前current:{refTest.current}</h1>
        <Button onClick={add}>count+1</Button>
      </div>
    </div>
  )
}
export default useRefDemo;

效果: 

 

方法一:用来绑定文本框 ref ,通过内置的current属性得到input上输入的值。

方法二:第一次控制台打印出current,初始值为0,是定义时传入的0 ,点击count+1按钮后显示 current的值已经改变了,但是在页面上并没有更新,因为useRef 不像 useState 会主动通知页面重新渲染。

  • useReducer():action 钩子

useReducer()可以为函数式组件提供类似Redux的功能,类似于vuex都是提供状态管理的

const [state, dispatch] = useReducer(reducer, initialState);

import React, { useReducer } from 'react'

const reducer = (state, action) => {
  if(action === 'add') {
    return state+1
  }
  return state
}
const useReducerDemo = () => {
  const [state, dispatch] = useReducer(reducer, 0)
  return (
    <div>
      <h1>{state}</h1>
      <Button onClick={() => dispatch('add')}>+1</Button>
    </div>
  )
}

export default useReducerDemo;

定义[state, dispatch]来接收我们后面的useReducer,因为useReducer包含两个参数,一个参数为useReducer的函数reducer,一个为初始值0

  • useContext():共享状态钩子

如果需要在组件之间共享状态,可以使用useContext()

import React, { useContext } from 'react';

const nameContext = React.createContext();
const useContextDemo = () => {
  return (
    <nameContext.Provider value={'派大星'}>
        <div>
            <ShowNameProvider />
            <ShowNameConsumer />
        </div>
    </nameContext.Provider>
  )
}

const ShowNameProvider = () => {
  const name = useContext(nameContext);
  return(
    <div>
      Provider: 我是 {name}
    </div>
  )
}
const ShowNameConsumer = () => {
  return (
    <div>
      <nameContext.Consumer>
        {name=> <div>Consumer: 我是 {name}</div>}
      </nameContext.Consumer>
    </div>
  )
}
export default useContextDemo;

效果: 

首先创建一个context,返回一个有两个值的对象{Provider , Consumer}

方法一:使用Provider 为子组件提供value,再调用useContext,传入从React.createContext获取的上下文对象

方法二:使用Consumer从上下文获取value

使用React搭建用户信息模块(纯前端)

  • 新建Content.js,并在app.js引用

Content.js

import React, { useState, useEffect } from 'react';
import Filter from './Filter';
import TableDetail from './TableDetail';

const Content = () => {
  const [filterData, setFilterData] = useState([])
  const getFilterData = (e) => {
    console.log(e)
    setFilterData(e)
  }

  return (
    <div>
      <div style={{ paddingLeft: '10px' }}>
        <h1>筛选数据</h1>
        <Filter getFilterData={getFilterData} />
        </div>
    </div>
  )
}
export default Content;
import React from 'react';

import Content from './components/Content'


export default function App() {
  return (
    <Content/>
  );
}
  • 新建Filter.js,在Content插入Filter组件,并将Filter组件的筛选信息传给Content 

Filter.js 

import React, { useState, useEffect } from 'react';
import { Divider, Button, Radio } from 'antd';
import { SearchOutlined } from '@ant-design/icons';
import '../common/style/filter.css'

const Filter = (props) => {
  const { getFilterData } = props;
  const [genderOptions, setGenderOptions] = useState(false);
  const [roleOptions, setRoleOptions] = useState(false);
  const [role, setRole] = useState('admin');
  const [gender, setGender] = useState('女');
  // 筛选项
  const getGenderOptions = () => {
    let option = [
      { label: '男', value: '男' },
      { label: '女', value: '女' },
    ]
    setGenderOptions(option);
  };
  const getRoleOptions = () => {
    let option = [
      { label: 'admin', value: 'admin' },
      { label: 'user', value: 'user' },
    ]
    setRoleOptions(option);
  };
  
  useEffect(() => {
    getGenderOptions()
    getRoleOptions ()
  }, []);

  const onGender = (e) => {
    setGender(e.target.value)
  }
  const onRole = (e) => {
    setRole(e.target.value)
  }
  const search = () => {
    let query = {
      role,
      gender,
    }
    console.log('筛选:', query)
    getFilterData(query)
  }
  return (
    <div>
      <span className='tags'>性别</span>
      <Radio.Group
        options={genderOptions}
        onChange={onGender}
        value={gender}
      />
      <Divider type="vertical" />
      <span className='tags'>角色</span>
      <Radio.Group
        options={roleOptions}
        onChange={onRole}
        value={role}
      />
      <Divider type="vertical" />
      <Button
        type="primary"
        shape="round"
        icon={< SearchOutlined />}
        size='middle'
        onClick={() => search()}
      >
        查询
      </Button>
      <Divider></Divider>
    </div>
  )
}
export default Filter;

效果:

  • 新建 TableDetail.js,在Content插入 TableDetail组件,在Content筛选整理数据后将tableData的数据传递给Table组件

Content.js 

import React, { useState, useEffect } from 'react';
import Filter from './Filter';
import TableDetail from './TableDetail';

const Content = () => {
  const [tableData, setTableData] = useState([])
  const [filterData, setFilterData] = useState([])
  const getTableData = () => {
    const data = [{
      key: '1',
      name: '派大星',
      age: 18,
      account: '123456789',
      password: '123456',
      gender: '女',
      tel: '12345678900',
      address: '广州市番禺区',
      role: 'user',
      tags: ['一级', '二级'],
    },{
      key: '2',
      name: '海绵宝宝',
      age: 22,
      account: '123456780',
      password: '123456',
      gender: '男',
      tel: '12345678900',
      address: '广州市番禺区',
      role: 'admin',
      tags: ['一级'],
    },{
      key: '3',
      name: '章鱼哥',
      age: 20,
      account: '123456781',
      password: '123456',
      gender: '男',
      tel: '12345678900',
      address: '重庆市渝北区',
      role: 'admin',
      tags: ['一级'],
    },{
      key: '4',
      name: '蟹老板',
      account: '123456782',
      password: '123456',
      age: 19,
      gender: '男',
      tel: '12345678900',
      address: '南宁市江南区',
      role: 'user',
      tags: ['二级'],
    },{
      key: '5',
      name: '珊迪',
      account: '123456783',
      password: '123456',
      age: 19,
      gender: '女',
      tel: '12345678900',
      address: '重庆市渝北区',
      role: 'admin',
      tags: ['一级', '二级'],
    }]
    let table = []
    data.map((item) => {
      if (item.role === filterData.role && item.gender === filterData.gender) {
        table.push(item)
      }
    })
    setTableData(table)
  }
  const getFilterData = (e) => {
    console.log(e)
    setFilterData(e)
  }
  useEffect(() => {
    getTableData()
  }, [filterData]);
  return (
    <div>
      <div style={{ paddingLeft: '10px' }}>
        <h1>筛选数据</h1>
        <Filter getFilterData={getFilterData} />
        <TableDetail tableData={tableData}/>
        </div>
    </div>
  )
}
export default Content;

  TableDetail.js

import React, { useState, useEffect } from 'react';
import { Table, Tag, Space, Button, message, Empty } from 'antd';

const { Column } = Table;

const TableDetail = (props) => {
  const {tableData} = props

  const renderUserMessage = () => {
      if (tableData.length > 0) {
        return (
          <span>
            <h1>用户表格</h1>
            <Table dataSource={tableData}>
              <Column
                title="姓名"
                dataIndex="name"
                key="name"
                width={150}
              />
              <Column
                title="角色"
                dataIndex="role"
                key="role"
              />
              <Column
                title="年龄"
                dataIndex="age"
                key="age"
                width={150}
              />
              <Column
                title="账号"
                dataIndex="account"
                key="account"
                width={150}
              />
              <Column
                title="密码"
                dataIndex="password"
                key="password"
                width={200}
              />
              <Column
                title="性别"
                dataIndex="gender"
                key="gender"
              />
              <Column
                title="联系电话"
                dataIndex="tel"
                key="tel"
                width={180}
              />
              <Column
                title="地址"
                dataIndex="address"
                key="address"
                width={300}
              />
              <Column
                title="标签"
                dataIndex="tags"
                key="tags"
                width={200} 
                render={ tags => (
                  <>
                    {tags.map(tag => {
                      let color = tag === '一级' ? 'geekblue' : 'green';
                      return (
                        <Tag color={color} key={tag}>
                          {tag}
                        </Tag>
                      );
                    })}
                  </>
                )}
              />
              <Column
                title="操作"
                key="action"
                render={(text, record) => (
                  <Space size="middle">
                    <Button
                      type="primary"
                      size='mini'
                      onClick={() => actionRow(record.key, 'edit')}>
                      编辑
                    </Button>
                    <Button
                      type="primary"
                      size='mini'
                      danger
                      onClick={() => actionRow(record.key, 'delete')}>
                      删除
                    </Button>
                  </Space>
                )}
              />
            </Table>
          </span>
        );
      } else {
        return (
          <Empty />
        );
      }
  }
  const actionRow = (e, type) => {
    if (type === 'edit') {
      console.log('edit——id', e)
    } else if (type === 'delete') {
      console.log('delete——id', e)
    }
  } 
  return (
    <div>
      {renderUserMessage()}
    </div>
  )
}
export default TableDetail;

 效果

  •  新增用户,新建CreateModal.js,并在TableDetail.js插入CreateModal.js,通过showCreateModel控制CreateModal是否弹出。

TableDetail.js 

import CreateModal from './comp/CreateModal';

const [showCreateModel, setShowCreateModel] = useState(false)

const createModel = () => {
  return (
    <div>
      <CreateModal showCreateModel={showCreateModel} changeModal={isShowCreateModel}/>
    </div>
  )
}
const isShowCreateModel = (e) => {
  setShowCreateModel(e)
}

 CreateModal.js

import React from 'react';
import { Modal, Form, Input, InputNumber, Button, Radio, Checkbox, Row, Col } from 'antd';

const CreateModal = (props) => { 
  const { showCreateModel, changeModal } = props;
  const [form] = Form.useForm();

  const layout = {
    labelCol: {
      span: 6,
    },
    wrapperCol: {
      span: 14,
    },
  };
  const validateMessages = {
    required: '${label} 不能为空!',
    types: {
      number: '${label} is not a valid number!',
    },
    number: {
      range: '${label} 为 ${min}~${max}',
    },
  };
  const onFinish = (values) => {
    console.log(values);
    changeModal(false);
    form.resetFields();
  };

  const hideModal = (e) => {
    form.resetFields();
    changeModal(e)
  }
  return (
    <div>
        <Modal
          title="Modal"
          forceRender 
          visible={showCreateModel}
          onCancel={() => hideModal(false)}
          footer={[]}
        >
          <Form
            {...layout}
            form={form}
            name="nest-messages"
            onFinish={onFinish}
            validateMessages={validateMessages}>
            <Form.Item
              name={['user', 'name']}
              label="姓名"
              rules={[
                {
                  required: true,
                },
              ]}
            >
              <Input />
            </Form.Item>
            <Form.Item
              name={['user', 'tel']}
              label="联系电话"
              rules={[
                {
                  required: true,
                },
              ]}
            >
              <Input />
            </Form.Item>
            <Form.Item
              name={['user', 'age']}
              label="年龄"
              rules={[
                {
                  type: 'number',
                  min: 0,
                  max: 99,
                },
              ]}
            >
              <InputNumber />
            </Form.Item>
            <Form.Item name={['user', 'gender']} label="性别">
              <Radio.Group>
                <Radio value="男">男</Radio>
                <Radio value="女">女</Radio>
              </Radio.Group>
            </Form.Item>
            <Form.Item name={['user', 'role']} label="角色">
              <Radio.Group>
                <Radio value="user">user</Radio>
                <Radio value="admin">admin</Radio>
              </Radio.Group>
            </Form.Item>
            <Form.Item name={['user', 'tags']} label="标签">
              <Checkbox.Group>
              <Row>
                <Col span={12}>
                  <Checkbox
                    value="一级"
                    style={{ lineHeight: '32px' }}>
                    一级
                  </Checkbox>
                </Col>
                <Col span={12}>
                  <Checkbox
                    value="二级"
                    style={{ lineHeight: '32px' }}>
                    二级
                  </Checkbox>
                </Col>
              </Row>
              </Checkbox.Group>
            </Form.Item>
            <Form.Item wrapperCol={{ ...layout.wrapperCol, offset: 5 }}>
            <Button
              onClick={() => hideModal(false)}
              size='large'
              style={{
                width: '48%',
                marginRight: '4%'
              }}>
                取消
              </Button>
            <Button
              type="primary"
              htmlType="submit"
              size='large'
              style={{ width: '48%' }}>
                提交
              </Button>
            </Form.Item>
          </Form>
        </Modal>
    </div>
  )
}
export default CreateModal;

 效果

优化表格样式

TableDetail.css

.ant-table-thead > tr >th{
  color: white !important;
  background: #4371aa !important;
  font-weight: bolder !important;
  text-align: center !important;
}

.ant-table-thead > tr > th:first-child{
  border-radius: 30px 0px 0px 30px !important;
}

.ant-table-thead > tr > th:last-child{
  border-radius: 0px 30px 30px 0px !important;
}

.ant-table-tbody > tr > td {
  color: #4371aa !important;
  background: #3070b91c !important;
  font-weight: bold !important;
  text-align: center !important;
}

.ant-table-tbody > tr:hover{
  background: #1b518625 !important;
}

.ant-table-tbody > tr > td:first-child{
  border-radius: 30px 0px 0px 30px !important;
}

.ant-table-tbody > tr > td:last-child{
  border-radius: 0px 30px 30px 0px !important;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React 是一个用于构建用户界面的 JavaScript 库。它被 Facebook 开发,用于构建 Facebook 和 Instagram 等应用程序的用户界面。React 通过组件化的方式构建用户界面,使得代码更易于维护和复用。下面是一个简单的 React 入门指南: 1. 安装 React React 可以通过 NPM 安装,可以在命令行中执行以下命令来安装 React: ``` npm install react react-dom ``` 2. 创建 React 组件 在 React 中,一个组件就是一个 JavaScript 类。下面是一个简单的组件示例: ```javascript import React from 'react'; class HelloWorld extends React.Component { render() { return <div>Hello World!</div>; } } export default HelloWorld; ``` 这个组件只是简单地渲染一个 `Hello World!` 的文本。 3. 渲染组件 要在页面中渲染组件,需要使用 `ReactDOM.render()` 方法。下面是一个简单的示例: ```javascript import React from 'react'; import ReactDOM from 'react-dom'; import HelloWorld from './HelloWorld'; ReactDOM.render( <HelloWorld />, document.getElementById('root') ); ``` 这个示例中,我们首先导入了 `ReactDOM` 和 `HelloWorld` 组件,然后使用 `ReactDOM.render()` 方法将 `HelloWorld` 组件渲染到页面上。在这个示例中,我们将组件渲染到了一个 ID 为 `root` 的元素中。 这只是 React入门React 还有很多其他的概念和功能,比如 JSX、状态、生命周期等等。如果您想深入了解 React,可以查看 React 官方文档,里面有很多有用的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值