1. class组件
复杂的组件,需要记录自己内部状态的话,使用class组件,因为function不能有局部变量和方法,而class可以有。
//一部分页面标签放在一个函数里
function App(){
return (
<div>
app
</div>
)
}
//必须继承组件,添加extends React.Component
class App2 extends React.Component{
constructor(props){ //声明变量必须写在constructor里面
super(props)//使用constructor必须写这个
this.state= { 变量必须写在this.state里
number:0
}
}
add(){
this.setState({
number: this.state.number += 1
})
}
render(){ //局部render
return (
<div>
app 2 {this.props.name}
<div>
{this.state.number}
<button onClick={this.add.bind(this)}>+</button>
</div>
</div>
)
}
}
render()
function render(){
ReactDOM.render(
<App2 name="qinglin" age="18"/>,
document.querySelector('#root'))
}
2. 函数组件
把组成一部分页面的标签写在一个函数中,叫做函数组件。
- 在上一节中说过React的作者的第一个创举,组件当中体现了第二个创举:标签的名字就是函数,标签的属性的key value 理解成一个对象,函数的参数就是这个对象。
例如:
let number = 0
add =()=>{
number += 1
render()
}
minus =()=>{
number -= 1
render()
}
//一部分页面标签放在一个函数里
function App(){
return (
<div>
//这里的Box1标签就是函数,代表页面一部分的标签,标签的属性其实是对象,下面两个函数的参数obj就是这个对象
<Box1 name="加一" />
</div>
)
}
function Box1(obj){
return (
<div class="parent">
我的名字是{obj.name}
<hr />
<span>{number}</span>
<button onClick={add}>+</button>
<button onClick={minus}>-</button>
</div>
)
}
render()
function render(){
ReactDOM.render(
//虚拟DOM,本质就是对象
<App/>, //这是XML语法
document.querySelector('#root'))
}
【涉及到的知识点】
-
this.setState ————
- 优点:回对更新优化,会把多次更新结果只进行一次渲染就能完成
- 缺点:同时带来了弊端,有时候会有多个执行语句时异步更新
-
DOM diff ——— react每次修改变量都会自动智能地去局部更新页面内,更新之前都会把最新信息跟之前相比较,然后只更新有变化的部分,这种非常友好的过程叫DOM diff。
3. 组件通信
3.1 父子通信
- 子组件向父级组件传递信息:
原理:父级组件传一个函数,子元素在必要时(回调)调用通信函数(通信函数被调用时还可以传给它一些参数页面中可以渲染出来)。
//代码示例
这个App是父元素
class App extends React.Component{
constructor(){
this.state={
...
}
this.setState({
....
})
}
通信函数1(){}
通信函数2(){}
//App父级组件会把两个通信函数分别传给子级组件div1 和 div2
render(){
return (
<div>
<div1 f1 = {this.通信函数1.bind(this)}></div1>
<div1 f2 = {this.通信函数2.bind(this)}></div1>
</div>
)
}
}
//两个div子组件会调用通信函数
//这个div1是子元素
class div1 extends React.Component{
....
this.state.通信函数1()
}
//这个div2也是子元素
class div2 extends React.Component{
....
this.state.通信函数2()
}
- 父级组件向子级组件传递信息:
父级组件通过 props 给子组件的某个属性传一个值function App(){ return ( <div> <span message="你好!"/> </div> ) } function span(props){ return ( <p>子级组件得到的信息是:{props.message}</p> ) } ReactDOM.renfer( <App />, document.querySelector("root") )
3.1 爷孙通信
原理:爷爷级组件把一个或多个函数传给父级组件,父级组件再把这个函数透传给子级组件,最后自己组建调用这个函数。
代码示例,
这个App是父元素
class App extends React.Component{
constructor(){
this.state={
...
}
this.setState({
....
})
}
通信函数1(){}
通信函数2(){}
//App爷爷级组件会把两个通信函数分别传给父级组件parent
render(){
return (
<div>
<parent
success1={this.success1.bind(this)}
success2={this.success2.bind(this)}
/>
</div>
)
}
}
function parent(props){
let 通信1 = props.通信函数1
let 通信2 = props.通信函数2
return (
<div class="playground">
//parent再把通信函数传给div孙子级组件
<Track1 通信={通信1} />
<Track2 通信={通信2}/>
</div>
)
}
div孙子级组件会调用通信函数
//这个div1是孙子组件
class div1 extends React.Component{
....
this.state.通信()
}
//这个div2也是孙子元素
class div2 extends React.Component{
....
this.state.通信2()
}
- 类似父子关系组件之间的通信就是这样一次传给函数,最后子级调用这个函数的过程。
4 . 任意组件之间通信
- 发布订阅模式(EventHub)
var eventHub = {
//发布事件
trigger(eventName,data){}, //参数一为事件名,参数二位要发布的数据
//订阅事件
on(eventName,function(){}) //参数一为事件名,参数二为调用函数
}
eventHub.on('事件名',function(){})//订阅,click是事件名称
eventHub.trigger('事件名',data)
-
单向数据流:
原理:一个组件向下延申拥有树形关系的子组件,那么如何在互相没有直接关系 的组件之间通信呢?对此React提供了一种发布订阅模式(eventHub)的功能,eventHub 的具体用法在上一内容中有。只要其中一个组件给页面发布修改请求,这个请求就会被最订阅机质收到,这个机质是个对象,只存在内存中,不会被渲染到页面中,订阅机制收到后给最高级的组件传递信息,然后由父向子级组件依次通过props传递调用函数最后被各个子组件调用,最后进行(DOM diff) 渲染。这样就可以在任意组件之间进行通信了。 -
Redux
使用eventHub发布订阅模式的特点是所有的动作都是通过事件来完成,数据必须放在顶层组件。- 下面是一些约定名词:
- store 所有存数据的地方
- store 对象中的对于数据的操作叫 reducer
- eventHub.on 订阅subscribe
- eventHub.trigger 发布action
- eventHub.trigger('eventName',data) eventName叫action type 、data 叫 payload
- 下面是一些约定名词:
-
Redux的优点:
1. eventHub的所有动作都是通过事件来进行的,而且事件名可以是任意的,所以可能会存在隐藏的Bug,对此Redux做出了调整:switch (action.type) { case 'event1': function() { } break; case 'event2': function() { } break; .... default: return { } }
就这样吧所有事件统一列在一个地方,防止重复使用
- Redux把所有数据写在顶层的组件中,并且只能只读取。
- 提高了前端的门槛,对于英语的要求较高。
5. Readux
- 使用Redux的步骤:
- 声明一个store,专门保存数据的,
声明时必须使用createStore,接受的参数叫counter的一个函数counter(state, action) {return 新的数据} //参数一为初始数据,参数二为### 1. class组件
- 声明一个store,专门保存数据的,
复杂的组件,需要记录自己内部状态的话,使用class组件,因为function不能有局部变量和方法,而class可以有。
//一部分页面标签放在一个函数里
function App(){
return (
<div>
app
</div>
)
}
//必须继承组件,添加extends React.Component
class App2 extends React.Component{
constructor(props){ //声明变量必须写在constructor里面
super(props)//使用constructor必须写这个
this.state= { 变量必须写在this.state里
number:0
}
}
add(){
this.setState({
number: this.state.number += 1
})
}
render(){ //局部render
return (
<div>
app 2 {this.props.name}
<div>
{this.state.number}
<button onClick={this.add.bind(this)}>+</button>
</div>
</div>
)
}
}
render()
function render(){
ReactDOM.render(
<App2 name="qinglin" age="18"/>,
document.querySelector('#root'))
}
2. 函数组件
把组成一部分页面的标签写在一个函数中,叫做函数组件。
- 在上一节中说过React的作者的第一个创举,组件当中体现了第二个创举:标签的名字就是函数,标签的属性的key value 理解成一个对象,函数的参数就是这个对象。
例如:
let number = 0
add =()=>{
number += 1
render()
}
minus =()=>{
number -= 1
render()
}
//一部分页面标签放在一个函数里
function App(){
return (
<div>
//这里的Box1标签就是函数,代表页面一部分的标签,标签的属性其实是对象,下面两个函数的参数obj就是这个对象
<Box1 name="加一" />
</div>
)
}
function Box1(obj){
return (
<div class="parent">
我的名字是{obj.name}
<hr />
<span>{number}</span>
<button onClick={add}>+</button>
<button onClick={minus}>-</button>
</div>
)
}
render()
function render(){
ReactDOM.render(
//虚拟DOM,本质就是对象
<App/>, //这是XML语法
document.querySelector('#root'))
}
【涉及到的知识点】
-
this.setState ————
- 优点:回对更新优化,会把多次更新结果只进行一次渲染就能完成
- 缺点:同时带来了弊端,有时候会有多个执行语句时异步更新
-
DOM diff ——— react每次修改变量都会自动智能地去局部更新页面内,更新之前都会把最新信息跟之前相比较,然后只更新有变化的部分,这种非常友好的过程叫DOM diff。
3. 组件通信
3.1 父子通信
- 子组件向父级组件传递信息:
原理:父级组件传一个函数,子元素在必要时(回调)调用通信函数(通信函数被调用时还可以传给它一些参数页面中可以渲染出来)。
//代码示例
这个App是父元素
class App extends React.Component{
constructor(){
this.state={
...
}
this.setState({
....
})
}
通信函数1(){}
通信函数2(){}
//App父级组件会把两个通信函数分别传给子级组件div1 和 div2
render(){
return (
<div>
<div1 f1 = {this.通信函数1.bind(this)}></div1>
<div1 f2 = {this.通信函数2.bind(this)}></div1>
</div>
)
}
}
//两个div子组件会调用通信函数
//这个div1是子元素
class div1 extends React.Component{
....
this.state.通信函数1()
}
//这个div2也是子元素
class div2 extends React.Component{
....
this.state.通信函数2()
}
- 父级组件向子级组件传递信息:
父级组件通过 props 给子组件的某个属性传一个值function App(){ return ( <div> <span message="你好!"/> </div> ) } function span(props){ return ( <p>子级组件得到的信息是:{props.message}</p> ) } ReactDOM.renfer( <App />, document.querySelector("root") )
3.1 爷孙通信
原理:爷爷级组件把一个或多个函数传给父级组件,父级组件再把这个函数透传给子级组件,最后自己组建调用这个函数。
代码示例,
这个App是父元素
class App extends React.Component{
constructor(){
this.state={
...
}
this.setState({
....
})
}
通信函数1(){}
通信函数2(){}
//App爷爷级组件会把两个通信函数分别传给父级组件parent
render(){
return (
<div>
<parent
success1={this.success1.bind(this)}
success2={this.success2.bind(this)}
/>
</div>
)
}
}
function parent(props){
let 通信1 = props.通信函数1
let 通信2 = props.通信函数2
return (
<div class="playground">
//parent再把通信函数传给div孙子级组件
<Track1 通信={通信1} />
<Track2 通信={通信2}/>
</div>
)
}
div孙子级组件会调用通信函数
//这个div1是孙子组件
class div1 extends React.Component{
....
this.state.通信()
}
//这个div2也是孙子元素
class div2 extends React.Component{
....
this.state.通信2()
}
- 类似父子关系组件之间的通信就是这样一次传给函数,最后子级调用这个函数的过程。
4 . 任意组件之间通信
- 发布订阅模式(EventHub)
var eventHub = {
//发布事件
trigger(eventName,data){}, //参数一为事件名,参数二位要发布的数据
//订阅事件
on(eventName,function(){}) //参数一为事件名,参数二为调用函数
}
eventHub.on('事件名',function(){})//订阅,click是事件名称
eventHub.trigger('事件名',data)
-
单向数据流:
原理:一个组件向下延申拥有树形关系的子组件,那么如何在互相没有直接关系 的组件之间通信呢?对此React提供了一种发布订阅模式(eventHub)的功能,eventHub 的具体用法在上一内容中有。只要其中一个组件给页面发布修改请求,这个请求就会被最订阅机质收到,这个机质是个对象,只存在内存中,不会被渲染到页面中,订阅机制收到后给最高级的组件传递信息,然后由父向子级组件依次通过props传递调用函数最后被各个子组件调用,最后进行(DOM diff) 渲染。这样就可以在任意组件之间进行通信了。 -
Redux
使用eventHub发布订阅模式的特点是所有的动作都是通过事件来完成,数据必须放在顶层组件。- 下面是一些约定名词:
- store 所有存数据的地方
- store 对象中的对于数据的操作叫 reducer
- eventHub.on 订阅subscribe
- eventHub.trigger 发布action
- eventHub.trigger('eventName',data) eventName叫action type 、data 叫 payload
- 下面是一些约定名词:
-
Redux的优点:
1. eventHub的所有动作都是通过事件来进行的,而且事件名可以是任意的,所以可能会存在隐藏的Bug,对此Redux做出了调整:switch (action.type) { case 'event1': function() { } break; case 'event2': function() { } break; .... default: return { } }
就这样吧所有事件统一列在一个地方,防止重复使用
- Redux把所有数据写在顶层的组件中,并且只能只读取。
- 提高了前端的门槛,对于英语的要求较高。
5. VanillaJs
-
使用Redux之关键函数:
声明一个store,专门保存数据的,
声明时必须使用createStore,接受的参数叫counter的一个函数``` counter(state, action) {return 新的数据} //这个函数提前声明,函数的参数一为初始数据, 参数二为操作数据的函数 var store = Redux.createStore(counter) //接受一个函数为参数 ```
-
使用redux的思路:
- dispatch一个action
- counter函数生成一个新的state,然后触发一个事件
- 上一步出触发的事件被subscribe函数接受,
- subscribe函数会调用render函数,然后重新render
- 第二次render之后在得到新的store,浏览器DOM diff 之后渲染页面
6. Redux
- react比vanilla好的地方是会DOM diff,局部更新。
7. React-Redux
7.1 API
- connect(mapStateToProps,mapDispatchToProps)(App)
一个括号为一个参数,第一个括号里可有多个参数,第二个括号为第二个参数 ;功能是把数据、数据变更动作、组件组合起来。
-
Provider() 从React-Redux引入之后以标签的形式写成包围组件,功能是获取state,然后通知到里面的每一个组件
-
写这一节博客,做了简单的项目[https://github.com/cnqinglin/react-redux-v1]之后的最大的感觉就是React社区的东西其实不难,但为什么总感觉很难是因为它给就概念都给了一个新的名字。
网友评论