react

255 阅读8分钟

react的特点

响应式UI

作为开发者,你只需编写你想要的是什么,React 自己会弄清楚该怎么做。当数据变化时,UI 会相应地发生改变。你无需再关心 DOM 的更新,React 会自动帮你完成。响应式 UI 的理念大大地简化了 UI 开发。

组件化

虚拟Dom

jsx

jsx其实就是javaScript对象

如果想要在html标签中使用js 需要把js用{}括起来

以下都是在index.js中实现 需要引入

import ReactDom from 'react-dom'
import React from 'react'

使用jsx的规范语法

超过一个标签时 必须使用一个根标签包裹

let ele = <h1>hello</h1><span>world</span>
//第一种使用一个标签包裹
let ele = <div><h1>hello</h1><span>world</span></div>
//第二种使用空标签 包裹
let ele = <><div><h1>hello</h1><span>world</span></div></>
//第三种 使用<React.Fragment></React.Fragment>包裹
let ele = <React.Fragment><h1>hello</h1><span>world</span></React.Fragment>
ReactDom.render(ele,document.getElementById('app'))

区分大小写

let ele = <Div>hello</Div> //'Div' is not defined  react/jsx-no-undef
ReactDom.render(ele,document.getElementById('app'))

它的属性值必须用引号引起来

let ele = <h1 id=a1>hello</h1> //错误写法
let ele = <h1 id='a1'>hello</h1>
ReactDom.render(ele,document.getElementById('app'))

在jsx中不能直接使用class 应该使用className

let ele = <div class='myele'>hello</div> //错误写法
let ele = <div className='myele'>hello</div>
ReactDom.render(ele,document.getElementById('app'))

使用style的方式

let ele = <div style='color:red'>hello</div> //错误写法
let ele = <div style={{'color':'red'}}>hello</div>
ReactDom.render(ele,document.getElementById('app'))

jsx的所有标签都要闭合 包括单标签 双标签

let ele = <div><h1>hello</h1><img ></div> //错误写法
let ele = <div><h1>hello</h1><img /></div>
ReactDom.render(ele,document.getElementById('app'))

jsx中存放的数据类型

// jsx中可以放字面量
let ele = <div>123</div>
// jsx中可以放运算符 在jsx中 如果想要在html标签中放js 需要把js放到{}里面
let ele = <div>{1+1+1}</div>
//jsx可以放变量
let name = 'wangcai'
let ele = <div>{name}</div>
let ele = <div>{name +'xiaoqiang '}</div>
//jsx中可以放函数调用
let ele = <div>{Math.random()}</div>
//jsx中可以放jsx
let name = <strong>wangcai</strong>
let ele = <div>{name}</div>
// ReactDom.render(ele,document.getElementById('app'))

react中没有v-if

使用if else实现

let isLogin = false
let ele = ''
if(isLogin){
    ele = <strong>登陆成功</strong>
}
else{
    ele = <strong>登陆失败</strong>
}
ReactDom.render(ele,document.getElementById('app'))

使用三元运算符实现

let isLogin = false
let ele = isLogin ? '登陆成功' : '登陆失败'
ReactDom.render(ele,document.getElementById('app'))

react中没有v-for

使用map实现

let name = ['vue.js','react.js',"angular.js"]
let ele = <div><ul>{name.map((item,index)=><li key={index}>{item}</li>)}</ul></div>
ReactDom.render(ele,document.getElementById('app'))

react 都是组件化

React 是围绕可重用组件的概念设计的。你定义小组件并将它们组合在一起形成更大的组件。

无论大小,所有组件都是可重用的,甚至在不同的项目中也是如此。 组件分为有状态组件 和 无状态组件 区分就是组件内是否有state

有状态组件

有状态组件中的数据分为两种 一种是自己内部的state(放到constructor中),通过this.state.xxx进行访问,它可以改变state中的状态(使用setState进行改变),但是其他的组件不可以改变状态,另一种是从上一层接受的数据(使用this.props.xxx),不可以改变数据,如果想要使其改变,只能让父组件重新赋值

使用类组件进行写的话 里面必须有一个render钩子函数 这个钩子函数必须return

在App.js

import React,{Component} from 'react'
class App extends Component{
    constructor(props){
        super(props)
        this.state={
            name:'wangcai'
        }
    }
    render(){
        return(
            <>
             <div>{this.state.name}</div>
             <button onClick={this.updateName.bind(this}>修改name</button>
             <p>{this.props.age}</p>
            </>
        )
    }
    updateName(){
        this.setState({
            name:'xiaoqiang'
        })
    }
}

无状态组件

无状态组件其实就是使用函数形式写的组件,它的内部没有state,状态都是从上层获取到的,使用props.xxx进行获取,它不能调用this,没有生命周期也就是没有钩子函数里面必须return

在App.js

import React from 'react'
function App(props){
    return(
        <div>{props.name}</div>
    )
}

在index.js

import React from 'react'
import ReactDom from 'react-dom'
import App from './App'

ReactDom.render(<App name='wangcai'></App>,document.getElementById('app'))

在index.html中

<div id='app'></div>

react中的方法

class App extends Component{
    constructor(){
        this.state={
            name:'wangcai'
        }
    }
    render(){
        return(
            //jsx 这里的this都是指向App组件
            <div>{this.state.name}</div>
            <button onClick={this.updateName}>修改name</button>
        )
    }
    updateName(){
        console.log(this)
        //会输出undefined 因为只有在jsx中this是指向App这个组件
        //所以需要手动的绑定this
    }
}

给方法手动绑定this的方法

在构造器中(constructor)中进行绑定

constructor(){
        this.state={
            name:'wangcai'
        }
        this.updateName=this.updateName.bind(this)
    }

在调用方法时进行绑定

<button onClick={this.updateName.bind(this)}>修改name</button>

在jsx中直接实现方法

<button onClick={console.log(this)}>修改name</button>

有状态的组件进行父传子

在App.js 父组件传子组件,不仅可以传数据,也可以传方法 它需要一级一级的往下传

import React,{Component} from 'react'
import Children from './Children'
//在父组件中引入子组件 不用注册 直接使用 
//如果传值的话 在父组件中设置数据 在子组件中接受数据

// 导入一个组件在jsx中使用 vue中是在tempate中使用  

// 每一个组件中都有一个state,react和vue一样,也可以使用props
// vue中  每一个组件中都一个data    数据源:data  props

// props在vue主要是用来传递数据的,实现父子通信的,是父给子传递数据。
// react中props也是用来传递数据,实现通信的,也是父传子,可以传递数据,也可以传递方法

// 如何使用Props?
// 需要有父组件和子组件
// 在父中设置数据,在子中获取数据
// 子中通过this.props.属性名来获取数据
class App extends Component{
    render(){
        return(
            <>
                <h1>父组件</h1>
                <Children></Children>
                {/* <Children age={100}></Children> */}
                {/* <Children age={'wangcai'}></Children> */}
            </>
        )
    }
}

export default App

在Children.js中

可以对接受的数据进行验证 使用propoTypes验证 使用defaultProps进行默认值

import React,{Component} from 'react'
import PropTypes from 'prop-types'

// 子中接收到数据后,能改变数据吗?
// vue中可以改变,但是不推荐
// vue中数据源:data props    data是每一个组件都有的,props是别人传递的数据
// props是别人传递的,人家不建议你去修改数据   如果你要经常修改数据,把数据定义到data中

// react中的数据源也是有两个:state  props
// 尽量使用props  在react中获取数据推荐在上层组件中获取, 然后传递给子组件,子组件通过this.props接收实使用
class Children extends Component{
    constructor(props){
        super(props)
    }
    render(){
        return(
            <>
                <p>子组件</p>
                {/* 在子组件中直接使用this.props.age就可以接受父组件传入的数据 */}
                <p>{this.props.age}</p>
            </>
        )
    }
   

}
// 检验传入的数据是不是number类型的
Children.propTypes={
    age:PropTypes.number 
}
//不传入数据的时候 默认为111
Children.defaultProps = {
    age:111
}

export default Children

无状态的父传子

import React from 'react'
import PropTypes from 'prop-types'

//传统的写法  下面是箭头函数形式
function App(props){
     return(
         <div>
             <h1>无状态组件</h1>
             <p>{props.name}</p>
         </div>
     )
 }

 const App = (props)=>{
     return(
         <div>
             <h1>无状态组件</h1>
         </div>
     )
 }

//上面的简化形式 把return和{}省略掉
const App = props =>(
        <div>
            <h1>无状态组件</h1>

            {/* 无状态组件中没有this */}
            {/* <p>{this.props.name}</p> */}

            {/* 直接使用props.name */}
            <p>{props.name}</p>
        </div>
    )
//检验传过来的数据
App.propTypes = {
    name:PropTypes.string
}
//如果没有传过来数据  设置默认数据
App.defaultProps = {
    name:'xxx'
}

export default App

// 无状态组件 就是函数形式的组件
// 有状态组件 就是class形式的组件

// 无状态组件指这个组件中没有state  数据源是props
// 传递的数据可以校验,propTypes 

特点:

    1,function  无状态组件不会被实例化,性能高
    2,无状态组件不能访问this
    3,无状态组件没有生命周期,也就是没有钩子函数
    4,无状态组件数据源只能靠props
     react建议,尽可能地使用无状态组件

state vs props ?

state是组件内部定义的数据  props是别人传递的数据  
state在组件内部初始化,自身可以修改数据(this.setState),别人是不能修改,可以
把state当成局部的,只能被自身使用的数据源,当state改变了,那么会导致组件重新渲染
props主要是父传给子的数据 ,在react中子中是没有办法修改props接收过来的数据 
如果要修改一个别人传递过来的一个props,只能再让别人重新传递过来一个新的Porps

尽可能少的使用state,尽可能多的使用props 

根据state可以把组件分成两类:有状态组件(有state)   无状态组件(无state)

有状态组件通常使用class来定义  
无状态组件通常使用function来定义