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

    1.脚手架

    npx create-react-app appName

    2.JSX是什么?

    JSX是一种JS语法扩展,可以在JS中编写类似于HTML的语法。需要明确的是,JSX本质是语法糖,我们写的并非是真正的HTML。

    3.React组件的存在形式

    有两种存在形式:函数组件 和 类组件。下面的例子中它们是等价的。

    function App() {
      return (
        <div>
          Hello World!
        </div>
      );
    }
    class App extends React.Component {
       render() {
          return (
            <div>Hello World!</div>
          );
       }
    }

    要明确的是:

    1. 组件必须有返回的视图内容,你可以理解为必须有JSX(当然,你也可以不用JSX,而用createElement)。
    2. 类组件中,必须有render函数,JSX写在该函数的返回值中。

    4.函数组件和类组件的区别(React16.8前):

    1. 类组件内部数据this.state,函数组件没有内部数据,被称为无状态组件
    2. 类组件拥有完整的组件生命周期钩子,而函数组件没有
    3. 函数组件书写简单,而类组件相对复杂。

    那么,是不是说函数组件一无是处呢?那倒不是,当页面的某些部分不需要内部数据,或者其展示的数据由父组件提供,我们可以使用书写更简便的函数组件。

    5.JSX占位符

    我们知道,每个组件中,最外层必须只有一个HTML标签或组件,比如这样:

    // 正确
    class App extends React.Component{
        render() {
            return (
               <div>
                   Hello World
               </div>
            );
        }
    }
    // 错误
    class App extends React.Component{
        render() {
            return (
               <div>Hello World</div>
               <div>Hello World</div>
            );
        }
    }

    有的页面极其复杂,DOM元素套了一层又一层,有时候我们不想这个组件外面套一层无意义的DIV,这时需要用到占位符,有两种写法:

    import React, {Fragment} from 'react';
    class App extends React.Component {
       render() {
          return (
             <Fragment>
                <div>Hello World</div>
                <div>Hello World</div>
             </Fragment>
          );
       }
    }
    或
    class App extends React.Component {
       render() {
          return (
             <>
                <div>Hello World</div>
                <div>Hello World</div>
             </>
          );
       }
    }

    这样,渲染出来的页面 DOM 就没有多余的嵌套元素了。

    6.JSX中的HTML元素属性

    因为JSX语法是存在于JavaScript中的,很多HTML和CSS的属性写在其中,有可能和JS发生混淆,例如HTML标签属性class就会和JS中的class混淆。为了避免这种混乱,HTML中的属性改了一种写法。

    • class --> className
    • onclick --> onClick
    • <label>中的for属性 --> htmlFor
    • ......
    <label htmlFor='insertArea'>请输入内容</label>
    <input className='input' id='insertArea' value={ this.state.inputValue } onChange={ this.handInputData }  ref={(content)=>{this.inputData = content}}/>
    {/* 在为元素添加样式类的时候,建议使用className,否则React会认为容易与js中的class关键字混淆 */}
    {/* 为label添加for属性的时候,建议使用htmlFor */}
    {/* 事件绑定,全部采用驼峰命名法 */}

    7.获取DOM

    通过ref属性获取

    render() {
          return (
             <Fragment>
                   <button ref = {(el)=>{this.buttonDom = el}}>提交</button>
             </Fragment>
          );
    }

    通过this.buttonDom即可获取

    8.绑定事件回调的this指向

    class App extends Component {
       addHandler(){
          console.log(this)
       }
    
       render() {
          return (
             <Fragment>
                   <button onClick={ this.addHandler.bind(this) }>提交</button>
             </Fragment>
          );
       }
    }

    如果没有bind(this),回调函数内的this并没有指向本组件。如果每个事件绑定都要bind(this),不仅代码冗余,且浪费性能。我们可以将bind(this)过程放在构造函数中,回调只需bind一次即可。

    class App extends Component {
       constructor(props) {
          super(props); // 继承并执行父类中的构造器
          this.state = {
             inputValue: "",
             list: [],
          };
          this.addHandler = this.addHandler.bind(this);
       }
    
       addHandler(){
          console.log(this)
       }
    
       render() {
          return (
             <Fragment>
                   <button onClick={ this.addHandler }>提交</button>
             </Fragment>
          );
       }
    }

    如果回调函数的定义使用箭头函数,则更简洁。

    class App extends Component {
    
       addHandler = () => {
          console.log(this)
       }
    
       render() {
          return (
             <Fragment>
                   <button onClick={ this.addHandler }>提交</button>
             </Fragment>
          );
       }
    }

    9.组件内部数据state

    React组件内部的数据要存放在state中,当state中的数据发生变化时,组件将发生更新。

    修改state中的数据必须通过setState方法,其它的修改方式都是非法的。

    class App extends React.Component {
    
       constructor(props) {
          super(props);
          this.state = {
             count: 0,
             value: "",
          };
       }
    
       clickCount = () => {
          // this.setState({
          //    count: this.state.count + 1
          // })
          // console.log(this.state.count); // 由于setState是异步函数,这里输出的count可能是修改之前的数据。
          // 如果想要在修改后获取最新的数据,可以使用回调函数的写法。第一个函数返回要修改的数据,当修改完成后执行第二个回调。
          this.setState((prev) => ({
             count: prev.count + 1
          }), ()=>{
             console.log(this.state);
          })
       };
       
       changeHandle = (e) => {
          this.setState({
             value: e.target.value,
          })
       };
    
       render() {
          return (
             <>
                <div>value { this.state.value }</div>
                <div>cunt { this.state.count }</div>
                <input onChange={ this.changeHandle }/>
                <button onClick={ this.clickCount }>修改count</button>
             </>
          );
       }
    }

    10.文本内容不转义

    <span dangerouslySetInnerHTML={{__html:value}}></span>

    11.组件间通信

    父传子:

    通过自定义属性传递。

    class App extends React.Component {
       constructor(props) {
          super(props);
          this.state = {
             count: 0,
             value: "",
          };
       }
    
       render() {
          return (
             <>
                <Item content={this.state.value} /> 
             </>
          );
       }
    }
    
    
    class Item extends React.Component{
       render() {
          return (
             <div>{this.props.content}</div>
          )
       }
    }

    子传父:

    子组件无法直接修改父组件中的数据,通过调用父组件的方法来达到目的。

    首先将父组件的方法传入子组件,在子组件中调用此函数。

    class App extends React.Component {
       constructor(props) {
          super(props);
          this.state = {
             count: 0,
             value: "",
          };
       }
    
       render() {
          return (
             <>
                <Item content={this.state.value} sign={this.changeCount} />
             </>
          );
       }
    }
    
    class Item extends React.Component{
       clickHandle = () => {
          const { sign } = this.props;
          sign("hello");
       };
    
       render() {
          return (
             <>
                <div>{this.props.content}</div>
                <button onClick={this.clickHandle}>改变父组件</button>
             </>
          )
       }
    }

    12.组件生命周期

    React16.0前的生命周期(后续的版本也都完全可用,但对于某些钩子,官方有计划将其移除)

    有以下几种途径可以导致组件渲染:

    1.初始化 2.父组件传入的props发生变化 3.组件内的state数据变化 4.强制刷新 5.父组件更新

    相关钩子:

    constructor() 构造器。最先执行的钩子,一般做初始化的操作。

    componentWillMount() 组件即将挂载,还未渲染DOM

    render() 渲染页面

    componentDidMount() 组件挂载完成。这里最常用,可以操作DOM,数据操作,绑定事件监听

    componentWillReceiveProps() 组件接收到新的props

    shouleComponentUpdate() 是否要更新渲染,返回true或false。可以在这里做性能优化,但是要周全考虑到所有情况,搞不好还不如不优化。

    componentWillUpdate() 组件即将渲染更新

    componentDidUpdate() 组件完成渲染更新

    componentWillUnmount() 组件即将卸载。如果在DidMount钩子中绑定了事件监听,一定要在这里解绑,否则内存泄漏。

    React16.4的生命周期

    1. 弃用了componentWillMount、componentWillReceiveProps、componentWillUpdate
    2. 新增了getDerivedStateFromProps、getSnapshotBeforeUpdate来替代弃用的三个钩子
    3. React16并没有完全移除这三个钩子,但是不能和新增的一起混用,React17将会删除这三个钩子。
    4. 新增了对错误的处理componentDidCatch
  • 相关阅读:
    使用CSS3制图
    hdu4585 &amp; BestCoder Round #1 项目管理(vector应用)
    ZooKeeperEclipse 小工具
    svn代码统计工具的金额
    【教你zencart仿站 文章1至6教训 高清1280x900视频下载】[支持手机端]
    [Django]models定义choices 字典中的页面显示值
    xml publisher根据条件显示或隐藏列
    hdu 1398 Square Coins(生成函数,完全背包)
    ubuntu软件中心崩溃
    PHP socket类
  • 原文地址:https://www.cnblogs.com/V587Chinese/p/11629742.html
Copyright © 2011-2022 走看看