React学习笔记

1).React核心概念

  • 虚拟DOM(Virtual Document Object Model)
    假如存在如下的Html结构,在js中可以获取到对应的DOM对象,因为JS中的DOM映射机制,可以通过操作js中的DOM对象来完成对页面的重排或重绘。但是DOM的操作成本是比较高的,所以引入虚拟DOM的概念。`所谓虚拟DOM就是与真实的DOM对象一一对应的普通JS对象
<div id="div1" style="background:red">
  Hello 简书!
  <p id="p1">可以在这里做笔记哦</p>
</div>
var vDom={
    id:"div1",
    style:"background:red",
    children:[
        "Hello 简书!",
        {
            id:"p1",
            children:["可以在这里做笔记哦"]
        }
   ]
}
  • Diff算法(分以下三步)
    • tree diff:新旧两颗DOM树,逐层对比的过程就是Tree Diff;当整颗DOM树对比完毕,则可以保证所有需要更新的元素必然可以找到。
    • component diff:对于组件化开发,DOM树中的每个层级都是各种的组建,在进行Tree Diff的时候,每一层中,组件级别的对比,叫做Component Diff

    1.如果对比前后,组建的类型相同,则暂时认为此组件不需要被更新
    2.如果对比前后,组建的类型不同,则需要移除旧的组建,创建新组建并追加到页面上。

    • element diff:在进行组建对比的时候,如果两个组建类型相同,则需要进行元素级别的对比,叫做Element Diff

2).使用webpack4.x构建项目

  • 1.初始化项目,创建一个目录,在根目录下运行npm init。(npm init -y快速初始化项目)
  • 2.在项目根目录创建src源代码目录和dist产品目录
  • 3.在src目录下创建一个index.html以及index.js入口文件(这里填写自己的js代码)
  • 4.安装webpack,npm i webpack --save-dev(在当前目录下安装),webpack默认只能打包处理.js文件,其他格式的需要配置第三方loader规则,webpack4.x具有约定大于配置的概念:目的是为了尽量减少配置文件的体积
    • 默认约定了打包的入口文件是src/index.js
    • 打包的输出文件时dist/main.js
  • 5.安装webpack-cli,在package.json的script添加编译命令"build":"webpack"
  • 6.在根目录下创建webpack.config.js文件,在webpack.config.js中指定mode
    module.exports = {
     mode: 'production' //or production
    };
    
  • 5.设置打包命令,在根目录package.jsonscripts节点添加"build": "webpack",就可以终端运行npm run build来打包代码了,可以看到在dist下有一个main.js的输出文件
  • 6.运行npm i webpack-dev-server --save-dev安装webpack-dev-server
  • 7.设置编译发布命令,在根目录package.jsonscripts节点添加"dev": "webpack-dev-server",就可以通过执行npm run dev命令来将网站托管在localhost的端口上,并且代码修改可以及时反映在浏览器中而不用执行编译脚本

    "dev": "webpack-dev-server --open chrome --host 127.0.0.1 --port 3000 --hot"
    //编译发布 在浏览器中打开 设置host 设置port 热替换

  • 8.添加js引用,在src/index.html添加对/main.js的引用

    webpack-dev-server打包好的main.js是托管在内存中的(避免频繁ctrl+s频繁编译),所以在磁盘的根目录中看不到,但是可以认为,在项目根目录下有一个看不见的main.js

3).在项目中使用React

  • 1.安装React包,运行npm i react react-dom --save(--save or -S在开发/生产都要用的的安装包)
    • react:专门用于创建组件和虚拟DOM的,同时维护组件的生命周期
    • react-dom:专门进行DOM操作的,主要的应用场景,就是ReactDOM.render()
  • 2.在index.html页面中,创建react渲染虚拟DOM的容器
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>home page</title>
    </head>
    <body>
        <!-- React容器   虚拟DOM在这里渲染 -->
        <div id="app"></div>
    </body>
    <!-- 切记:这里不可以把main.js在head中引用,因为这时这是body还没有加载,但是在 
    js中react已经用到了app容器 -->
    <script src="/main.js"></script>
    </html>
    
  • 3.在入口文件index.js中导入包、创建虚拟DOM元素、使用ReactDOM将虚拟DOM元素渲染到页面容器中
    //1.引入React包,以下两个react包导入的时候必须用以下两个名字接收
    import React from 'react'  //创建组件、虚拟DOM元素、生命周期
    import ReactDOM from 'react-dom'  //在页面渲染创建好的组件和虚拟DOM
    
    //2.创建虚拟DOM元素
    //param1:字符串 创建的元素名称  
    //param2:对象或null 表示当前这个DOM元素的属性  
    //param…:子节点  (其他若干参数)
    const myh1 = React.createElement('h1',{id:'myh1',title:'this is a h1'},'this is a h1 
    element') //<h1 id='myh1' title='this is a h1'>this is a h1 element</h1> 
    
    //3.使用ReactDOM把虚拟DOM渲染到页面上
    //param1:要渲染的虚拟DOM元素
    //param2:指定一个DOM元素,作为渲染虚拟DOM的容器
    ReactDOM.render(myh1,document.getElementById('app'))
    
  • 4.启用JSX语法(符合XML规范的js语法,类似与HTML)
    • 安装babel插件:
      npm i babel-core babel-loader babel-plugin-transform-runtime --save-dev
      npm i babel-preset-env babel-preset-stage-0 --save-dev
    • 安装能够识别JSX语法的包:npm i babel-preset-react -D
    • 在项目根目录添加.babelrc配置文件,该文件为JSON格式
      {
          "presets":["env","stage-0","react"],
          "plugins":["transform-runtime"]
      }
      
    • 在webpack配置文件中,配置babel-loader对jsx语法的解析规则
      //webpack.config.js
      module.exports = {
        mode: 'development',
        module:{//配置loader 所有第三方模块的配置规则
            rules:[
                {test:/\.js|jsx$/,use:'babel-loader',exclude:/node_modules/}
            ]
        }
      };
      

      在JSX语法区域内,如果需要写JS表达式,则需要把JS代码写在{}中

4).React组件的两种创建方式

  • 1.构造函数方式
    • 组件如果需要接收外界的数据,需要在构造函数列表中使用props来接收,props就相当于DOM元素的属性一般赋值。
    • 在一个组件中,必须要一个返回值,这个返回值是一个合法的JSX虚拟DOM元素,如果return null,则表示此组件是空的.
    • props是只读的,props需要用形参接收。
    • 组件的首字母必须大写
    function Hell(props){
        return <div>{{props.name}}</div>
    }
    ReactDOM.render(<div>
      <Hello name='kerry'></Hello>
    </div>,document.getElementById('app'))
    
  • 2.Class方式
    • 使用class定义组件,必须让组件继承自React.Component
    • 组件内部必须有render函数,render函数必须返回合法的JSX虚拟DOM结构
    • 最基本的组件结构:
    • props是只读的,在class中可以通过this.props使用
    • 有自己的私有数据state,class内部自身维护的可读写的数据,不通于props是通过外界传递而来
    class 组件名称 extends React.Component{
      constructor(){
        super();
        this.state={}
      }
      render(){
        return <div>{this.props.name}</div>
      }
    }
    
  • 3.异同
    • 使用class创建的组件,有自己的私有数据state和生命周期函数,叫做“有状态组件
    • function创建的组件,只有props,没有自己的私有数据和生命周期函数,叫做“无状态组件
    • 有状态组件与无状态组件的本质区别是有无state

5).React中的元素样式

React中的元素样式属性名也是style,但是不接收字符串,而是以双层大括号包裹,外层大括号表示在JSX中的JS代码,内层大括号表示一个对象。且样式属性对象的key必须是小写字母开头的驼峰写法

  • 1.内联样式

    function ItemComp(props){
        //1.直接将样式写在元素内
        // return <li style={{color:'red',txetAlign:'center',width:'60%'}}>
        //     <span style={{fontSize:'14px'}}>id:{props.id}</span>
        //     <span style={{float:'right',display:'inline-block'}}>code:{props.code}</span>
        // </li>;
        //2.将样式封装成对象,也可以抽出到一个单独的js文件中然后import
        const styles={
            li:{color:'red',txetAlign:'center',width:'60%'},
            spanId:{fontSize:'14px'},
            spanCode:{float:'right',display:'inline-block'}
        }
        return <li style={styles.li}>
            <span style={styles.spanId}>id:{props.id}</span>
            <span style={styles.spanCode}>code:{props.code}</span>
        </li>;
      }
    
  • 2.外联样式(样式表)

    • 2.1 安装样式相关的包,运行npm i style-loader css-loader -D
    • 2.2 webpack.config.js的module的rules节点配置cssloader
    let path=require('path')
    module.exports = {
      mode: 'development',
      module:{//配置loader 所有第三方模块的配置规则
          rules:[
              {test:/\.js|jsx$/,use:'babel-loader',exclude:/node_modules/},//exclude,排除项
              {test:/\.css$/,use:['style-loader','css-loader']}//配置打包处理css样式表的第三方loader,webpack的loader匹配规则是从右到左
          ]
      },
      resolve:{
          extensions:['.js','.json','.css'],//表示在引用这几种后缀名的文件时,可以省略不写后缀名
          alias: {//声明别名,编译的时候会按照这里的规则将别名替换掉
              '@': path.join(__dirname,'./src')
          }
      }
    };
    
    • 2.3 新建一个样式表,按照css语法书写样式
    .itemli{
      color:red;
      text-align:center;
      width:60%
    }
    
    • 2.4 在需要使用样式的组件中导入样式表文件
    import stylesObj from './../css/itemcomp.css';
    
    • 2.5 在需要应用样式的元素中添加className属性
    return <li className="itemli">列表项</li>;
    

    但是,使用上述方式定义的样式是全局的,一次引用,每个组件都可以使用,容易造成样式混乱,因为样式表不同于JS没有作用域的概念,那么怎么解决这个问题呢?

  • 3.模块化的样式表

    • 3.1. 为css-loader配置参数以支持普通的css样式表启用模块化
    //css-loader可以通过?追加参数
    //modules表示为普通样式表启用模块化
    {test:/\.css$/,use:['style-loader','css-loader?modules']}//配置打包处理css样式表的第三      方loader,webpack的loader匹配规则是从右到左
    
    • 3.2. 启用模块化样式表后,import的样式表不同于未启用模块化的空对象,是具有值 的
    import stylesObj from './../css/itemcomp.css';
    console.log(stylesObj);
    

    ![image.png](https://upload-images.jianshu.io/upload_images/3566275- cc80053689b64f1b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    • 3.3. 为需要的元素添加className或id(css-loader模块化只是针对class或id选择器生 效),<li className={stylesObj.itemli}>
    • 3.4. 非模块化与模块化的样式表异同在于
      *非模块化的样式表编译后,样式表解析在index.html的<style>标签中,类名同于样式表的类名
      *模块化样式表编译后,样式表同样解析在index.html的<style>标签中,不同的是,类名是被混淆的而非样式表中原始类名
      ![模块化样式表编译后](https://upload-images.jianshu.io/upload_images/3566275- 4c40688f04a446a9.png?imageMogr2/auto-orient/strip%7CimageView2/3/w/500)
      ![非模块化样式表编译后](https://upload-images.jianshu.io/upload_images/3566275- 58ba9610b50df1aa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/500)
  • 4.自定义样式表模块化名称
    开启css-loader的模块化会对样式表中的类名进行混淆,如果不想要混淆,而是通过一定规则定义的怎么做呢?

    使用css-loader的localIdentName参数自定义生成的类名格式,可选参数有
    - [path]表示对样式表编译后生成的类名具有相对于项目根目录所在的路径
    - [name]表示生成的类名具有样式表文件名
    - [local]表示生成的类名具有样式表中定义的原始类名
    - [hash:length]表示生成的类名具有length长的的hash值

    使用localIdentName参数自定义的stylesObj

    如图所示,四段分别对应四个可选参数,如此便可以看到有意义的className

     {test:/\.css$/,use:['style-loader','css-loader?modules&localIdentName=[path][name]-[local]-[hash:5]']}
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,829评论 1 331
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,603评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,846评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,600评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,780评论 3 272
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,695评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,136评论 2 293
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,862评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,453评论 0 229
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,942评论 2 233
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,347评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,790评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,293评论 3 221
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,839评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,448评论 0 181
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,564评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,623评论 2 249

推荐阅读更多精彩内容

  • 3. JSX JSX是对JavaScript语言的一个扩展语法, 用于生产React“元素”,建议在描述UI的时候...
    pixels阅读 2,752评论 0 24
  • 安装: 概述 React起源于FaceBook的内部项目,因为该公司对市场上所有的JavaScript MVC框架...
    姒沝無痕阅读 670评论 0 0
  • create-react-app 通过创建一个已经完成基本配置的应用,让开发者快速开始React应用的开发。 安装...
    爱翔是我二媳妇阅读 242评论 0 0
  • 写在前面 React入门学习笔记。 教程可参考:React 教程 | 菜鸟教程阮一峰的网络日志 > React 入...
    年少有van阅读 357评论 1 1
  • 周末了,想让老妈休息,自己带女儿去买菜。老妈还钦点了一家肉摊,大概描述了位置和摊主的特征,说想买肉就去那家吧。买菜...
    长余有联阅读 340评论 2 0