美文网首页
【转】3个容易混淆的前端框架概念

【转】3个容易混淆的前端框架概念

作者: 涅槃快乐是金 | 来源:发表于2023-03-07 22:58 被阅读0次

    大家好,我卡颂。

    有3个容易混淆的前端框架概念:

    1. 响应式更新
    2. 单向数据流
    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)出发,根据状态的派生关系,一路推下去。

    在例子中:

    1. todos变化
    2. filteredTodostodos派生而来,变化传导到他这里
    3. <TodoList/>组件依赖了filteredTodos,变化传导到他这里
    4. 确定了todos变化的最终影响范围后,更新对应UI

    这就建立了状态与UI之间的关系

    除了之外,还有一种被称为的方式。

    拉的原理

    同样的例子,我们也能建立状态与可能的UI变化的关系,再反过来推导UI变化的范围。

    在例子中:

    1. todos变化
    2. 可能有UI变化(因为建立了状态与可能的UI变化的关系
    3. UI<TodoList/>组件相关,判断他是否变化
    4. <TodoList/>组件依赖filteredTodosfilteredTodostodos派生而来,所以filteredTodos是变化的
    5. 既然filteredTodos变化了,那么<TodoList/>组件可能变化
    6. 计算变化的影响范围,更新UI

    在主流框架中,React的更新以为主,VuePreactSolid.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之间的关系

    原文:https://segmentfault.com/a/1190000043512498

    相关文章

      网友评论

          本文标题:【转】3个容易混淆的前端框架概念

          本文链接:https://www.haomeiwen.com/subject/ydenldtx.html