这篇文章主要讲了对reactJS的认识以及如何利用webpack+reactJS构建项目,使用构造函数创建组件和使用class关键字创建组件。

1.基础知识

2.构建项目初始化

  1. 运行npm init -y 快速初始化项目

  2. 在 src 目录下创建 index.html

  3. 注意:webpack 4.x 提供了 约定大于配置的概念;目的是为了尽量减少 配置文件的体积;

    • 默认约定了:
    • 打包的入口是src -> index.js
    • 打包的输出文件是dist -> main.js
    • 4.x 中 新增了 mode 选项(为必选项),可选的值为:developmentproduction;
  4. 安装webpack-dev-server自动打包编译

  5. 在package.json中的scripts中添加 “dev”: “webpack-dev-server –open –oprt 3000 –hot”

  6. 配置html-webpack-plugin插件

    1
    2
    npm i html-webpack-plugin -D
    # -D 是工具包,
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // webpack.config.js 配置文件
    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');

    const htmlPlugin = new HtmlWebpackPlugin({
    template: path.join(__dirname, './src/index.html'),
    filename: 'index.html'
    });

    let config = {
    mode: 'development', // production模式打包是压缩好的,development模式是开发模式
    plugins: [
    htmlPlugin
    ]
    };
    module.exports = config;

3.react基本应用

  • 安装包

    1
    2
    3
    npm i react react-dom -S
    # react: 专门用于创建组件和虚拟DOM的,同时组件的生命周期都在这个包中
    # react-dom: 专门进行DOM操作的,最主要的应用场景,就是 ReactDOM.render()
  • 在index.html中创建容器

    1
    2
    <!--  使用 React 创建的虚拟DOM元素,都会被渲染到这个指定的容器中 -->
    <div id="app"></div>
  • 在index.js中引包

    1
    2
    import React from 'react'
    import ReactDOM from 'react-dom'
  • 创建虚拟DOM元素

    1
    2
    3
    4
    //  第一个参数: 字符串类型的参数,表示要创建的标签的名称
    // 第二个参数:对象类型的参数, 表示 创建的元素的属性节点
    // 第三个参数: 子节点
    const myH1 = React.createElement('h1', {id: 'myH1', title: 'my title'}, '我是新创建的h1元素内容')
  • 渲染

    1
    ReactDOm.render(myH1, document.getElementById('app'))

4.jsx语法

JSX语法:就是符合 xml 规范的 JS 语法;(语法格式相对来说,要比HTML严谨很多)

  1. 如何启用jsx语法:
  • 安装babel插件

    1
    2
    3
    4
    # 安装babel6.x版本
    npm i babel-core babel-loader@7 babel-plugin-transform-runtime -D
    # 语法包中babel-preset-react能够识别转换jsx语法
    npm i babel-preset-env babel-preset-stage-0 babel-preset-react -D
  • 配置webpack.config.js

    1
    2
    3
    4
    5
    module: {
    rules: [
    { test: /\.js|jsx$/, use: 'babel-loader', exclude: /node_modules/ }
    ]
    }
  • 配置.babelrc

    1
    2
    3
    4
    {
    "presets": ["env", "stage-0", "react"],
    "plugins": ["transform-runtime"]
    }
  1. jsx 语法的本质:并不是直接把 jsx 渲染到页面上,而是 内部先转换成了 createElement 形式,再渲染的;
  2. 在 jsx 中混合写入 js 表达式:在 jsx 语法中,要把 JS代码写到 { }
    • 渲染数字
    • 渲染字符串
    • 渲染布尔值
    • 为属性绑定值
    • 渲染jsx元素
    • 渲染jsx元素数组
    • 将普通字符串数组,转为jsx数组并渲染到页面上【两种方案】
  3. 在 jsx 中 写注释:推荐使用{ /* 这是注释 */ }
  4. 为 jsx 中的元素添加class类名:由于 JSX 就是 JavaScript,所以需要使用className 来替代 classhtmlFor替换label的for属性
  5. 在JSX创建DOM的时候,所有的节点,必须有唯一的根元素进行包裹;
  6. 在 jsx 语法中,标签必须 成对出现,如果是单标签,则必须自闭和!

当编译引擎,在编译JSX代码的时候,如果遇到了<那么就把它当作 HTML代码去编译,如果遇到了 {} 就把 花括号内部的代码当作 普通JS代码去编译。

5.创建组件

1. 使用构造函数创建组件

使用构造函数来创建组件,如果要接收外界传递的数据,需要在构造函数的参数列表中使用props来接收;
必须要向外return一个合法的JSX创建的虚拟DOM。

  • 创建组件

    1
    2
    3
    4
    5
    6
    7
    8
    // 抽离到一个Hello.jsx文件中
    import React from "react";
    // 组件的名称首字母必须是大写
    function Hello(props) {
    // 不论是 Vue 还是 React,组件中的 props 永远都是只读的,不能被重新赋值
    return <div>这是组件内容--{props.name} -- {props.age}</div>
    }
    export default Hello
  • 使用组件

    1
    2
    3
    4
    5
    // 使用组件并 为组件传递 props 数据
    <Hello name={dog.name} age={dog.age}></Hello>

    // 使用{...obj}属性扩散传递数据,效果和上面一样
    <Hello {...dog}></Hello>
  • 导入组件如何省略.jsx后缀名

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 打开 webpack.config.js ,并在导出的配置对象中,新增如下节点:
    resolve: {
    extensions: ['.js', '.jsx', '.json'], // 表示这几个文件的后缀名可以省略不写
    alias: { // 在项目中使用“@”作为别名代替src目录
    '@': path.join(__dirname, './src')
    }
    }

    // 使用的时候不用后缀名,直接用@代替src目录
    import Hello from '@/coms/Hello'

2.使用class创建组件

ES6 中 class 关键字,是实现面向对象编程的新形式。

类和对象的区别:对象是对客观事物的抽象,是对对象的抽象。是一种抽象的数据型。它们的关系是,对象的实例,对象的*模板。

  • 基于class关键字创建组件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // CmtList.jsx 父组件
    import React from 'react'
    import CmtItem from '@/coms/CmtItem'

    class CmtList extends React.Component{
    constructor(){
    super();
    this.state = {
    CommentList: [
    { id: 1, user: '张三', content: '哈哈,香蕉' },
    { id: 2, user: '李四', content: '哈哈,苹果' }
    ]
    }
    }
    render(){
    return <div>
    <h2>评论列表</h2>
    {this.state.CommentList.map(item => <CmtItem {...item} key={item.id}></CmtItem>)}
    </div>
    }
    }
    export default CmtList
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // CmtItem.jsx 子组件
    import React from "react";
    function CmtItem(props){ // 展示评论列表,从父组件继承数据
    return <div>
    <h2>{props.user}</h2>
    <p>{props.content}</p>
    </div>
    }
    export default CmtItem

3.使用两种方法创建组件对比

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

二者的区别就在于:有无state属性和有无生命周期函数

  • 用构造函数创建出来的组件叫做“无状态组件”【用处不多】
  • 用class关键字创建出来的组件叫做“有状态组件”【经常使用】
  • 什么情况下使用哪种组件:
    • 如果一个组件需要有自己的私有数据推荐使用class创建的有状态组件
    • 组件不需要私有数据推荐使用构造函数创建的无状态组件
    • React官方:无状态组件由于没有自己的state和生命周期函数,所以运行效率会比 有状态组件稍微高一些。
  • 组件中的 propsstate/data 之间的区别
    • props 中的数据都是外界传递过来的;
    • state/data 中的数据,都是组件私有的;(通过 Ajax 获取回来的数据,一般都是私有数据);
    • props 中的数据都是只读的;不能重新赋值;
    • state/data 中的数据,都是可读可写的;