React基础

202 阅读5分钟

渐进式框架的理解

渐进式框架: 一种最流行的设计思想,一般框架中都包含很多内容,这样会导致框架的体积臃肿,拖慢加载速度。真实项目中,我们使用一个框架,不一定使用全部的功能,此时我们应该把框架的功能进行拆分,用户想要什么,让其自己自由组合即可。

全家桶

vue的全家桶: 
vue-cli vue vue+router vuex axios(fetch) vue-element(vant) ...
react的全家桶
create-react-app react react-dom react-router-dom redux react-redux axios(fetch) antd  dva/saga/mobx...

React

REACT的核心部分,提供了Component类可以供我们进行组件开发,提供了钩子函数(生命周期函数--所有的生命周期函数都是基于回调函数完成的)

React-Dom

在react-dom中提供了Render的方法,Render方法能够把JSX语法(react独有语法)渲染为真实DOM(能够放到页面中展示的解构都为真实DOM)的组件.

/*
 * RectDOM.render([jsx],[CONTAINER],[CALLBACK]): 把JSX语法渲染到页面中
 *  jsx: react虚拟元素
 *  CONTAINER: 容器,我们想把元素呈现到页面中的哪个容器中
 *  CALLBACK:当把内容呈现到页面中触发的回调函数
*/

JSX

react的独有语法

import React,{ Component } from 'react'
import logo from './logo.png'

function getName(name){
    return name;
}

class App extends Component{
    render(){
        const name = "name";
        const pName = <p>哈哈哈</p>
        return(
            {/* 这是jsx中的注释写法 */}
            
            {/* JSX语法中,添加类名要写成className,因为class是一个关键字 */}
            <div className="app">
                {/* 在jsx中出现的{ }是存放js的,但是要求js代码执行完成有返回结果(js表达式) */}
                
                {/* 表达式: js合理的表达式 */}
                { name }
                
                {/* 函数也是表达式 */}
                { getName({name: '哈哈'}) }
                
                {/* JSX也是表达式 */}
                { pName }
                
                {/* 属性 */}
                <img src={ logo }  />
            </div> 
        )
    }
}

把JSX(虚拟DOM)变为真实的DOM

import React from 'react';
import ReactDOM,{ render } from 'react-dom';  // 从REACT-DOM中导入一个ReactDOM,逗号后面的内容是把ReactDOM这个对象结构出来;

let styleObj = { color: 'red' }
ReactDOM.render(<h1 id="title" className="title" style={ styleObj }>哈哈哈</h1>,root);

JSX渲染过程

1. 基于BABEL中的语法解析模块(babel-preset-react)把JSX语法编译为React.CreateElement(...)结构.

// <h1 id="title" className="title" style={ styleObj }>哈哈哈</h1>
编译成
React.createElement("h1", {
    id: "title",
    className: "title",
    style: styleObj
}, "\u54C8\u54C8\u54C8");

2.执行React.createElement(type,props,children),会创建一个对象,这个对象就是虚拟DOM.

let styleObj = {color: 'red'};
console.log(
    React.createElement("h1", {
        id: "title",
        className: "title",
        style: styleObj
    }, "\u54C8\u54C8\u54C8")
)
// 执行结果: 会创建一个对象,这个对象就是虚拟DOM
 /*
  * type: 'h1',
  * ref: '',
  * key: '',
  * ...
  * props:{
        id:'',
        className: '',
        style: { color: 'red'},
        children: '哈哈哈',     // 存放的是元素中的内容.
    }
  * __proto__: 
 */

3.ReactDOM.render(JSX语法最后生成的对象,容器),基于RENDER方法吧生成的对象动态创建为DOM元素,插入到指定的容器中.

4.JSX->真实DOM的过程源码实现

组件

React中创建组件有两种方式

1.函数声明式组件
2.基于继承COMPONENT类来创建组件

组件祥细讲解

循环操作与条件判断

import React,{ Component } from 'react';
export default class CompType extends Component{
    constructor(props){
        super(props);
        this.state = {
            title: '',
            goods: [
                {id: 1, name: '苹果', price: '12',},
                {id: 2, name: '香蕉', price: '10',},
                {id: 3, name: '橘子', price: '11',}
            ],
            isShow: false,
        }
        setTimeout(()=>{
            this.setState({
                title: '哈哈哈'
            })
        })
    }
    render(){
        // 循环操作 (map)
        const goods = this.state.goods.map(good=> {
            console.log(good);
            return (<li key={good.id}>{ good.name }</li>)
        })
        
        // 循环操作
        return(
            <div>
                {/* 条件语句 */}
                { this.state.title && <h1>{ this.state.title }</h1> }
                { this.state.isShow ? <h1>我输条件判断</h1> : null }
                
                {/* 循环操作 */}
                <ul>{ goods }</ul>
            </div>
        )
    }
}

父子组件之间的通讯

/*
父组件把信息传递给子组件:
    基于属性传递即可(而且传递是单方向得:只能父亲通过属性把信息传递给儿子,儿子不能直接把信息作为属性传递给父亲)
	
	后期子组件中得信息要修改:可以让父组件传递给子组件得信息发生变化(也就是子组件接受得属性发生变化子组件会重新渲染 =》componentWillReceiveProps钩子函数)
	
	只要实现点击子组件按钮得时候,可以修改父组件PANEL的状态信息,panel的状态改变,panel回重新执行RENDER渲染,而重新执行RENDER的时候,会把最新的状态值作为哦属性,传递给子组件HEAD,HEAD接受的属性值发生变化,HEAD组件也会重新渲染。
	类似于这种”子改父“的操作,我们需要是要以下技巧完后
		1.把父组件中的一个方法,作为属性传弟给子组件
		2.在子组件中,把基于属性传递进来的方法,再合适的时候执行(相当于在执行父组件的方法,而这个方法中完全可以操作父组件中的信息)
*/ 
/* HEAD */
class Head extends React.Component{
	constructor(props){
		super(props)
	}
	render(){
		return <div className='panel-heading'>
			<h3 className='panel-title'>
				{/* 子组件通过属性获取父组件传递过来得内容 */}
				点击次数: {  this.props.count }
			</h3>	
		</div>
	}
} 
/* BODY */
class Body extends React.Component{
	constructor(){
		super()
	}
	render(){
		return <div className='panel-body'>
			<button className='btn btn-success' onClick={ this.props.callback }>点我啊!</button>	
		</div>
	}
} 

class Panel extends React.Component{
	constructor(){
		super()
		this.state = {
			n:0
		}
	}
	fn = () => {
		//修改PANEL的状态信息
		this.setState({
			n: this.state.n+1
		})
	}
	render(){
		return <section className='panel panel-default'>
			
			{/*  父组件中在调取子组件得时候,把信息通过属性传递给子组件 */}
			<Head count={ this.state.n } />
			{/* 父组件把自己的一个方法基于属性传递给子组件,目的是在子组件中执行这个方法 */}
			<Body callback = { this.fn } />
		</section>
	}
}

生命周期

看这里


细节之处,略有疏漏,如有不足或者错误的地方,欢迎大佬批评并加以指正.谢谢.