• React技术栈 --》组件对比和评论列表案例 ## Day4


    文章目录

    一、两种组件创建的方式的对比

    二、React创建组件 实现评论列表

    实现评论列表的HTML骨架

    实现评论列表的CSS样式

    配置CSS样式表

    CSS样式表的作用域冲突问题


    前情回顾:

    React技术栈 --》 JSX语法书写JS和React创建组件 ## Day3_亦世凡华、的博客-CSDN博客

    一、两种组件创建的方式的对比

            通俗来讲:用构造函数function创造出来的组件:叫做“无状态组件”;用class关键字创建出来的组件:叫做“有状态组件”。那么两者的区别是什么?有状态组件和无状态组件之间的本质区别就是:有无state属性和有无生命周期函数。

    1. //class关键字创建组件
    2. class People extends React.Component{
    3. constructor(){
    4. super()
    5. this.state = { //相当于Vue中的data(){ return{ } }
    6. //在class创建的组件中,this.state 上的数据,都是可读可写的
    7. mvg:'大家好,我是People的组件'
    8. }
    9. }
    10. render(){
    11. return <div>
    12. <h3>{this.state.mvg}</h3>
    13. </div>
    14. }
    15. }

    什么情况下使用有状态组件?什么情况下使用无状态组件?

            如果一个组件需要有自己的私有数据,则推荐class创建的有状态组件;如果一个组件不需要有自己的私有数据,则推荐用function创建的无状态组件。React官方说:无状态组件由于没有自己的state和生命周期函数,所以运行效率会比有状态组件稍高一些。

    组件中的props和state/data之间的区别

            props中的数据都是外界传递过来的,数据都是只读的;不能重新赋值;  state/data中的数据,都是组件私有的;(通过Ajax获取回来的数据,一般都是私有数据),数据都是可读可写的

    注意

    使用class关键字创建的组件,有自己的 私有数据 和 生命周期函数;使用function创建的组件,只有props,没有自己的私有数据和生命周期函数。          

    二、React创建组件 实现评论列表

    实现评论列表的HTML骨架

            根据以上学习内容,现在实现一个简单的小案例,将评论列表和评论内容抽离出来封装到俩个单独的jsx文件夹下

    1. //ComponmentList.jsx文件
    2. import React from "react"
    3. // 导入 评论项 子组件
    4. import CmtItem from '@/components/CmtItem' //使用@更加方便的移动导入的文件路径
    5. // 使用class关键字定义父组件
    6. export default class ComponmentList extends React.Component{
    7. constructor(){
    8. super(),
    9. this.state = {
    10. ComponmentList:[//评论列表数据
    11. {id:1,user:'张三',content:'我姓张'},
    12. {id:2,user:'李四',content:'我姓李'},
    13. {id:3,user:'王五',content:'我姓王'},
    14. {id:4,user:'赵六',content:'我姓赵'},
    15. {id:5,user:'田七',content:'我姓田'},
    16. ]
    17. }
    18. }
    19. // 渲染当前组件所对应的虚拟DOM
    20. render(){
    21. return <div>
    22. <h1>这是评论列表组件</h1>
    23. {this.state.ComponmentList.map(item=> <CmtItem {...item} key={item.id}></CmtItem> )}
    24. </div>
    25. }
    26. }
    1. //CmtItem.jsx文件
    2. import React from "react"
    3. //使用 function 构造函数,定义普通的无状态组件
    4. export default function CmtItem(props){
    5. return <div>
    6. <h1>评论人:{props.user}</h1>
    7. <p>评论内容:{props.content}</p>
    8. </div>
    9. }

    现在我们导入评论内容的子组件,将创建好的虚拟DOM渲染到页面上,大功告成!

    1. //1.导入包
    2. import React from 'react'
    3. import ReactDOM from 'react-dom'
    4. import ComponmentList from '@/components/ComponmentList'
    5. ReactDOM.render(<div>
    6. <ComponmentList></ComponmentList>
    7. </div>,document.getElementById('app'))

    实现评论列表的CSS样式

            在正常项目中我们书写CSS样式的方式很简单,能不能在React中使用呢?试一试

    我们正常书写内联样式的方式就是这样,看看浏览器结果 。。。。报错?

            报错并不可怕,关键你有理解报错的原因和处理报错的能力。报错提醒我们在JSX中书写行内样式的不能上string,并且给我提供了书写的例子,看for example,两个大括号的含义分别是:外层的大括号表示的是要书写JSX,里面的那层表示要书写的是样式对象。

    注意点:在行内样式中,如果是数值类型的样式则可以不用引号包裹如果是字符串类型的样式必须使用引号包裹

    <h1 style={{color:'red',fontSize:'35px',zIndex:4}}>这是评论列表组件</h1>

    解决样式格式书写之后,可以正式对评论列表进行编辑了,如下所示:

    1. // 渲染当前组件所对应的虚拟DOM
    2. render(){
    3. return <div>
    4. {/* 在JSX中书写行内样式的格式为 style={{color:'red'}} */}
    5. {/* 在行内样式中,如果是数值类型的样式,则可以不用引号包裹,如果是字符串类型的样式值,必须使用引号包裹 */}
    6. <h1 style={{color:'red',fontSize:'35px',zIndex:4,fontWeight:200,textAlign:'center'}}>这是评论列表组件</h1>
    7. {this.state.ComponmentList.map(item=> <CmtItem {...item} key={item.id}></CmtItem> )}
    8. </div>
    9. }
    1. //使用 function 构造函数,定义普通的无状态组件
    2. export default function CmtItem(props){
    3. return <div style={{border:'1px dashed #ccc',margin:'10px',padding:'10px',boxShadow:'0 0 10px #ccc'}}>
    4. <h1 style={{fontSize:'14px'}}>评论人:{props.user}</h1>
    5. <p style={{fontSize:'12px '}}>评论内容:{props.content}</p>
    6. </div>
    7. }

    相信大家都理解,在内联样式中编写css,代码太长影响代码的整体的美观。在JSX中如何处理?

    配置CSS样式表

    1. //第一层封装:将样式对象和UI结构分离
    2. const CmtItemdiv = {border:'1px dashed #ccc',margin:'10px',padding:'10px',boxShadow:'0 0 10px #ccc'}
    3. const CmtItemh1 = {fontSize:'14px'}
    4. const CmtItemp = {fontSize:'12px '}
    5. //使用 function 构造函数,定义普通的无状态组件
    6. export default function CmtItem(props){
    7. return <div style={CmtItemdiv}>
    8. <h1 style={CmtItemh1}>评论人:{props.user}</h1>
    9. <p style={CmtItemp}>评论内容:{props.content}</p>
    10. </div>
    11. }
    1. //第二层封装:合并成一个大的样式表对象
    2. const style = {
    3. item:{border:'1px dashed #ccc',margin:'10px',padding:'10px',boxShadow:'0 0 10px #ccc'},
    4. user:{fontSize:'14px'},
    5. content:{fontSize:'12px '}
    6. }
    7. //使用 function 构造函数,定义普通的无状态组件
    8. export default function CmtItem(props){
    9. return <div style={style.item}>
    10. <h1 style={style.user}>评论人:{props.user}</h1>
    11. <p style={style.content}>评论内容:{props.content}</p>
    12. </div>
    13. }
    1. //第三层封装:抽离为单独的样式表模块
    2. //举例:将style封装在src下components文件夹下创建的style.js文件里
    3. export default {
    4. item:{border:'1px dashed #ccc',margin:'10px',padding:'10px',boxShadow:'0 0 10px #ccc'},
    5. user:{fontSize:'14px'},
    6. content:{fontSize:'12px '}
    7. }
    8. //需要style的文件下导入以下命令即可
    9. //import style from '@/components/style.js'

    虽然将css抽离到 .js 文件,但还是有点毛病,正常我们书写css的时候,不是将css写入 .css文件中的吗?这样书写css样式才简单明洁,我们可以创建一个css文件夹,如果文件需要样式,我们可以将样式进行导入吗?可以的

    在src新建css文件夹,写入格式导入需要样式的组件文件夹中,出现报错,为什么?

    import cssobj from '@/css/ComponmentList.css'

    提示:因为webpack默认处理不了后缀名为css的文件,想处理的话必须加loader,所以我们安装

    新建终端或者拆分终端执行:安装完成后配置webpack.config.js的第三方模块

    cnpm i style-loader css-loader -D

    配置完成后,新建终端再次执行一次打包 npm run dev 没有报错说明引入css文件成功。

    举个例子吧, 在css文件中书写代码如下

    1. .title{
    2. color: red;
    3. }

    直接调用css样式即可,如下图,成功

    CSS样式表的作用域冲突问题

    看到这,大家有点疑惑了,正常我们导入文件的时候 import 文件路径 之前要把文件暴露出来,export default 但是 css是不支持这个语法的所以我们要导入一个空对象来接收。

    import一个对象来接收,然后给出一个路径,我们可以看一下这个对象的内容是什么

    1. //导入组件需要的样式表
    2. import cssobj from '@/css/ComponmentList.css'
    3. console.log(cssobj);

    注意:直接导入的样式表,默认是在全局上,整个项目都生效的!因为样式表是没有模块作用域的

    现在配置webpack.config.js

    1. module:{//所有第三方 模块的配置规则
    2. rules:[//第三方匹配规则
    3. {test: /\.js|jsx$/,use: 'babel-loader',exclude: /node_modules/},
    4. {
    5. test: /\.css$/,
    6. use: [
    7. {
    8. loader: 'style-loader'
    9. },
    10. {
    11. loader: 'css-loader',
    12. options: {
    13. importLoaders: 1,
    14. modules: {
    15. localIdentName: '[name]__[local]___[hash:base64:5]'
    16. }
    17. }
    18. }
    19. ]
    20. }
    21. ]
    22. },

    一开始正常配置出现了ValidationError: Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.这种问题,采用上图的方法解决,css-loader 选项的语法在 3.0.0 版中已更改。

    现在在来看我们导入的cssobj已经不在是undefined已经是一个有具体属性的一个对象了。

    1. .title{
    2. color: blue;
    3. }
    4. /* 如上文,控制台没有h1的原因,css模块化只针对类选择器和Id选择器,不会对标签选择器模块化 */
    5. h1{
    6. font-style: italic;
    7. }

    现在在需要的组件中,import导入样式表,并接收模块化的CSS对象

    import cssobj from '@/...../文件名.css'

    在需要的HTML标签上,使用className指定模块化的样式:例如

    <h1 className={cssobj.title}>这是评论列表组件</h1>

    当然也可以使用localIdentName自定义生成的类名格式

    嗯~   ,  差不多就这些了,剩下的内容下期在补充。

    原创不易,呜呜~,看到这还不点赞加收藏?

  • 相关阅读:
    SpringBoot+Vue实现前后端分离的学生选课系统
    淘宝/天猫API接口,item_get_pro - 获得淘宝商品详情高级版
    网络基础入门:数据通信与网络基础
    [Unity] GPU动画实现(二)——网格合并
    一站式BI解决方案:从数据采集到处理分析,全面满足决策支持需求
    SpreadJS V15.0 Update2 新特性一览
    centos7篇---安装nvidia-docker
    ROS常用的命令
    XSS challenges绕过防护策略进行 XSS 注入
    Mybatis 数据源 池化和非池化的实现
  • 原文地址:https://blog.csdn.net/qq_53123067/article/details/125389026