zoukankan      html  css  js  c++  java
  • React基础知识

    1.React介绍

    中文官网

    英文官网

    1.  react、vue、angular俗称前端框架三驾马车
    2. React起源于Facebook的内部项目,因为该公司对市场上所有的JavaScript MVC框架都不满意,就决定自己写一套,用来架设Instagram的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了
    3. React是一个用于构建用户界面的JavaScript库
    4. React主要用户构建UI,很多人认为React是MVC中的V(视图)

    1.1.react特点

    1.2.react和vue的区别

    1.首先,这两个框架,都是以组件化的思想进行开发的!

    2.从开发团队上进行比较:

    1. React的开发团队,是Facebook官方大牛团队,团队技术实力雄厚;
    2. Vue:第一版本,主要是作者尤雨溪进行维护。

    3.从社区方面进行对比:

    1. React社区早,解决方案多
    2. Vue社区晚一点,解决方案相对少一点

    4.从移动App开发方面:

    1. 使用React这门技术,可以分分钟转到ReactNative的开发中
    2. Vue这门技术,也提供了无缝的转移到移动端开发中,通过weex可以使用Vue的语法,进行移动端APP开发

     

    1.3.react核心知识

    1.3.1React核心概念

    • 虚拟DOM(Virtual DOM)
    • Diff算法(Diff Algorithm)
    • 单向数据流渲染(Data Flow)
    • 组件生命周期
    • JSX
    • 一切皆为组件

    2.我的第一个React项目

    推荐使用yarn来安装node包,时间更快

    2.1.新建文件夹,初始化项目

    mkdir react-demo
    
    cd react-demo
    
    npm init -y

    2.2.安装依赖

    yarn add react react-dom webpack webpack-cli webpack-dev-server babel babel-cli babel-core babel-loader@7 babel-preset-react babel-preset-env babel-preset-es2015

    2.3.编写文件

    2.3.1.新建webpack.config.js

    目录下新建webpack配置文件webpack.config.js

    module.exports = {
      entry: "./main.js",
      output: {
        path: "/",
        filename: "index.js"
      },
      module: {
        rules: [
          {
            test: /.js$/,
            exclude: /(node_modules)/,
            use: {
              loader: "babel-loader",
              options: {
                presets: ['env', 'react', 'es2015']
              }
            }
          }
        ]
      }
    }

    2.3.2.新建页面文件index.html

    <!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>Document</title>
    </head>
    <body>
      <div id="root"></div>
      <script src="./index.js"></script>
    </body>
    </html>

    2.3.3.新建入口文件main.js

    目录下新建main.js

    import React, { Component } from 'react';
    import ReactDom from 'react-dom';
    
    class App extends Component {
        render() {
            return <h1> Hello, world! </h1>
        }
    }
    
    ReactDom.render(
        <App />,
        document.getElementById('root')
    )

    2.3.4.修改package.json

      "scripts": {
        "start": "webpack-dev-server --inline --hot --open --port 8090 --mode development"
      },

    2.3.5.运行

    yarn start

    3.脚手架-我的第一个React项目

    create-react-app是react脚手架的名称

    脚手架官网

    3.1.快速开始

    npm5.2或者更高带来的一个新特性,可以不同全局安装脚手架,就可以直接使用脚手架

    npx create-react-app my-app
    
    cd my-app
    
    yarn start

     3.2.运行成功

    3.3.项目结构

    │  .gitignore                git忽略清单
    │  package.json                项目配置文件
    │  README.md                说明文件
    │  
    ├─public            公共资源
    │      favicon.ico           图标 
    │      index.html            首页html
    │      manifest.json        缓存清单
    │      
    └─src                源代码
            App.css                组件的样式文件
            App.js                组件文件
            App.test.js            组件的测试文件
            index.css            全局样式文件
            index.js            入口文件
            logo.svg            logo图标
            serviceWorker.js    serviceWorker文件

    4.JSX

     jsx是React框架中的一种语法,它是JavaScript的语法拓展。既可以在js文件中写js逻辑代码,也可以在js文件中写HTML语言。

    JSX是JavaScript XML的简写

    import React from 'react';
    import ReactDOM from 'react-dom';
    
    // const App = () => <h1>我就是jsx</h1>;
    
    const App = function () {
      return (
        <h1>我就是jsx</h1>
      );
    }
    
    ReactDOM.render(<App />, document.getElementById('root'));

    4.1.JSX嵌套元素

    组件中,必须返回一个根元素

    如下列语法是错误的!

    const App = function () {
      return (
        <h1>我就是jsx</h1>
        <h1>我就是jsx</h1>
      );
    }

    假设想要在根目录下直接渲染2个标签,可以使用Fragment标签,类似vue中的template

    引入Fragment组件

    import React, { Fragment } from 'react';

    包裹标签

    import React, { Fragment } from 'react';
    import ReactDOM from 'react-dom';
    
    const App =  ()=> {
      return (
        <Fragment>
          <h1>我就是jsx</h1>
          <h1>我就是jsx</h1>
        </Fragment>
      )
    }
    
    ReactDOM.render(<App />, document.getElementById('root'))

    4.2.JSX表达式

    1.普通渲染

    <h1>我就是jsx</h1>

    2.数学表达式

    <h1>{1 + 1}</h1>

    3.字符串

    <h1>{'hello world'}</h1>

    4.bool类型-无法渲染

    <h1>{isBoy}</h1>

    5.使用变量

    <h1>{msg}</h1>

    6.三目运算符

    <h1>{isBoy ? "男生" : "女生"}</h1>

    7.调用方法

     const format = (msg) => {
      return '---' + msg + '---';
    }    
    
    <h1>{format(msg)}</h1>

    8.使用对象

    const person = {
      name: "沙和尚"
    };      
    
    <h1>{person.name}</h1>

    完整代码

    import React, { Fragment } from 'react';
    import ReactDOM from 'react-dom';
    
    const msg = "你们好呀";
    const isBoy = false;
    const format = (msg) => {
      return '---' + msg + '---';
    }
    const person = {
      name: "沙和尚"
    };
    
    const App = () => {
      return (
        <Fragment>
          <h1>我就是jsx</h1>
          {/* 数字 */}
          <h1>{1 + 1}</h1>
          {/* 字符串 */}
          <h1>{'hello world'}</h1>
          {/* bool类型 */}
          <h1>{isBoy}</h1>
          {/* 使用变量 */}
          <h1>{msg}</h1>
          {/* 3目运算符 */}
          <h1>{isBoy ? "男生" : "女生"}</h1>
          {/* 调用方法 */}
          <h1>{format(msg)}</h1>
          {/* 使用对象 */}
          <h1>{person.name}</h1>
        </Fragment>
      )
    }
    
    ReactDOM.render(<App />, document.getElementById('root'))

    4.3.JSX嵌套JSX JSX循环

    按照这个思路去理解即可

    1. index.js文件可以直接写标签入<h1></h1>
    2. 在标签中可以通过{}直接写js如<h1>{‘你们好’}</h1>
    3. 既然1中的js可以直接写标签,那么{}中的js也可以直接写标签

    如下所示:

    import React from 'react';
    import ReactDOM from 'react-dom';
    
    const msg = "今天天气不错";
    
    const App = () => {
      return (
        <div >
          {
            <div>
              <h1>我也是大头 {msg} </h1>
              <h1>我也是大头 {msg} </h1>
            </div>
          }
        </div>
      )
    }
    
    ReactDOM.render(<App />, document.getElementById('root'))

    加强版本,必须要掌握

    import React from 'react';
    import ReactDOM from 'react-dom';
    
    const list = ['苹果', '香蕉', '雪梨', '西瓜'];
    
    
    const App = () => {
      return (
        <div >
          {
            <div>
              {
                list.map(function (v) {
                  return (
                    <h1 key={v}>{v}</h1>
                  )
                })
              }
            </div>
          }
        </div>
      )
    }
    
    ReactDOM.render(<App />, document.getElementById('root'))

    终极版 最常用

    import React from 'react';
    import ReactDOM from 'react-dom';
    
    const list = ['苹果', '香蕉', '雪梨', '西瓜'];
    
    const App = () => {
      return (
        <div >
          {
            <div>
              {
                list.map(v => <h1 key={v}>{v}</h1>)
              }
            </div>
          }
        </div>
      )
    }
    
    ReactDOM.render(<App />, document.getElementById('root'))

    4.4.JSX注释

        {
          // 这里是单行注释
        }
        {
          /*
          这里是多行注释
          这里是多行注释
          这里是多行注释
          这里是多行注释
          */
        }

    4.5.JSX标签属性

    jsx标签上可以设置绝大部分和以前html标签一样的属性,如checked、图片的src

    除此之外

    1.html的class属性改为className

     <div className="redCls">大头大头</div>

    2.html中label标签的for属性改为htmlFor

    <label htmlFor="inp">
            点我点我
              <input id="inp" type="text" />
    </label>

    3.标签中的自定义属性使用data

     <div data-index={'hello'} >自定义属性</div>

    4.渲染html字符串使用dangerouslySetInnerHTML属性

    <li dangerouslySetInnerHTML={{__html:"<i>打我呀</i>"}}></li>

    5.bool类型的值可以这样用

    <input type="checkbox" checked={true} />

    6.当属性太多了,可以使用...拓展运算符

    const props={
      className:"redCls",
      "data-index":5
    }
    
    <div {...props}>展开属性</div>

    4.6.JSX的行内样式

    JSX可以像传统的HTML标签一样添加行内样式,不同的是,要通过对象的方式来实现。并且属性名是以驼峰命名。

    import React from 'react';
    import ReactDOM from 'react-dom';
    import "./index.css";
    
    const App = () => {
      return (
        <div style={{ color: 'yellow', fontSize: "50px", "backgroundColor": 'blue' }} > 颜色好好看呀 </div>
      )
    }
    
    ReactDOM.render(<App />, document.getElementById('root'))

    4.7.JSX创建组件的本质(了解即可)

    JSX俗称 语法糖,提供了一种更好使用的语法让我们使用,其本质是调用React.createElement实现的

    React.createElement,接收3个参数

    1. 标签名 如 “div”
    2. 标签上的属性,如{className: "redCls"}
    3. 文本内容或者另一个React.createElement对象或者React.createElement数组
    import React from 'react';
    import ReactDOM from 'react-dom';
    import "./index.css";
    
    const parentProps = {
      className: "redCls",
      "data-index": 100
    }
    
    const App = () => {
      return React.createElement(
        "div",
        parentProps,
        [
          React.createElement(
            "span",
            null,
            "你们好呀"
          ),
          React.createElement(
            "span",
            null,
            "你们好呀"
          )
        ]
      )
    }
    
    ReactDOM.render(<App />, document.getElementById('root'))

    5.组件的创建

    在React中,组件分为两种,类组件和函数式组件

    1. 简单功能使用函数式组件
    2. 复杂功能使用类组件
    3. 组件名都必须大写

    5.1.类组件

    • 使用es6创建class的方式来实现一个组建类
    • 首字母要大写
    • 要继承React中的Component类
    • 必须实现render函数,函数内返回标签
    • 组件有自己的state和生命周期
    import React,{Component} from 'react';
    import ReactDOM from 'react-dom';
    import "./index.css";
    
    
     class App extends Component {
      render() {
        return (
          <div>
            hello
          </div>
        )
      }
    }
    ReactDOM.render(<App />, document.getElementById('root'))

    5.2.函数式组件

    也叫做无状态组件

    简单功能组件可以使用函数式组件,性能更高。

    函数式组件其实就是一个函数,只不过函数内部要返回对应的标签

    • 首字母要大写
    • 函数内返回标签
    import React from 'react';
    import ReactDOM from 'react-dom';
    import "./index.css";
    
    
    // 这个就是函数式组件
    const App = () => {
      return (
        <div>这个就是一个简单的函数式组件</div>
      )
    }
    
    ReactDOM.render(<App />, document.getElementById('root'))

    5.3.小结

    • 函数式组件性能更高,因为没有生命周期
    • 函数式组件更方便进行测试
    • 能不用类组件就不要用类组件
    • 当要使用state时,就要使用类组件

    6.状态和属性

    在React中,状态和属性都可以实现数据动态化,我们现在开始这两个知识

    6.1.状态state

    在react中,内部组件的数据是通过state来实现和管理

    1. 可以理解为state就是vue中的data
    2. 函数式组件没有自己的state

    我们之前使用变量,都是脱离了组件本身,正确来说,组件自身是应该具有私有和独立的数据(状态)的,这个私有的数据和状态就叫做state,以后,只要说到数据的状态那么就是指state

    6.1.1.state的声明和使用

    在类组件中,state的声明分为两种方式

    1.类属性的方式声明

     class Person extends Component {
      // 1 声明 state
      state = {
        date: "2008",
        msg: "大头大头下雨不愁"
      }
      render() {
        return (
          <div>
            {/* 2 使用state */}
            <h1>{this.state.date}</h1>
            <h2>{this.state.msg}</h2>
          </div>
        )
      }
    }

    2.构造函数中声明

     class Person extends Component {
      // 1 构造函数中 声明 state
      constructor() {
        // 1.1 必须在this之前调用super()方法
        super();
        this.state = {
          date: "2008",
          msg: "大头大头下雨不愁"
        }
      }
      render() {
        return (
          <div>
            {/* 2 使用state */}
            <h1>{this.state.date}</h1>
            <h2>{this.state.msg}</h2>
          </div>
        )
      }
    }

    6.1.2.state的赋值

    state的赋值方式通过this.setState方式来实现

    需要注意的是,不能使用this.state.date=100 直接修改

    class Person extends Component {
      state = {
        date: 2008
      }
    
      // 2 事件的声明 要使用箭头函数
      handleClick = () => {
        // 3 获取state中的日期
        let { date } = this.state;
        
        // 4 修改state中的日期
        this.setState({
          date: date + 1
        });
    
      }
      render() {
        return (
          // 1  绑定事件 事件名必须驼峰命名
          <div onClick={this.handleClick}>
            <h1>{this.state.date}</h1>
          </div>
        )
      }
    }

    6.1.3.state的赋值是异步的

    react为了优化性能,将state的赋值代码改成异步的方式,为了避免反复的设置state而引发的性能损耗问题。

    看看下面打印的值

    class Person extends Component {
      state = {
        date: 2008
      }
      handleClick = () => {
        let { date } = this.state;
    
        // 1 修改state中的日期 增加 1000
        this.setState({
          date: date + 1000
        });
    
        // 2 看看这个date是多少
        console.log(this.state.date);
      }
      render() {
        return (
          <div onClick={this.handleClick}>
            <h1>{this.state.date}</h1>
          </div>
        )
      }
    }

    有时候,我们希望在一设置值的时候,就希望马上得到最新的state的值,那么可以将代码改为下列的写法,给setState添加一个回调函数,回调中可以获取到修改后的state的值

     class Person extends Component {
      state = {
        date: 2008
      }
    
      handleClick = () => {
        let { date } = this.state;
    
        // 添加一个回调函数
        this.setState({
          date: date + 1000
        }, () => {
          // date的值为 3008
          console.log(this.state.date);
        });
      }
      render() {
        return (
          <div onClick={this.handleClick}>
            <h1>{this.state.date}</h1>
          </div>
        )
      }
    }

    有时候,setState还可以接收一个函数,函数内可以实时获取state中的值,不存在延迟。

        this.setState(preState => {
          console.log("上一次的state", preState.date);
          return {
            date: preState.date + 1000
          }
        })
    
        this.setState(preState => {
          console.log("上一次的state", preState.date);
          return {
            date: preState.date + 1
          }
        })

    6.2.属性props

    props意思是属性,一般存在父子组件中,用于父向子传递数据。

    子组件不能修改接受到的props值

    6.2.1.初体验

    1.声明一个类组件HomeTop父组件的数据通过this.props来获取

    class HomeTop extends Component {
      render() {
        return (
          <h1>屋顶的颜色是 {this.props.acolor} 尺寸 {this.props.asize}</h1>
        )
      }
    }

    2.声明一个函数式组件HomeFotter,父组件传递的数据 需要在函数的形参props上接收

    const HomeFooter = (props) => {
      return <h1>屋底的颜色是 {props.bcolor}  尺寸 {props.bsize}</h1>
    }

    3.声明父组件,并在标签上通过属性的方式进行传递数据

    class Home extends Component {
      state = {
        color: "blue",
        size: 100
      }
      render() {
        return (
          <div>
            <HomeTop acolor={this.state.color} asize={this.state.size} ></HomeTop>
            <HomeFooter bcolor={this.state.color} bsize={this.state.size}  ></HomeFooter>
          </div>
        )
      }
    }

    4.需要注意的是父组件中的变量名是color,size而HomeTop和HomeFotter中修改了一下变量名,分别是acolor,asize和bcolor,bsize。

    完整代码

    import React, { Component } from 'react';
    import ReactDOM from 'react-dom';
    
    class HomeTop extends Component {
      render() {
        return (
    
          <h1>屋顶的颜色是 {this.props.acolor} 尺寸 {this.props.asize}</h1>
    
      )
      }
    }
    
    const HomeFooter = (props) => {
      return <h1>屋底的颜色是 {props.bcolor}  尺寸 {props.bsize}</h1>
    }
    
    class Home extends Component {
      state = {
        color: "blue",
        size: 100
      }
      render() {
        return (
    
          <div>
            <HomeTop acolor={this.state.color} asize={this.state.size} ></HomeTop>
            <HomeFooter bcolor={this.state.color} bsize={this.state.size}  ></HomeFooter>
          </div>
    
        )
      }
    }
    
    ReactDOM.render(<Home />, document.getElementById('root'))

    6.2.2.类组件构造函数中的props

    当想要在类组件的构造函数中,获取到props时,需要如下使用:

      constructor(props) {
        super(props);
        console.log(props);
      }

    6.2.3.props默认值

    当父元素没有传递props属性时,子组件可以指定一个默认props属性值来使用。

    通过 组件名.defaultProps 来指定

    import React from 'react';
    import ReactDOM from 'react-dom';
    
    let HomeNav = (props) => {
      return <h1> 导航为 {props.color}  </h1>
    }
    // 指定一个默认属性
    HomeNav.defaultProps = {
      color: "yellow"
    }
    
    class Home extends Component {
      state = {
        color: "blue"
      }
      render() {
        return (
          <div>
            <HomeNav></HomeNav>
          </div>
        )
      }
    }
    
    ReactDOM.render(<Home />, document.getElementById('root'))

    6.2.4.props类型检验

    在一些要求代码更为严格的项目中,父组件传递数据的格式,必须和子组件要求的格式保持一致,否则就认为代码出错。

    如子组件要求的是数字类型(100),而父组件传递的是字符串类型(“100”)。

    这个需求可以通过react中的props类型检验来完成。

    自React v15.5起,react.PropTypes已移入另一个包中。请使用prop-types库代替

     6.2.4.1.安装prop-types

    yarn add prop-types --dev

    引入

    import PropTypes from 'prop-types'; 

    6.2.5.使用

    import React, { Component } from 'react';
    import ReactDOM from 'react-dom';
    // 1 引入 prop-types
    import PropTypes from 'prop-types'; 
    
    
    let HomeNav = (props) => {
      return <h1> 导航为 {props.color} 数量为 {props.nums}  </h1>
    }
    // 2  指定要求接收的数据格式
    HomeNav.propTypes ={
      color:PropTypes.string,
      nums:PropTypes.number
    }
    
    
    
    class Home extends Component {
      state = {
        color: "blue",
        nums:100
      }
      render() {
        return (
          <div>
            <HomeNav {...this.state}></HomeNav>
          </div>
        )
      }
    }
    
    ReactDOM.render(<Home />, document.getElementById('root'))

    6.2.6.props插槽props.children

    props.children可以实现类似Vue中的插槽功能(slot)

    6.2.6.1.子组件

    let HomeNav = (props) => {
      return (
        <div>
          <div>标题</div>
          <div>{props.children}</div>
        </div>
      )
    }

    6.2.6.2.父组件

    class Home extends Component {
      render() {
        return (
          <div>
            <HomeNav {...this.state}>
              {/* 这里放动态插入的内容 */}
              <div>小标题你</div>
            </HomeNav>
          </div>
        )
      }
    }

    6.2.6.3.完整代码

    import React, { Component } from 'react';
    import ReactDOM from 'react-dom';
    import PropTypes from 'prop-types';
    
    let HomeNav = (props) => {
      return (
        <div>
          <div>标题</div>
          <div>{props.children}</div>
        </div>
      )
    }
    
    class Home extends Component {
      render() {
        return (
          <div>
            <HomeNav {...this.state}>
              {/* 这里放动态插入的内容 */}
              <div>小标题</div>
            </HomeNav>
          </div>
        )
      }
    }
    
    ReactDOM.render(<Home />, document.getElementById('root'))

    6.3.state和props对比

    相同

    1. 二者都作为React内更新视图的依据,只有他们变化时,React才会进行相应的更新
    2. 二者都不可以通过直接赋值的方式更新

    不同

    1. 更新方式不同:state通过setState方法更新(只能在组件内部更新),props则通过传入的值实现(组件内不可变)。
    2. state只维护组件内部的状态,props让外部维护组件的状态。

    总结:尽量少用state,尽量多用props,这样既能提高组件的可复用性,又能降低维护成本。

    7.事件

    React元素的事件处理和DOM元素的很相似,但是有一点语法上的不同:

    1. React事件的命名采用小驼峰式(camelCase),而不是纯小写。
    2. 使用JSX语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。

    7.1.传统HTML绑定事件

    <button onclick="activateLasers()">
      Activate Lasers
    </button>

    7.2.React中

    <button onClick={this.handleClick}>
      Activate Lasers
    </button>

    7.3.事件中的this

    观察以下的this值 它是undefined

    import React, { Component } from 'react';
    import ReactDOM from 'react-dom';
    class Home extends Component {
      state = {
        msg: "大家好呀"
      }
      handleClick() {
        // undefined
        console.log(this);
      }
      render() {
        return (
          <div>
            <div onClick={this.handleClick} >小标题</div>
          </div>
        )
      }
    }
    
    ReactDOM.render(<Home />, document.getElementById('root'))

    因为在react中,绑定事件不是原生HTML的dom元素,onClick只是react帮我们做的一个中间的映射,那么他在处理事件的时候,是不会处理this的指向的,我们需要手动处理这个this

    7.3.1.处理方式

    1.绑定事件的时候使用bind来锁定this 代码丑陋,不推荐

    <div onClick={this.handleClick.bind(this)} >小标题</div>

    2.在构造函数中使用bind修改this执行(推荐)

    import React, { Component } from 'react';
    import ReactDOM from 'react-dom';
    class Home extends Component {
      state = {
        msg: "大家好呀"
      }
      constructor() {
        super();
        // 重新绑定this
        this.handleClick = this.handleClick.bind(this);
      }
      handleClick() {
        console.log(this);
      }
      render() {
        return (
          <div>
            <div onClick={this.handleClick} >小标题</div>
          </div>
        )
      }
    }
    
    ReactDOM.render(<Home />, document.getElementById('root'))

    3.将事件的执行,改成箭头函数的方式(推荐)

    import React, { Component } from 'react';
    import ReactDOM from 'react-dom';
    class Home extends Component {
      state = {
        msg: "大家好呀"
      }
        // 修改为箭头函数的方式
      handleClick = () => {
        console.log(this);
      }
      render() {
        return (
          <div>
            <div onClick={this.handleClick} >小标题</div>
          </div>
        )
      }
    }
    
    ReactDOM.render(<Home />, document.getElementById('root'))

    7.4.事件传参

    执行类似以前HTML的DOM事件传参一样的功能

    <button onclick="show('大家好')"></button>

    React中的写法为:

    不推荐,容易导致意外情况(BUG)

    <button onClick={() => { this.handleClick('red') }}>红色</button>

    推荐写法:

     <button onClick={ this.handleClick.bind(this,'red') }>红色</button>
  • 相关阅读:
    redhat 6.4下PXE+Kickstart无人值守安装操作系统
    ubuntu14.04安装好Hadoo之后接着安装hbase和介绍常用命令
    避坑之Hadoop安装伪分布式(Hadoop3.2.0/Ubuntu14.04 64位)
    kindeditor文件上传设置文件说明为上传文件名(JSP版)
    sqlmap 扫描注入漏洞
    局域网内访问不同网段的主机(转记)
    cmd创建用户开启3389命令
    用python来更改windows开机密码
    代码安全之上传文件
    web渗透(转)
  • 原文地址:https://www.cnblogs.com/sauronblog/p/12670830.html
Copyright © 2011-2022 走看看