React入门第二章:用户管理功能实战入手(react入门实例教程)
Vue组件和React组件的区别
Vue组件是创建.vue
文件,通过vue-loader转换成js文件。
React组件是创建.jsx
文件,通过babel-loader转换成js文件。
Vue组件通过template
、script
、style
标签的形式区分模板、逻辑和样式
React组件直接在内部写逻辑,最后导出jsx
模板。
Vue支持在main.js
中直接全局引入组件库。
React在需要使用的地方手动引入组件。
Vue支持局部样式,style
标签添加scoped
属性
React需要使用CSS Modules
的方式使用局部样式
Vue通过v-if
、v-for
指令处理渲染内容
React通过js的if
、for
原生语法处理渲染内容
Vue11个生命周期钩子函数用于处理各种情况。
实例初始化之后:beforeCreate
实例创建完成后:created
挂载开始之前:beforeMount
实例被挂载后:mounted
DOM 被更新之前:beforeUpdate
DOM 更新完之后:updated
实例销毁之前:beforeDestroy
实例销毁之后:destroyed
缓存的组件激活时:activated
缓存的组件失活时:deactivated
捕获后代组件的错误时:errorCaptured
React也提供了几乎差不多的生命周期钩子函数
组件将要挂载时:componentWillMount
组件挂载完成时:componentDidMount
是否要更新数据时:shouldComponentUpdate
数据更新完成时:componentDidUpdate
当组件从DOM中移除时:componentWillUnmount
当抛出错误时:componentDidCatch
将要更新数据时:componentWillUpdate
即将废弃
父组件中改变了props传值时:componentWillReceiveProps
即将废弃
通过用户管理理解JSX和函数组件
学习最好的方式就是实战,什么都别说了,就是干!
jsx
JSX是一个 JavaScript 的语法扩展JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。JSX 可能会使人联想到模板语言,但它具有 JavaScript 的全部功能。
可以将JSX简单理解为模板和JS的结合,继承了JS的灵活性。
JSX绑定属性通过花括号绑定,Vue通过v-bind指令或冒号绑定属性。
关于JSX可以阅读React-JSX简介文档,两分钟就能上手。
用户列表
函数组件就是一个纯函数,返回JSX即可。
添加用户管理的列表组件并添加路由配置
// config/routes.js export default [ { path: '/access', name: '权限管理', routes: [ { path: '/access/user', name: '用户管理', component: './access/User' } ] }, ] // src/pages/access/User.jsx export default () => { return <div>用户管理</div> } 复制代码
检测页面是否正常显示。若不正常检查问题,
此处我出现问题,主要提前在函数外面定义了数据,删除后页不正常,通过删除.umi目录后重新启动后才正常,估计是缓存原因
使用pro-layout的PageContainer
和antd的Table
组件将页面完善。
import { PageContainer } from '@ant-design/pro-layout'; import { Table, Space, Button } from 'antd'; export default () => { const sexs = ['男', '女']; const columns = [ { dataIndex: 'id', title: 'ID' }, { dataIndex: 'name', title: '用户姓名' }, { dataIndex: 'sex', title: '性别', render: (text, record, index) => sexs[text] }, { dataIndex: 'age', title: '年龄' }, { dataIndex: 'action', title: '操作', width: 150, render: () => ( <Space size="middle"> <a>编辑</a> <a>详情</a> <a>删除</a> </Space> ), }, ]; const datas = [ { id: 1, name: '张三', age: 19, sex: 0 }, { id: 2, name: '李四', age: 22, sex: 1 }, ]; return ( <PageContainer title="用户管理" header={{ extra: [ <Button key="1" type="primary"> 创建用户 </Button>, ], }} > <Table columns={columns} dataSource={datas} rowKey="id" /> </PageContainer> ); }; 复制代码
columns中的render用于转换数据,和iView的render类似。
注意Table组件添加RowKey属性,Button组件的key属性。
否则控制台报错,这点和Vue的其他组件库不一样。
用户表单
我个人不喜欢把表单和列表写在一起,所以表单需要单独创建一个组件。正好熟悉一下函数式组件间传值
import React, { useImperativeHandle } from 'react'; import { Form, Input, InputNumber, Radio } from 'antd'; import { useEffect } from 'react'; export default React.forwardRef(({ data }, ref) => { const [form] = Form.useForm(); // 自定义暴露给父组件的实例值 useImperativeHandle(ref, () => ({ validate: form.validateFields, resetFields: form.resetFields, })); // 函数组件的生命周期 useEffect(() => { if (data && data.id) { form.setFieldsValue(data); } }); // JSX渲染 return ( <Form form={form} ref={ref}> <Form.Item name="name" label="姓名" rules={[{ required: true }]}> <Input placeholder="请输入用户姓名" /> </Form.Item> <Form.Item name="sex" label="性别" rules={[{ required: true }]}> <Radio.Group placeholder="请选择用户性别"> <Radio value={0}>男</Radio> <Radio value={1}>女</Radio> </Radio.Group> </Form.Item> <Form.Item name="age" label="年龄" rules={[{ required: true }]}> <InputNumber /> </Form.Item> </Form> ); }); 复制代码
React.forwardRef用于函数组件的实例暴露。由于表单组件是单独的组件,需要在父级组件获取子级组件的数据。
useEffect是React Hook方法之一 函数组件没有生命周期,Effect Hook可以让你在函数组件中执行副作用操作,类似生命周期。
列表事件触发表单组件
表单使用抽屉组件承载,通过列表页事件显示表单。
添加操作方法、Drawer抽屉数据对象和控制Drawer抽屉显示/隐藏的数据。
之前datas数据是静态的,表单添加/修改需要改变datas,datas也需要改为可修改的状态数据
import { useState } from 'react'; import { Table, Space, Button, Drawer } from 'antd'; export default () => { ... /** * 数据 */ const [datas, setDatas] = useState([ { id: 1, name: '张三', age: 19, sex: 0 }, { id: 2, name: '李四', age: 22, sex: 1 }, ]); // 抽屉控制 const [showDrawer, setShowDrawer] = useState(false); // 抽屉数据 const [drawerData, setDrawerData] = useState({}); /** * 操作 */ // 显示表单 const handleShowForm = (data) => { if (data) { setDrawerData(data); } setShowDrawer(true); }; // 关闭操作 const handleCancel = () => { setShowDrawer(false); setDrawerData({}); userForm.current.resetFields(); }; // 保存操作 const handleSave = async () => { const data = await userForm.current.validate(); if (drawerData.id) { const index = datas.findIndex((v) => v.id === drawerData.id); datas.splice(index, 1, { ...data, id: drawerData.id }); } else { datas.push({ ...data, id: datas.length + 1 }); } setDatas([...datas]); handleCancel(); }; /** * JSX渲染 */ return ( <PageContainer title="用户管理" header={{ extra: [<Button key="1" type="primary" onClick={handleShowForm}>创建用户</Button>], }} > <Table columns={columns} dataSource={datas} rowKey="id" /> <Drawer title="创建用户" width={500} maskClosable={false} visible={showDrawer} onClose={handleCancel} > <UserForm data={drawerData} ref={userForm} /> <Space size="middle"> <Button onClick={handleCancel}>关闭</Button> <Button type="primary" onClick={handleSave}>保存</Button> </Space> </Drawer> </PageContainer> ); } 复制代码
useState是React的hook的方法之一
函数组件是没有状态的,也就是说函数组件不会监听到数据的变化,而Hook就是为了解决这个问题而生的(暂时这么理解)
用法类似Vue中的store,状态不可更改,通过设置状态的方法更改状态。
注意const后面是数组的中括号[]
完善删除和详情操作
详情操作继续用Drawer展示,和表单类似,不再继续了。
删除操作用antd的Popconfirm组件实现拦截提示即可
... <Popconfirm title="您确定要删除当前数据么?" onConfirm={() => { handleRemove(record); }} > <a>删除</a> </Popconfirm> ... // 删除操作 const handleRemove = (data) => { const index = datas.findIndex((v) => v.id === data.id); datas.splice(index, 1); setDatas([...datas]); message.success('删除成功!'); }; 复制代码
结语
通过用户的增删改查操作,大致摸清楚了React的函数组件的实现方式。
通过使用Ant Design组件库,对React组件库有了基本的了解,同时熟悉了JSX语法。
拆分组件后理解了函数组件的ref获取实例的方式以及子组件控制暴露API的方式
初步了解了React Hook的使用方式和基本作用。
作者:ybc4652
链接:https://juejin.cn/post/7028765768170864647