1、AntDesign库的安装

  1. // 使用npm或者yarn进行安装
  2. # npm install antd -sava or yarn add antd
  3. // 我们需要在index.js文件中引入全局的antd样式
  4. import "antd/dist/antd.less";
  5. // 直接在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 的配置信息的
  • 那么如何来进行修改默认配置呢?社区目前有两个比较常见的方案

    • react-app-rewired + customize-cra;(这个是antd早期推荐的方案)
    • craco;(目前antd推荐的方案)

      2.2 craco的使用步骤

  • 第一步:安装craco:

    1. # 安装依赖
    2. 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文件用于修改默认配置
    1. // 先创建配置文件 再对配置文件进行相应的配置
    2. module.exports = {
    3. // 配置文件
    4. }
    平时相关的配置可以再craco.config.js配置文件中进行书写,因为我们已经修改了package.json配置文件的命令,每次运行程序时程序都会先读取craco.config.js文件里面的配置。

2.3 对antd组件库主题颜色的配置

1、因为antd组件库使用的是css预编译语言是less,我们可以借助社区的解决方案craco-less库来进行配置
安装craco-less库:

  1. $ yarn add craco-less

修改craco.config.js配置文件的相关信息:

  1. // 引入插件
  2. const CracoLessPlugin = require('craco-less');
  3. // 进行配置
  4. module.exports = {
  5. plugins: [
  6. {
  7. plugin: CracoLessPlugin,
  8. options: [
  9. lessLoaderOptions: {
  10. lessOptions: {
  11. modifyVars: { '@primary-color': '#1DA57A' },
  12. javascriptEnabled: true,
  13. }
  14. }
  15. ]
  16. }
  17. ]
  18. }
  19. // 修改引入的css文件
  20. import "antd/dist/antd.css"
  21. // 修改为
  22. import "anrd/dist/antd.less"

2.4 修改项目的别名的配置文件

对craco.config.js配置文件进行配置:

  1. const path = require('path');
  2. const resolve = dir => path.resolve(__dirname, dir)
  3. // 配置文件导出
  4. modules.exports = {
  5. // 别名的配置
  6. webpack: {
  7. alias: {
  8. "@": resolve("src"), // 路径的拼接
  9. "components": resolve("src/component") // 也是路径的拼接
  10. }
  11. }
  12. }
  13. // 以上的配置就算完成了

3、评论案例的设计与实现

功能描述:使用antd组件内的comment组件来实现评论的功能,以及删除评论。 案例采用模块化、组件化的设计完成的。

3.1 根组件App.js

  1. # App.js
  2. import React, { PureComponent } from 'react'
  3. // 引入antd库的css样式
  4. import 'antd/dist/antd.less'
  5. // 时间的中文设置
  6. import 'moment/locale/zh-cn'
  7. // 引用评论组件 主组件
  8. import Comment from '@/12_comment案例/Comment'
  9. export default class App extends PureComponent {
  10. render() {
  11. return (
  12. <div className="comment">
  13. <Comment/>
  14. </div>
  15. )
  16. }
  17. }

3.2 评论整个组件结构-Comment

  1. import React, { Component } from 'react'
  2. // 引入子组件
  3. import CommentInput from './CommentInput'
  4. import CommentList from './CommentList'
  5. export default class Comment extends Component {
  6. constructor() {
  7. super()
  8. this.state = {
  9. contentList: []
  10. }
  11. }
  12. render() {
  13. return (
  14. <div style={{ width: '500px', padding: '20px', outline: '1px dashed red' }}>
  15. <h2 style={{ textAlign: 'center' }}>评论区域</h2>
  16. {
  17. this.state.contentList.map((item, index) => {
  18. return <CommentList
  19. key={ item.id }
  20. comment={ item }
  21. deleteItem={ () => this.btnClick(index)}
  22. >
  23. </CommentList>
  24. })
  25. }
  26. <CommentInput getContent={ list => this.getContentList(list) } />
  27. </div>
  28. )
  29. }
  30. getContentList(list) {
  31. // 将子组件传递过来的数据 保存在父组件的state中 这里需要体现出数据的不可变性
  32. this.setState({
  33. contentList: [...this.state.contentList, list]
  34. })
  35. }
  36. btnClick(index) {
  37. const newContentList = [...this.state.contentList]
  38. // 修改数组里面的元素
  39. newContentList.splice(index, 1)
  40. this.setState({
  41. contentList: newContentList
  42. })
  43. }
  44. }

3.3 输入组件-CommentInput

  1. import React, { Component } from 'react'
  2. import { Input, Button, message } from 'antd'
  3. import moment from 'moment'
  4. export default class CommentInput extends Component {
  5. constructor() {
  6. super()
  7. this.state = {
  8. content: ''
  9. }
  10. }
  11. render() {
  12. return (
  13. <div>
  14. <Input.TextArea rows={6} allowClear value={ this.state.content } onChange={e => this.handleChange(e) } />
  15. <Button type='primary' style={{ marginTop: '15px'}} onClick={ () => this.getContent() }>添加评论</Button>
  16. <Button type='primary' style={{ marginLeft: '15px' }} onClick={ () => this.handleCancle() }>重置</Button>
  17. </div>
  18. )
  19. }
  20. handleChange(event) {
  21. // 取出输入框最新的值进行绑定 修改组件的状态
  22. this.setState({
  23. content: event.target.value
  24. })
  25. }
  26. getContent() {
  27. // 组装数据 给父组件进行传值
  28. const commentObj = {
  29. id: moment().valueOf(), // 使用时间戳作为id
  30. avatar:'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii0xMS41IC0xMC4yMzE3NCAyMyAyMC40NjM0OCI+CiAgPHRpdGxlPlJlYWN0IExvZ288L3RpdGxlPgogIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSIyLjA1IiBmaWxsPSIjNjFkYWZiIi8+CiAgPGcgc3Ryb2tlPSIjNjFkYWZiIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiPgogICAgPGVsbGlwc2Ugcng9IjExIiByeT0iNC4yIi8+CiAgICA8ZWxsaXBzZSByeD0iMTEiIHJ5PSI0LjIiIHRyYW5zZm9ybT0icm90YXRlKDYwKSIvPgogICAgPGVsbGlwc2Ugcng9IjExIiByeT0iNC4yIiB0cmFuc2Zvcm09InJvdGF0ZSgxMjApIi8+CiAgPC9nPgo8L3N2Zz4K',
  31. name: 'coderweiwei',
  32. time: moment(),
  33. content: this.state.content
  34. }
  35. // 子组件向父组件通信 调用父组件的方法
  36. this.props.getContent(commentObj)
  37. // 数据传向父组件以后 就可以清空输入框的值
  38. this.setState({
  39. content: ''
  40. })
  41. }
  42. handleCancle() {
  43. message.info('用于展示button按钮')
  44. }
  45. }

3.4 列表展示组件-CommentList

  1. import React, { Component } from 'react'
  2. import { Comment, Avatar, Tooltip, message } from 'antd'
  3. import { DeleteOutlined } from '@ant-design/icons'
  4. export default class CommentList extends Component {
  5. render() {
  6. const { name, avatar, content, time } = this.props.comment
  7. return (
  8. <Comment
  9. author={ <a href="/#">{ name }</a> }
  10. avatar={ <Avatar src={ avatar } alt={ name } /> }
  11. content={ <p>{ content }</p> }
  12. datetime={
  13. <Tooltip title={ time.format('YYYY-MM-DD HH:mm:ss')}>
  14. <span>{ time.fromNow()}</span>
  15. </Tooltip>
  16. }
  17. actions={
  18. [
  19. <>
  20. <span onClick={ () => this.removeItem() }><DeleteOutlined />删除</span>
  21. <span onClick={ this.replay }>回复</span>
  22. <span onClick={ () => this.handleLike()}>点赞</span>
  23. </>
  24. ]
  25. }
  26. />
  27. )
  28. }
  29. replay() {
  30. // 未绑定正确的this
  31. message.info('该功能正在开发中!敬情期待!')
  32. }
  33. handleLike() {
  34. // this指向组件的实例化对象 是正确的
  35. message.info('你点赞了')
  36. }
  37. removeItem() {
  38. // 父组件向子组件进行通信
  39. this.props.deleteItem()
  40. }
  41. }

总结:总的来说,就是将评论组件拆分为两个小组件。一个是获取组件输入的内容,另外一个列表组件就是将获取的组件内容进行展示。输入组件将收集到的数据传递给父组件,父组件进行简单的循环便利,每一个小项的列表就是一条评论,我们可以将每一项的内容传递给详细的列表展示组件,这样的化我们的组件就全部展示出来了。