Dav*_*ing 11 javascript reactjs mobx
当我从套接字获取新转储时,我需要替换我的observable对象中的数据:
class Store {
@observable data = { foo: 'bar' }
replaceFromDump(newData) {
this.data = newData
}
}
const store = new Store()
store.replaceFromDump({ foo: 'bar' })
// { foo: 'bar' } can be a huge amount of JSON
Run Code Online (Sandbox Code Playgroud)
但是,我注意到数据对象扩展时的性能命中,可能是因为即使某些属性/值相同,MobX也会在任何地方触发反应.
有一种"更聪明"的方式吗? - 我在想f.ex只替换对象的受影响部分会比替换整个observable更好吗?
我在这里做了一个小演示,解释了我的意思:https://jsfiddle.net/yqqxokme/.即使数据完全相同(预期),更换对象也会引起新的反应.但我确信有一种方法可以像在merge()
函数中一样改变数据对象的受影响部分.
所以这里有一些事情和案例.我已将转储功能更改为以下模拟更改
variations = [
{foo: 'bar'},
{foo: 'bar'},
{foo: 'bar2' },
{foo: 'bar2' },
{foo: 'bar2', bar: {name: "zoo"} },
{foo: 'bar2', bar: {name: "zoo"} },
{foo: 'bar2', bar: {name: "zoo2"} },
{foo: 'bar2', bar: {name: "zoo2"} },
{foo: 'barnew', bar: {name: "zoo2", new: "yes"} },
{foo: 'barnew', bar: {name: "zoo2", new: "no"} },
{foo: 'barnew', bar: {name: "zoo2", new: "no"} }
]
i=0;
dump = () => {
i++;
i = i%variations.length;
console.log("Changing data to ", variations[i]);
store.replaceFromDump(variations[i])
}
Run Code Online (Sandbox Code Playgroud)
使用extendObservable
现在,如果你使用下面的代码
replaceFromDump(newData) {
extendObservable(this.data, newData)
}
Run Code Online (Sandbox Code Playgroud)
并通过转储循环运行它,输出如下
事件bar
将在您获得更改之前不会开始提升foo
,这发生在以下更改
{foo: 'barnew', bar: {name: "zoo2", new: "yes"} },
Run Code Online (Sandbox Code Playgroud)
结果:新密钥只能观察现有的可观察密钥更改
使用地图
在这里我们改变代码如下
@observable data = map({
foo: 'bar'
})
replaceFromDump(newData) {
this.data.merge(newData)
}
Run Code Online (Sandbox Code Playgroud)
结果:数据仅合并,不会删除.您还将获得重复事件,因为它是仅合并选项
使用对象差异
您可以使用如下所示的对象差异库
https://github.com/flitbit/diff
您可以更新如下代码
@observable data = {
foo: 'bar'
}
replaceFromDump(newData) {
if (diff(mobx.toJSON(this.data), newData)){
this.data = newData;
}
}
Run Code Online (Sandbox Code Playgroud)
结果:事件仅在数据更改时发生,而不是在重新分配到同一对象时发生
使用Diff和应用Diff
使用我们之前使用的相同库,我们可以只应用所需的更改
如果我们改变代码如下
replaceFromDump(newData) {
observableDiff(toJSON(this.data), newData, d => {
applyChange(this.data, newData, d);
})
}
Run Code Online (Sandbox Code Playgroud)
如果运行上面的命令,我们得到以下输出
结果:仅观察到对初始密钥集的更改,请不要删除其间的密钥
它还为您提供以下格式的差异
{"kind":"E","path":["foo"],"lhs":"bar2","rhs":"barnew"}
{"kind":"N","path":["bar","new"],"rhs":"yes"}
Run Code Online (Sandbox Code Playgroud)
这意味着您可以根据需要更好地控制字段名称
下面是我使用的小提琴,大多数代码都有评论,但是如果你需要查看下面的导入使用
https://jsfiddle.net/tarunlalwani/fztkezab/1/
您可以阅读有关优化组件的信息:https ://mobx.js.org/best/react-performance.html
默认情况下,Mobx 仅触发在渲染函数中使用状态的组件。因此,并非所有组件都会被触发渲染。
React 渲染所有使用已更改的 props 的子组件。
也就是说,更改的状态越多,需要重新渲染的次数就越多。因此,我建议仅同步更改并使用@action
装饰器来确保渲染仅完成一次,而不是在每次对状态进行更改时进行渲染。
@observable data = {}
@action
replaceChanges(partialNewData) {
Object.keys(partialNewData).forEach(propName => {
this.data[propName] = partialNewData[propname];
}
}
Run Code Online (Sandbox Code Playgroud)
Mobx 不会检查更改后的状态是否实际相同。因此,即使更改同一对象的状态也可能会触发重新渲染。(https://mobx.js.org/best/react.html)
是的,正如您所说:您还可以仅针对已更改的属性在旧状态上深度合并/覆盖新状态。这也会触发更少的重新渲染。
如果您正确编写代码(例如:不要在 React 渲染方法中使用 Labmda 语句),您的代码应该非常有效地重新渲染。
归档时间: |
|
查看次数: |
1333 次 |
最近记录: |