React基础

react

他是一个用于构建用户界面的 JavaScript 库

React-安装

  1. 安装 nodeJS
  2. 安装create-react-app
npm install -g create-react-app

创建项目

create-react-app myreact
// myreact 项目名称

启动项目

    cd myreact
    yarn start
    // npm run start

默认项目地址:http://localhost:3000/

React文件结构和JSX语法

第一个react项目

打开 src/App.js 删除默认代码 得到 hello react

import React, { Component } from 'react';
//导入React和 React.Component

class App extends Component {
// App根组件继承 React.compoent  

  render() {
// 渲染 并返回一段html结构
    return (
      <div className="App">
        <h1>你好react</h1>
      </div>
    );

  }
}

export default App;
//导出默认 App根组件

JSX语法

JSX 是一个看起来很像 html 的 JavaScript 语法扩展。

js和html混合

1. 只能有一个根节点

return (
  <div className="App">
    <h1>你好react</h1>
  </div>
);

// Classname="App" 就是根节点

2. 可以执行javascript表达式 {}

{1+1}   
{i == 1 ? '对的!' : '错误的'}

3. 类名class 变成 className

<div className="App">
 </div>

4. 行内样式 展开

var myStyle = {
  "font-size": "14px",
  "color": "#FF0000"
}
return (

  <div className="App">
    <h1 style={myStyle}>你好react</h1>
  </div>

);

5. 注释 {/* 注释 */}

6. 数组里面可以直接写html节点

var arr = [
  <h1>组件渲染</h1>,
  <h1>虚拟dom</h1>
]
return (
  <div className="App">
   {arr}
  </div>
);

组件

可以这么说,一个 React 应用就是构建在 React 组件之上的。

创建组件 Child.js

import React,{Component} from 'react'
export default class Child extends Component{
    render(){
        return (
            <div className="child">
                    <h1>我是子组件</h1>
                    <hr/>
            </div>
        );
    }
}

调用组件

01. 导入组件

import Child from './components/Child.js'

02 使用组件

return (
  <div className="App">
    <Child/>
    <h1>App根组件</h1>    
  </div>
);

完成代码

import React, { Component } from 'react';

import Child from './components/Child.js'
// 导入组件

class App extends Component { 
  render() {
    return (
      <div className="App">
        <Child/>
        <h1>App根组件</h1>    
      </div>
    );
  }
}

export default App;
//导出默认 App根组件

React State(状态)

state 是组件的当前状态,可以把组件简单看成一个“状态机”,根据状态 state 呈现不同的 UI 展示。 一旦状态(数据)更改,组件就会自动调用 render 重新渲染 UI,这个更改的动作会通过 this.setState 方法来触发。

初始化组件 state

添加一个类构造函数来初始化状态 this.state

constructor() {  
    super();  //调用父对象构造函数
    this.state={name:"dandan",age:18}
  }

使用state

return (
    <div className="App">
        大家好我是{this.state.name}今年{this.state.age}岁了
    </div>
  );

完整代码

import React, { Component } from 'react';

class App extends Component { 
  constructor() {  
    super();  
    this.state={name:"dandan",age:18}
  }
  render() {
    return (
      <div className="App">
          大家好我是{this.state.name}今年{this.state.age}岁了
      </div>
    );
  }
}

export default App;

React Props

state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据。

传递prop给子组件

return (
<div className="App">
  <Child name="dandan"/>
  <Child name="段鹏"/>
  <Child />
</div>
);

子组件使用props

import React, { Component } from 'react';
import Child from './components/Child'

class App extends Component {
  render() {
    return (
      <div className="App">
      <Child name="dandan"> </Child>
      <Child name="段鹏"></Child>
      <Child ></Child>
      </div>
    );
  }
}

export default App;

完整代码

App.js

import React, { Component } from 'react';
import Child from './components/Child'

class App extends Component {
  render() {
    return (
      <div className="App">
      <Child name="dandan"> </Child>
      <Child name="段鹏"></Child>
      <Child ></Child>
      </div>
    );
  }
}

export default App;

Child.js

import React,{Component} from 'react'
export default class Child extends Component{

    render(){
        return (
            <div className="child">
                    <h1>我是子组件 我的名字是{this.props.name}</h1>
                    <hr/>
            </div>
        );
    }
}
Child.defaultProps = {
    name:"保密"
}
// props 默认值

事件处理

React 元素的事件处理和 DOM 元素类似

React 事件绑定属性的命名采用驼峰式写法,而不是小写。

如果采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM 元素的写法)

javascript写法

<button onclick="showMsg()">
  按钮
</button>

react写法

<button onClick={showMsg}">
  按钮
</button>

完整react代码

import React, { Component } from 'react';
class App extends Component {  
  showMsg(){
    alert("来自react问候!");
  }
  render() {

    return (
      <div className="App">
        <button onClick={this.showMsg}>按钮</button>     
      </div>
    );
  }
}

export default App;

setState 改变react状态

import React, { Component } from 'react';

class App extends Component {  
  constructor(props) {
    super(props);
    this.state = {num:1}
  }
  addNum(){
    this.setState({num:this.state.num+1})
  }
  render() {     
    return (

{this.state.num}

        {this.addNum()}}>按钮     

    );
  }
}

export default App;

用箭头函数是为了保证函数里面this的正确指向br 你也可以用bind方法

按钮

React 表单双向绑定

import React, { Component } from 'react';
class App extends Component {  
  constructor(props) {
    super(props);
    this.state = {num:1}
  }
  changeNum(e){
    this.setState({num:e.target.value})
  }
  render() {     
    return (
      <div className="App">
      <input type="text" value={this.state.num} onChange={this.changeNum.bind(this)}/>
      <h1>{this.state.num}</h1>
      </div>
    );
  }
}

export default App;

动态的添加更改class

import React, { Component } from 'react';
import './App.css';
class App extends Component {  
  constructor(props) {
    super(props);
    this.state = {bg:'red'}
  }
  changeClass(e){
    this.setState(pre=>{
      return ({bg:pre.bg==='red'?'blue':'red'});
    })
  }
  render() {     
    return (
      <div className="App">
        <button className={this.state.bg} onClick={this.changeClass.bind(this)}>按钮</button>
      </div>
    );
  }
}

export default App;

添加style

render() {   
    var css = {
      borderRadius:"6px",
      padding:"8px 16px",
      color:'#fff',
      background:'blue'
    }  
    return (
      <div className="App">
        <button style={css}>按钮</button>
      </div>
    );
  }
      }

React 条件渲染

条件性地渲染一块内容

三目运算符号

render() {
    var isLogin = true;
    return (
      <div className="App">
        {isLogin?'欢迎您回来主人':'请登陆'}      
      </div>
    );
  }

& &运算符

在 JavaScript 中,true && expression 总是返回 expression,而 false && expression 总是返回 false。
因此,如果条件是 true,&& 右侧的元素就会被渲染,如果是 false,React 会忽略并跳过它。

render() {
    var isLogin = false;
    return (
      <div className="App">
        {isLogin &&'欢迎您回来主人'}      
      </div>
    );
  }

列表渲染

我们可以使用 JavaScript 的 map() 方法来创建列表。

初始化列表数据

constructor(props) {
    super(props);
    this.state={
      list:[{name:'vue'},{name:'react'},{name:'angular'}]
    }
  }

map渲染列表

return (
      <div className="App">

        {this.state.list.map(
          (item,index)=>{
            return (
              <div key={index}>{item.name}</div>
            )
          }
        )}

      </div>
    );

完整代码

import React, { Component } from 'react';

class App extends Component {
  constructor(props) {
    super(props);
    this.state={
      list:[{name:'vue'},{name:'react'},{name:'angular'}]
    }
  }

  render() {
    return (
      <div className="App">        
        {this.state.list.map(
          (item,index)=>{
            return (
              <div key={index}>{item.name}</div>
            )
          }
        )}      
      </div>
    );
  }
}

export default App;

Key 可以在 DOM 中的某些元素被增加或删除的时候帮助 React 识别哪些元素发生了变化。因此你应当给数组中的每一个元素赋予一个确定的标识。
一个元素的 key 最好是这个元素在列表中拥有的一个独一无二的字符串。通常,我们使用来自数据的 id 作为元素的 key:
元素没有确定的 id 时,你可以使用他的序列号索引 index 作为 key:

组件生命周期

组件的生命周期可分成三个状态:

Mounting:已插入真实 DOM
Updating:正在被重新渲染
Unmounting:已移出真实 DOM


image

componentWillMount 
在渲染前调用,在客户端也在服务端。一般用的比较少,更多的是用在服务端渲染

1、组件刚经历constructor,初始完数据
2、组件还未进入render,组件还未渲染完成,dom还未渲染

componentDidMount 
在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。

组件第一次渲染完成,此时dom节点已经生成,可以在这里调用ajax请求,返回数据setState后组件会重新渲染

componentWillReceiveProps 
在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。

shouldComponentUpdate 
返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。 
可以在你确认不需要更新组件时使用。

componentWillUpdate
在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。

componentDidUpdate
 在组件完成更新后立即调用。在初始化时不会被调用。

componentWillUnmount
在组件从 DOM 中移除之前立刻被调用。

class Demo extends Component {
    constructor(props, context) {
            //如果想(在组件其他地方是可以直接接收的)使用props或context,则需要以参数形式传入。
            //只要组件存在constructor,就必要要写super,否则this指向会错误
            super(props, context);
            this.state = {
                data: 1
            };
    },
    componentWillMount () {
        // 在组件挂载之前调用,且全局只调用一次。如果在这个钩子里可以setState,render后可以看到更新后的state,不会触发重复渲染。
        // 该生命周期可以发起异步请求,并setState。(React v16.3后废弃该生命周期,可以在constructor中完成设置state)
        // 不推荐在这里发起ajax请求,若返回数据为空,则容易造成界面空白,影响渲染效果
    },
    componentDidMount () {
        //组件第一次渲染完成,此时dom节点已经生成,可以在这里调用ajax请求,返回数据setState后组件会重新渲染
    },
    componentWillReceiveProps (nextProps) {
        // 在接受父组件改变后的props需要重新渲染组件时用到的比较多
        // 通过对比nextProps和this.props,将nextProps setState为当前组件的state,从而重新渲染组件
        nextProps.data !== this.props.data && this.setState({
            data: nextProps.data
            },() => {
              console.log("new data...");
        });

    },
    shouldComponentUpdate (nextProps, nextState) {
        // react性能优化非常重要的一环。
        // 组件接受新的state或者props时调用,我们可以设置在此对比前后两个props和state是否相同,
        // 如果相同则返回false阻止更新,因为相同的属性状态一定会生成相同的dom树,
        // 这样就不需要创造新的dom树和旧的dom树进行diff算法对比,节省大量性能,尤其是在dom结构复杂的时候。
    },
    componentWillUpdate (nextProps, nextState) {
        // 组件初始化时不调用,只有在组件发生更新需要重新渲染时才调用
    },
    componentDidUpdate (prevProps, prevState) {
        // 组件初始化时不调用,组件更新渲染完成后调用,此时dom节点加载完成,可以获取到dom节点。
        // react只会在第一次初始化成功会进入componentDidmount,
        // 之后每次重新渲染后都会进入这个生命周期,这里可以拿到prevProps和prevState,即更新前的props和state。
        // 该钩子内setState有可能会触发重复渲染,需要谨慎判断,否则会进入死循环 
    },
    render () {
        return (
            <div>This is Demo!</div>
        );
    },
    componentWillUnmount () {
        // 组件将要卸载时调用,一些事件监听和定时器需要在此时清除。
    },
    componentDidCatch (error, info) {
        //React 16 中引入,用来 捕获组件的错误。
        //如果 render() 函数抛出错误,则会触发该函数。
        //错误在渲染阶段中被捕获,但在事件处理程序中不会被捕获。
    }
}

我们应当将AJAX 请求放到 componentDidMount 函数中执行,主要原因有下:

React 可能会多次频繁调用 componentWillMount,如果我们将 AJAX 请求放到 componentWillMount 函数中,那么显而易见其会被触发多次,自然也就不是好的选择。

如果我们将 AJAX 请求放置在生命周期的其他函数中,我们并不能保证请求仅在组件挂载完毕后才会要求响应。如果我们的数据请求在组件挂载之前就完成,并且调用了setState函数将数据添加到组件状态中,对于未挂载的组件则会报错。而在 componentDidMount 函数中进行 AJAX 请求则能有效避免这个问题。

componentDidMount() {
    this.getMovie();
}
getMovie(){
    fetch("http://www.endata.com.cn/API/GetData.ashx",{
        method:"post",
        body:"MethodName=BoxOffice_GetPcHomeList",
        headers:{"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}
    })
    .then(res=>res.json())
    .then(res=>{
        console.log(res)
    })
}


子组件调用父组件方法|向父组件传递参数

父亲传一个函数props

import React, { Component } from 'react';
import Child from './components/Child'
class App extends Component {  
  showMsg(msg){
    alert(msg);
  }
  render() {  
    return (
      <div className="App">
        <Child name="曾庆林" fun={this.showMsg}></Child>
      </div>
    );
  }
}

export default App;

子组件在箭头函数执行props

import React,{Component} from 'react' export default class Child extends Component{

render(){
        return (
            <div className="child">
                    <h1>我是子组件 我的名字是{this.props.name}</h1>
                    <button onClick={()=>{this.props.fun('我爱我的祖国')}}>调用父亲函数方法</button>                   
                    <hr/>
            </div>
        );
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容