大家好,我卡颂。
有3个容易混同的前端框架概念:
- 响应式更新
- 单向数据流
- 双向数据绑定
在持续浏览本文前,读者能够思考下是否明确晓得三者的含意。
这三者之所以容易混同,是因为他们尽管同属前端框架领域内的概念,但又不是同一形象层级的概念,不好间接比拟。
本文会从3个形象层级动手解说这三者的区别。
欢送退出人类高质量前端交换群,带飞
响应式更新
响应式更新也叫细粒度更新。同时,最近前端圈比拟火的Signal
这一概念形容的也是响应式更新。
抽象的讲,响应式更新形容的是状态与UI之间的关系,即状态变动如何映射到UI变动。
思考如下例子(例子来自what are signals一文):
function TodoApp() { const [todos, setTodos] = useState( [{ text: 'sleep', completed: false }] ) const [showCompleted, setShowCompleted] = useState(false) const filteredTodos = useMemo(() => { return todos.filter((todo) => !todo.completed || showCompleted) }, [todos, showCompleted]) return ( <TodoList todos={filteredTodos} /> )}
在TodoApp
组件中,定义了两个状态:
- 待办事项
todos
- 是否展现实现的事项
showCompleted
以及根据上述状态派生出的状态filteredTodos
。最终,返回<TodoList/>
组件。
如果todos
状态变动,UI
该如何变动?即咱们该如何晓得状态变动的影响范畴?这时,有两个思路:
- 推(
push
) - 拉(
pull
)
推的原理
咱们能够从变动的状态(例子中为todos
)登程,依据状态的派生关系,一路推下去。
在例子中:
todos
变动filteredTodos
由todos
派生而来,变动传导到他这里<TodoList/>
组件依赖了filteredTodos
,变动传导到他这里- 确定了
todos
变动的最终影响范畴后,更新对应UI
这就建设了状态与UI之间的关系。
除了推之外,还有一种被称为拉的形式。
拉的原理
同样的例子,咱们也能建设状态与可能的UI变动的关系,再反过来推导UI
变动的范畴。
在例子中:
todos
变动- 可能有
UI
变动(因为建设了状态与可能的UI变动的关系) UI
与<TodoList/>
组件相干,判断他是否变动<TodoList/>
组件依赖filteredTodos
,filteredTodos
由todos
派生而来,所以filteredTodos
是变动的- 既然
filteredTodos
变动了,那么<TodoList/>
组件可能变动 - 计算变动的影响范畴,更新
UI
在支流框架中,React
的更新以推为主,Vue
、Preact
、Solid.js
等更多框架应用拉的形式。
本文聊的响应式更新就是拉这种形式的一种实现。
单向数据流
咱们能够发现,不论是推还是拉,他们都须要计算变动的影响范畴,即一个状态变动后,到底有多少组件会受影响。
那么,从框架作者的角度登程,是心愿减少一些束缚,来缩小计算影响范畴这一过程的复杂度。
同样,从框架使用者的角度登程,也心愿减少一些束缚,当计算影响范畴出bug
后,更容易排查问题。
这就有了单向数据流。
单向数据流是一条约定,他规定了当状态变动后,变动产生的影响只会从上往下传递。
思考如下例子:
function Parent() { const [num] = useState(0); return <Child data={num}/>;}function Child({data}) { const isEven = data % 2 === 0; return <GrandChild data={isEven}/>;}function GrandChild({data}) { return <p>{data}</p>;}
<Parent/>
组件的状态num
作为props
传给<Child/>
组件,再作为props
传给<GrandChild/>
组件,整个过程只能自上而下。
单向数据流并不是实现前端框架必须遵循的准则,他的存在次要是为了缩小开发者的心智累赘,让状态变动后,计算影响范畴这一过程更可控。
双向数据绑定
当本文开篇聊响应式更新时,探讨的是状态与UI的关系,这是将框架作为一个整体来探讨,形象层级比拟高。
当咱们持续聊到单向数据流时,探讨的是状态变动的影响范畴在组件间单向扩散,这是组件与组件之间的关系,形象层级降落了一级。
接下来咱们要探讨的双向数据绑定,探讨的是单个组件内产生的事。
双向数据绑定是状态+扭转状态后触发的回调相结合的语法糖。
这里不探讨框架语境下「语法糖」一词是否齐全精确
比拟出名的双向数据绑定实现,比方Vue
中的v-model
语法:
<input v-model=‘data’/>
相当于如下状态+事件回调的组合:
<input @input='onInput' :value=‘data’ />
实际上晚期React
中也有相似实现,名叫LinkedStateMixin,只是早已被废除
总结
咱们能够用一张图概括本文介绍的3个概念之间的关系:
概括起来次要是两点:
- 他们都是前端框架领域内的概念
- 他们属于不同形象层级的概念
其中:
- 双向数据绑定形容的是组件内逻辑与视图的关系
- 单向数据流形容的是组件之间的关系
- 响应式更新形容的是状态与UI之间的关系