-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
组件 #1
Comments
新的UI体系会引入Virtual Dom,或者是基于容器组件层级引入? |
不会,Server Render暂不在第一个版本考虑范围内,核心是MVVM式的绑定和变化追踪局部刷新,vue已经证实这种方式没有性能上的顾虑,san的特色是依靠强制Immutable来解除变化追踪的复杂性,简化整个逻辑和数据流来追求稳健 |
我觉得不要 replaceState 这个 api,一个定义良好的组件,具体的state数量应该是确定的,不应该动态增减,如果有增减需求,可以用高阶组合来做。固定的state也方便在开发阶段做类型检测,使得代码更加可预测。 |
是的。最早的设计里是打算用 |
经过和 @jinzhubaofu 沟通了一下,我们需要解决一个“发送请求前显示loading,请求结束消失”这样的需求,本质上一个事件处理函数可能需要多次修改状态 为此,除了原有的参数外,我们再添加一个叫 但是函数本身还是有 async remove({id}, output, resolve) {
// 可以在函数return前的任意时候调用`resolve`提供Action更新状态
resolve(state => ({...state}, loading: true));
try {
await service.removeTodo(id);
// return还是有,用来标识这个事件已经处理完成(这里可能就会涉及和事件处理有关的资源的回收等),
// 另外未来对于Optimisitc UI来说,只有这个Action可以做
return (state, output) => {
// 这个事件等效于`on-item-change`再判断`item.removed`,但我们更推荐对于业务有独立的事件
output('remove', id);
// 简单的属性修改可以用Object Spread
return {...state, removed: true};
};
}
finally {
resolve(state => ({...state, loading: false}));
}
} |
组件状态
不分state和prop,所有状态可访问性为公开,称为state
组件的状态是不可变的,即每次修改状态都会创建一个新的state
状态更新
对外暴露的方法为
patchState(partialState)
另外还有
replaceState(newState)
,用于更新整个状态,且replaceState(newState)
还会被用于数据流传递基于Immutable的设计下,组件收到一个新的状态(通过
replaceState(newState)
调用)时,只要检查引用是否与当前状态相等就行,如果不相等则直接开始进行数据的向下传递,不对状态进行任何深层的判断,这保证了数据流的简单,简单又进一步带动可靠,这是san-view的主要目的之一组件内部可通过
protected
的方法notifyStateChange({previousState, newState})
对外通知状态的变化,这一方法会触发相关的事件/回调事件处理
每一个事件处理函数接收当前的状态,并返回一个Promise,该Promise在resolve时提供一个函数(后称为Action),Action接收当前组件的状态并返回状态的补丁(参考上文
patchState
)同时事件处理函数和Action均接收一个
output
参数,该参数为一个函数,用于对外发送通知(使用事件或回调的形式,具体由组件控制)用范式表达为:
一个简单的业务逻辑如下:
注意事件处理函数得到的状态和Action得到的状态可能是不一样的(因为有异步)
事件处理函数的
this
为当前组件实例,但非常不建议使用任何带有this
访问的代码,尽可能保持事件处理函数是个纯函数一个事件相当于如下过程:
Promise<Action>
patchState
更新状态notifyStateChange
通知状态变化需要注意的是通过事件执行的新状态,都会自动通知状态变化,这与外部直接调用
patchState
不同注:最初设想一个事件处理函数是直接返回
Promise<newState>
的,但是考虑到异步会导致状态错乱,所以设计成了Promise<Action>
,这会提升一定的复杂性,但更稳健组件渲染
组件渲染的核心为
render(state)
,接收当前的状态进行处理组件渲染只会由状态变化触发(暂无其它触发手段),调用
patchState
后,使用一个所有组件共享的统一调度器进行更新调度调度器全局共享一个,通过异步管理,将所有组件的渲染计划收集起来,一个周期后统一处理,一个组件在周期内有多次状态更新,会由调度器进行合并
这会导致在某些时刻状态和界面是不同步的,但这并不重要
在与函数式的配合上,render方法的返回值当前还未决定
组件定义
从上文可以看到,组件中最频繁使用核心功能(状态更新、事件处理)都是纯函数,而不是当前社区中其他框架的依赖
this.state
等一堆状态这一特点决定了在san-view体系中,组件事实上是一个“状态的容器”,它本身的逻辑是纯函数,组件实例的存在用来存放状态,而这个存放本身对组件实现者也是透明的
我称这种组件为“纯组件”,与“函数式组件”不同,纯组件的特点是逻辑为纯函数,但本身具备对开发者透明的状态管理,这使得纯组件避开了一般组件状态与生命周期紧耦合难以测试的缺点,也不至于因为实际函数式组件导致数据流过于繁琐
其一个可见的特点为可以针对事件进行测试,可以参考一个简单的 普通组件 与 纯组件 的对比
对于特殊情况,如果一个事件处理函数不能是纯函数,需要用
@sideeffect
标记,这个标记本身没啥用,但配合一系列工具会有特殊的效果(待定)The text was updated successfully, but these errors were encountered: