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.jsimport 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 <CommentListkey={ 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(), // 使用时间戳作为idavatar:'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.commentreturn (<Commentauthor={ <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() {// 未绑定正确的thismessage.info('该功能正在开发中!敬情期待!')}handleLike() {// this指向组件的实例化对象 是正确的message.info('你点赞了')}removeItem() {// 父组件向子组件进行通信this.props.deleteItem()}}
总结:总的来说,就是将评论组件拆分为两个小组件。一个是获取组件输入的内容,另外一个列表组件就是将获取的组件内容进行展示。输入组件将收集到的数据传递给父组件,父组件进行简单的循环便利,每一个小项的列表就是一条评论,我们可以将每一项的内容传递给详细的列表展示组件,这样的化我们的组件就全部展示出来了。
