01-发布文章-页面结构
完成页面基本结构搭建
大致步骤:
- 使用 Card 组件搭建布局容器和面包屑
- 使用 Form 组件表单
- 准备 标题选项 和 频道选项
核心代码:
Artilce/index.jsx
import { Card, Breadcrumb, Form, Select, Button, Input } from ‘antd’
import { getChannels } from “@/store/actions/article”;
import { useDispatch, useSelector } from “react-redux”;
import { Link } from ‘react-router-dom’
import styles from “./index.module.scss”;
const Publish = () => {
// 频道数据
const channels = useSelector((state) => state.article.channels);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getChannels());
}, [dispatch]);
return (
首页
内容管理
}
>
name=”title”
>
name=”channel_id”
>
)
}
Artilce/index.module.scss
.root {
padding: 24px;
:global {
.ql-editor {
min-height: 200px;
}
}
}
02-发布文章-频道组件封装
封装频道组件逻辑与UI,且在Form组件中使用
大致步骤:
- 提取频道组件自身功能
- 实现value赋值,onChange改值,也就是父子通讯
具体代码:
- 封装 components/Channel.jsx
// 需求:
// 1. 实现频道本身的功能,获取频道数据,展示频道选项,可以选择频道
// 2. 实现传入频道ID显示对应频道,自己更改频道的时候需要把更改的频道ID传给父组件
// 3. 而且现在是在form表单上使用,要符合form表单的要求,value赋值,onChange改值
import { useDispatch, useSelector } from “react-redux”;
import { useEffect } from “react”;
import { getChannels } from “@/store/actions”;
import { Select } from “antd”;
const Channel = ({ width, value, onChange }) => {
// 频道相关逻辑
const dispatch = useDispatch();
useEffect(() => {
dispatch(getChannels());
}, [dispatch]);
const { channels } = useSelector((state) => state.article);
return (
- 使用 Article/index.jsx
- 使用 Publish/index.jsx
03-发布文章-处理封面
完成封面类型切换,完成封面图上传。
大致步骤:
- 完成封面类型渲染和切换
- 完成封图上传,根据封面类型限制上传的图片张数
- 切换封面的时候重置数据
具体代码:Artilce/index.jsx
import {
Radio,
Upload,
} from “antd”;
import { useState } from “react”;
- 完成封面类型渲染和切换
const [type, setType] = useState(1);
const onTypeChange = (e) => {
setType(e.target.value);
};
{/ 一个FormItem只能有一个元素 /}
{/ 这个位置放Upload组件 /}
- 完成封图上传,根据封面类型限制上传的图片张数
const [fileList, setFileList] = useState([]);
const onUploadChange = ({ fileList }) => {
setFileList(fileList);
};
{type > 0 ? (
listType=”picture-card”
action=”http://geek.itheima.net/v1_0/upload“
fileList={fileList}
onPreview={() => {}}
onChange={onUploadChange}
>
{fileList.length < type ? (
) : null}
) : null}
- 切换封面的时候重置数据
const onTypeChange = (e) => {
setType(e.target.value);
+ setFileList([]);
};
04-发布文章-富文本编辑器
使用react-quill富文本编辑器完成文章内容选项
大致步骤:
- 安装导入 react-quill 组件
- 使用 react-quill 组件
- 处理默认值问题
- 处理宽度
核心代码:
- 安装导入 react-quill 组件
npm i react-quill
# or
yarn add react-quill
+import ReactQuill from “react-quill”;
+import “react-quill/dist/quill.snow.css”;
import styles from “./index.module.scss”;
- 使用 react-quill 组件
name=”content”
initialValue=””
>
- 处理默认值问题
name=”content”
+ initialValue=””
>
- 处理宽度
name=”content”
+ wrapperCol={{ span: 16 }}
initialValue=””
>
05-发布文章-添加校验
给标题,频道,内容必填校验,提交表单校验封面类和图片张数
大致步骤:
- 标题,频道,内容必填校验
- 提交表单校验封面类和图片张数
核心代码:
- 标题,频道,内容必填校验
name=”title”
+ rules={[{ required: true, message: “请输入文章标题” }]}
>
name=”channel_id”
+ rules={[{ required: true, message: “请选择所属频道” }]}
>
name=”content”
wrapperCol={{ span: 16 }}
+ rules={[{ required: true, message: “请输入文章内容” }]}
initialValue=””
>
- 提交表单校验封面类和图片张数
- 点击发布文章,需要重置数据
useEffect(() => {
const setFormData = async () => {
if (params.id) {
const { title, cover, content, channel_id } = await dispatch(
getArticle(params.id)
);
form.setFieldsValue({ title, content, channel_id });
setType(cover.type);
setFileList(cover.images.map((item) => ({ url: item })));
+ } else {
+ setType(1);
+ setFileList([]);
+ form.resetFields();
+ }
};
setFormData();
+ }, [dispatch, form, params]);
- 提交修改
const onFinish = async (values) => {
if (type !== fileList.length) {
return message.warning(“请按照选择的封面类型上传图片”);
}
const data = {
…values,
cover: {
type,
+ images: fileList.map((item) => {
+ return item?.response?.data?.url || item.url;
+ }),
},
};
+ if (params.id) {
+ // 编辑
+ data.id = params.id
+ await dispatch(editArticle(data));
+ } else {
// 添加
await dispatch(addArticle(data));
+ }
history.push(“/article”);
};
08-发布文章-存入草稿
实现存入草稿功能
大致步骤:
- 改造 onFinish 函数支持,存入草稿调用
- 添加存入草稿按钮,添加处理函数
核心代码:
- 改造 onFinish 函数支持,存入草稿调用
- const onFinish = async (values, draft = false) => {
if (type !== fileList.length) {
return message.warning(“请按照选择的封面类型上传图片”);
}
const data = {
…values,
cover: {
type,
images: fileList.map((item) => {
return item?.response?.data?.url || item.url;
}),
},
};
if (params.id) {
// 编辑
data.id = params.id
+ await dispatch(editArticle(data, draft));
} else {
// 添加
+ await dispatch(addArticle(data, draft));
}
+ message.success(‘保存成功’)
history.push(“/article”);
};
- 添加存入草稿按钮,添加处理函数
+
const saveDarft = async () => {
try {
const values = await form.validateFields()
onFinish(values, true)
}catch(e){}
}
2021/12/30 23:22:54