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的使用方式和基本作用。