码迷,mamicode.com
首页 > 其他好文 > 详细

React基础

时间:2019-10-07 16:10:08      阅读:102      评论:0      收藏:0      [点我收藏+]

标签:create   语法   NPU   标签   click   命名   UNC   构造函数   fragment   

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>
         </>
      )
   }
}

 

React基础

标签:create   语法   NPU   标签   click   命名   UNC   构造函数   fragment   

原文地址:https://www.cnblogs.com/V587Chinese/p/11629742.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!