React基础入门


参考Blog

阮一峰React入门实例教程
阮一峰Redux基础入门

关于React引发的思考

  • 声名式开发;
  • 组件化开发;
  • 可以与其他框架并存;
  • 函数式变成,便于前端的自动化测设;
  • 单向数据流 父组件向子组件传递的数据具有只读行;
  • 视图层框架 结合其他框架工具 Flux和redux等工具管理数据;

使用react脚手架工具快速创建一个项目

  • 在目录下打开cmd命令行工具;
  • 运行npx create-react-app my-app命令,快速创建一个项目(npm的版本需在5.2.0+);
  • 运行yarn start命令,启动项目,并在localhost:3000端口自动打开项目;
  • 项目成功运行在浏览器客户端,证明react脚手架成功搭建;

JSX语法

定义:通过在js文件引入react的包,可以直接写入html5标签元素,我们称之为jsx语法;
知识点:
1.ReactDOM内置组件是用来处理jsx语法;
2.通常定义组件名时,我们需要大写首字母,但是对于一般的H5标签,我们需要小写,用来区分组件和h5标签;
3.render函数的返回值,即组件html部分,有且只有一个根元素标签;
4.通常我们引入Fragment占位符,将html部分进行包裹;
6.通常定义组件名时,我们需要大写首字母,但是对于一般的H5标签,我们需要小写,用来区分组件和h5标签;
7.JSX使用{}进行包裹,内部可以写变量,三元表达式,也可以放入函数执行的结果;
8.{}内部不可以写对象或函数,但是可以显示对象里定义的key-value键值对;
9.行内属性style后面必须是一个对象,使用toString方法进行转译;
10.react区别于vue框架,是一种单向数据流,只能数据驱动视图;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React,{Component,Fragment} from 'react';
import ReactDOM from 'react-dom';
class App extends Component {
constructor(props){
super(props);
this.state = {

};
}
render() {
return (
<div>
<h2>hello world</h2>
</div>
);
};
};

ReactDOM.render(<App />, document.getElementById('root'));

render渲染函数

ReactDOM.render(jsx结构,container,callback());

  • 第一个参数: 当前操作的dom结构
  • 第二个参数: 目标容器
  • 第三个参数: 回调函数,会在dom放入容器之后,触发

createElement函数封装

目的: elenEle 等价

1
2
3
4
5
6
7
8
9
10
11
let ele = React.createElement(
'h1',
{id:'qqq',className:'www'},
'哈哈哈',
React.createElement('div',null,'呵呵呵')
)

let ele1 = <h1 id='qqq' className='www'>
哈哈哈
<div>呵呵呵</div>
</h1>

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
let fn = function (str){
return str.replace(/[A-Z]/g,function(n){
return '-' + n.toLowerCase()
})
}
class Element {
constructor(type,attr,children){
this.type = type
this.attr = attr
this.children = children
}
render(){
let ele = document.createElement(this.type)
for(let key in this.attr){
switch(key){
case 'htmlFor':
ele.setAttribute('for',this.attr[key]);
break;
case 'className':
ele.setAttribute('class',this.attr[key]);
break;
case 'style':
let str = ''
let obj = this.attr[key];
for(let key in obj){
str += `${fn(key)}:${obj[key]};`
}
str = str.slice(0,str.length-1);
ele.setAttribute('style',str)
break;
default:
ele.setAttribute(key,this.attr[key])
break;
}
}
this.children.forEach(item => {
let nEle = item instanceof Element ? item.render():document.createTextNode(item)
ele.app,endChild(nEle)
nEle = null;
});
return ele
}
}
let react = {
createElement(type,attr,...children){
return new Element(type,attr,children)
}
};
let reactDOM = {
render(ele,container){
container.appendChild(ele.render())
}
};

定义组件

定义:

  1. 创建一个App类,并继承react中component类的属性,这时候我们就创建一个App的组件;
  2. 无状态组件 : 没有state属性,通过props属性取得数据;
  • 使用函数定义组件=构造函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function Person(props){
    let {id,className} = props
    return(
    <div id = {id} className = {className}>
    hello world
    </div>
    )
    }
    ReactDOM.render(<div>
    <Person id = "qqq" className = 'www'></Person>
    </div>,document.getElementById('root'))
  • 使用class语法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Person extends Component {
    constructor(props){
    super(props)
    this.state = {

    }
    }
    render(){

    }
    }
    ReactDOM.render(<div>
    <Person id = "qqq" className = 'www'></Person>
    </div>,document.getElementById('root'))

组件间的通讯

知识点:

  1. react组件中的数据来源 一个是属性(props),一个是状态(state),
  2. 但是不能直接修改props中的数据,而state中的数据可以修改,但是需要用setState触发render函数;
  3. 在原生标签上,不能有对象的数据格式;
  4. 自定义组件,行内属性的值 类型不限, 可以是对象;
  5. 父组件通过行内属性向内属性向子组件传递数据;
    将属性包裹成一个对象,向子组件的constructor函数传递实参
  6. 子组件通过this.props拿到父组件的数据;
  7. 父组件通过自定义属性传递一个函数体,子组件通过this.props.xxx(参数),
    通过让函数体执行,结合传参数的方式修改父组件数据;
  8. setState函数,能触发render函数重新执行,合并渲染虚拟DOM,在Component的原型上;
  9. <button onClick = {this.props.add2.bind(1111,this.state.str2)}>按钮2</button>
    若方法是父组件中定义,那么子组件在调用时,不用在意this的指向问题,只要执行即可
    因为方法是在父组件中执行的时候,this已经被规定指向父组件;

事件

  1. 对应的事件对象,只能在函数执行的过程中可以获取;
  2. 事件执行完毕后就不能再获取到,React会把它设置成null,节省性能;
  3. 阻止默认事件 原生JS可以使用 e.preventDefault() 或者 e.returnValue = false(IE的方式);
  4. 在React中,只能使用e.preventDefault();
  5. 若bind后面除this外,有其他参数,则会将默认的事件对象当成最后一个参数,传参到add函数中;
  6. 改变组件原型函数执行时this指向的三种方法,以下代码为实现方式;
1
2
3
4
5
6
7
8
add(n,e){
console.log(n,e)
}
1)add = (n,e)=>{
console.log(n,e)
}
<div 2)onClick = {this.add.bind(this,2)}></div>
<div 3)onClick = {(e)=>{this.add(e)}}></div>

children类似于Vue中的插槽slot

用法:代码实现如下
用途: 使用该组件的人,可以通过children属性,渲染出组件标签类名内部包裹的内容

1
2
3
4
5
6
7
8
9
10
11
12
render(){
console.log(this.props.children)
return(<div className=''>
{this.props.children[3] || 'hahaha'}
</div>)
}

ReactDOM.render(<App id = '111'>
"我是你爸爸"
<div>hello</div>
<h1>world</h1>
</App>,window.root)

-------------本文结束感谢您的阅读-------------