1、AntDesign库的安装
// 使用npm或者yarn进行安装
# npm install antd -sava or yarn add antd
// 我们需要在index.js文件中引入全局的antd样式
import "antd/dist/antd.less";
// 直接在App.js中就可以直接使用组件了
考虑一个问题:Antd是否将一些没用的代码(组件或者逻辑代码)引入,造成包很大呢?
antd 官网有提到:antd 的JS 代码默认支持基于ES modules 的tree shaking,对于js部分,直接引入import { Button } from ‘antd’ 就会有按需加载的效果。
2、认识craco
2.1 使用的原因
- 上面的使用过程是无法对主题进行配置的,好像对主题等相关的高级特性进行配置,需要修改create-react-app 的默认配置。
- 如何修改create-react-app 的默认配置呢?
- 前面我们讲过,可以通过yarn run eject来暴露出来对应的配置信息进行修改。
- 但是对于webpack并不熟悉的人来说,直接修改CRA 的配置是否会给你的项目带来负担,甚至会增加项目的隐患和不稳定性呢?
- 所以,在项目开发中是不建议大家直接去修改CRA 的配置信息的
那么如何来进行修改默认配置呢?社区目前有两个比较常见的方案
第一步:安装craco:
# 安装依赖
yarn add @craco/craco
第二部:修改package.json文件
- 原本启动时,我们是通过react-scripts来管理的;
- 现在启动时,我们通过craco来管理:
- 修改package.json文件的启动代码: ```javascript “scripts”: {
- “start”: “react-scripts start”, // 读取craco.config.js配置文件里面的配置信息
- “build”: “react-scripts build”, // 需要删除的文件
- “test”: “react-scripts test”, // 需要删除的文件
- “start”: “craco start”,
- “build”: “craco build”,
- “test”: “craco test”, } ```
- 第三步:在根目录下创建craco.config.js文件用于修改默认配置
平时相关的配置可以再craco.config.js配置文件中进行书写,因为我们已经修改了package.json配置文件的命令,每次运行程序时程序都会先读取craco.config.js文件里面的配置。// 先创建配置文件 再对配置文件进行相应的配置
module.exports = {
// 配置文件
}
2.3 对antd组件库主题颜色的配置
1、因为antd组件库使用的是css预编译语言是less,我们可以借助社区的解决方案craco-less库来进行配置
安装craco-less库:
$ yarn add craco-less
修改craco.config.js配置文件的相关信息:
// 引入插件
const CracoLessPlugin = require('craco-less');
// 进行配置
module.exports = {
plugins: [
{
plugin: CracoLessPlugin,
options: [
lessLoaderOptions: {
lessOptions: {
modifyVars: { '@primary-color': '#1DA57A' },
javascriptEnabled: true,
}
}
]
}
]
}
// 修改引入的css文件
import "antd/dist/antd.css"
// 修改为
import "anrd/dist/antd.less"
2.4 修改项目的别名的配置文件
对craco.config.js配置文件进行配置:
const path = require('path');
const resolve = dir => path.resolve(__dirname, dir)
// 配置文件导出
modules.exports = {
// 别名的配置
webpack: {
alias: {
"@": resolve("src"), // 路径的拼接
"components": resolve("src/component") // 也是路径的拼接
}
}
}
// 以上的配置就算完成了
3、评论案例的设计与实现
功能描述:使用antd组件内的comment组件来实现评论的功能,以及删除评论。 案例采用模块化、组件化的设计完成的。
3.1 根组件App.js
# App.js
import React, { PureComponent } from 'react'
// 引入antd库的css样式
import 'antd/dist/antd.less'
// 时间的中文设置
import 'moment/locale/zh-cn'
// 引用评论组件 主组件
import Comment from '@/12_comment案例/Comment'
export default class App extends PureComponent {
render() {
return (
<div className="comment">
<Comment/>
</div>
)
}
}
3.2 评论整个组件结构-Comment
import React, { Component } from 'react'
// 引入子组件
import CommentInput from './CommentInput'
import CommentList from './CommentList'
export default class Comment extends Component {
constructor() {
super()
this.state = {
contentList: []
}
}
render() {
return (
<div style={{ width: '500px', padding: '20px', outline: '1px dashed red' }}>
<h2 style={{ textAlign: 'center' }}>评论区域</h2>
{
this.state.contentList.map((item, index) => {
return <CommentList
key={ item.id }
comment={ item }
deleteItem={ () => this.btnClick(index)}
>
</CommentList>
})
}
<CommentInput getContent={ list => this.getContentList(list) } />
</div>
)
}
getContentList(list) {
// 将子组件传递过来的数据 保存在父组件的state中 这里需要体现出数据的不可变性
this.setState({
contentList: [...this.state.contentList, list]
})
}
btnClick(index) {
const newContentList = [...this.state.contentList]
// 修改数组里面的元素
newContentList.splice(index, 1)
this.setState({
contentList: newContentList
})
}
}
3.3 输入组件-CommentInput
import React, { Component } from 'react'
import { Input, Button, message } from 'antd'
import moment from 'moment'
export default class CommentInput extends Component {
constructor() {
super()
this.state = {
content: ''
}
}
render() {
return (
<div>
<Input.TextArea rows={6} allowClear value={ this.state.content } onChange={e => this.handleChange(e) } />
<Button type='primary' style={{ marginTop: '15px'}} onClick={ () => this.getContent() }>添加评论</Button>
<Button type='primary' style={{ marginLeft: '15px' }} onClick={ () => this.handleCancle() }>重置</Button>
</div>
)
}
handleChange(event) {
// 取出输入框最新的值进行绑定 修改组件的状态
this.setState({
content: event.target.value
})
}
getContent() {
// 组装数据 给父组件进行传值
const commentObj = {
id: moment().valueOf(), // 使用时间戳作为id
avatar:'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii0xMS41IC0xMC4yMzE3NCAyMyAyMC40NjM0OCI+CiAgPHRpdGxlPlJlYWN0IExvZ288L3RpdGxlPgogIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSIyLjA1IiBmaWxsPSIjNjFkYWZiIi8+CiAgPGcgc3Ryb2tlPSIjNjFkYWZiIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiPgogICAgPGVsbGlwc2Ugcng9IjExIiByeT0iNC4yIi8+CiAgICA8ZWxsaXBzZSByeD0iMTEiIHJ5PSI0LjIiIHRyYW5zZm9ybT0icm90YXRlKDYwKSIvPgogICAgPGVsbGlwc2Ugcng9IjExIiByeT0iNC4yIiB0cmFuc2Zvcm09InJvdGF0ZSgxMjApIi8+CiAgPC9nPgo8L3N2Zz4K',
name: 'coderweiwei',
time: moment(),
content: this.state.content
}
// 子组件向父组件通信 调用父组件的方法
this.props.getContent(commentObj)
// 数据传向父组件以后 就可以清空输入框的值
this.setState({
content: ''
})
}
handleCancle() {
message.info('用于展示button按钮')
}
}
3.4 列表展示组件-CommentList
import React, { Component } from 'react'
import { Comment, Avatar, Tooltip, message } from 'antd'
import { DeleteOutlined } from '@ant-design/icons'
export default class CommentList extends Component {
render() {
const { name, avatar, content, time } = this.props.comment
return (
<Comment
author={ <a href="/#">{ name }</a> }
avatar={ <Avatar src={ avatar } alt={ name } /> }
content={ <p>{ content }</p> }
datetime={
<Tooltip title={ time.format('YYYY-MM-DD HH:mm:ss')}>
<span>{ time.fromNow()}</span>
</Tooltip>
}
actions={
[
<>
<span onClick={ () => this.removeItem() }><DeleteOutlined />删除</span>
<span onClick={ this.replay }>回复</span>
<span onClick={ () => this.handleLike()}>点赞</span>
</>
]
}
/>
)
}
replay() {
// 未绑定正确的this
message.info('该功能正在开发中!敬情期待!')
}
handleLike() {
// this指向组件的实例化对象 是正确的
message.info('你点赞了')
}
removeItem() {
// 父组件向子组件进行通信
this.props.deleteItem()
}
}
总结:总的来说,就是将评论组件拆分为两个小组件。一个是获取组件输入的内容,另外一个列表组件就是将获取的组件内容进行展示。输入组件将收集到的数据传递给父组件,父组件进行简单的循环便利,每一个小项的列表就是一条评论,我们可以将每一项的内容传递给详细的列表展示组件,这样的化我们的组件就全部展示出来了。