这是我参与「第四届青训营 」笔记创作活动的第10天
今天讲的是响应式系统与React的关系。
首先什么是响应式系统,那么我们就要知道什么是转换式系统。转换式系统的特点就是给定输入,求解输入。编译器就是一个很复杂的转换式系统。
而在我们的前端代码中我们需要的是监听事件再做出行为。这是响应式的特点监听事件,消息驱动。例如UI界面和监控系统。
状态归属
在设计页面时,我们要考虑数据存放的位置。一般我们存放在需要使用数据的组件们共同的父组件中。方便数据的改变和调用。
我们
下列是子组件利用父组件的方法改变数据:
在app组件中定义方法:
// 将新事项添加进todos
addTodo (todoObj) {
this.todos.unshift(todoObj)
},
并将此方法传给Myheader组件:
<MyHeader :addTodo="addTodo" />
组件化
- 组件内部拥有私有状态State
- 组件接收外部的Props状态提供复用性
- 根据当前的State/Props,返回一个UI
老师提出了3个问题:
首先,我们把React是看作单向数据流,父组件向子组件传递数据。 其次,在组件树外我们设立一个仓库来存放数据,这样我们就不需要一层层的传递数据。这种方式我们在后面进行举例理解。 最后更新DOM我们使用虚拟DOM来实现消息驱动。
响应式编程
代码如下:
function Components(props) {
// props 是父组件传入的状态
const { url }=props;
this.text='点击我'; // 状态
// 返回一个‘UI’
return (<div>
<SubComponent props={{ color: 'red' }}></SubComponent>
<img src={ url }>
<button>text</button>
</div>
)
}
代码符合我们的响应式编程设计,但我们能实现吗?
生命周期
这里介绍最主要的生命周期:
React (hooks)
// 首先引入useState等hooks函数
import React, { useState } from 'react;
function Example () {
// 声明一个状态属性 count
const [count,setCount] = useState(0);
// 副作用函数 只在渲染时调用一次
useEffect(() => {
document.title=`you clicked ${count} times`
})
// 返回DOM
return (
<div>
<p> 你点击的{{ count }} 次数</p>
<button onClick={()=> setCount(count+1)}>
点击我
</button>
</div>
)
};
React 实现
首先我们来列举一下困难:
- 我们的JSX不符合JS标准 这里很好解决,我们将代码转译成js代码即可。例如:
return(<div className="root"><img src={url}/></div>)
可以转译成
return React.createElement("div",{className:"root"},React.createElement("img",{src:url}));
- 返回的JSX发生改变时,如何更新DOM 解决这个问题,react使用 Virtual DOM(虚拟DOM)
但是这里又出现一个问题,浏览器渲染DOM元素耗费时间是相对较长的,如果我们从头到尾重新渲染,那么性能是非常差的。
这个时候我们就要使用Diff算法来局部更新元素。
这个时候我们就要去想如何Diff。
要Diff算法执行时间,还是减少DOM更新次数
我们针对不同的情况来diff
- State/Props更新时,要重新触发render函数
状态管理库
什么是状态管理库?我的理解就是统一管理我们组件状态数据的仓库。
react的状态管理库的推荐,其中Xstate是利用状态机原理来管理。
状态机原理,就是设定一个状态表根据当前状态收到的外部事件来进入下一状态。
// 存储状态数据
state:{
count:1,
name:'张三',
age:18,
phone:'10086XXX'
}
action:{
green(){
setTimeout(()=>{
count+=1
),6000}
}