尝试使用mithril.js过滤数据列表时遇到了问题。
我有两个组件:表单和inputWrapper。
在表单视图中直接使用m('input', { value: ...} )
时,过滤效果很好。
当使用包含输入且m.prop
与其值耦合的组件时,一切都变为amis。
在表单中我们有类似的内容:m.component( inputWrapper, { value: ... })
尝试过滤此列表时,视图会呈现错误的组件。
请查看this codepen以获得更清晰的图片。
我的猜测是,mithril diff引擎存储了一组缓存的组件并渲染它们,而不是在每次重绘时实例化新的组件。 然而,我还没有找到解决方案来做到这一点。请帮忙。
答案 0 :(得分:0)
为了能够遵循逻辑,我不得不重构你的代码,但设法让它运行起来。
缓存问题与控制器有关:在重绘时,如果给定类型的组件与前一个绘图中的相同类型的组件呈现在同一位置 - 且组件没有区分密钥 - 然后假设您要检索以前的控制器。对于组件,控制器存储视图使用的输入(而不是直接从其自己的args
输入读取的视图)。
解决这个问题的最简单方法是简单地摆脱控制器并直接读取输入,因为如果输入应该总是新鲜的话,它就没有用处。
// ---------------------------------
// component with an input
// ---------------------------------
const inputWrapper = {
view : ( ctrl, args ) =>
m('input[type=text]', args )
}
// ---------------------------------
// component that filters list
// ---------------------------------
m.mount( document.body, {
controller : function( attrs ) {
const filterTerm = m.prop( '(?:)' )
return {
filterTerm,
filterFunc : word => {
const term = filterTerm()
if ( _.isString( term ) && _.isString( word ) )
return word.search( new RegExp( term, 'i' ) ) > -1
},
someData : [ "long", "list", "of", "meaningful", "data", "really", "cool", "stuff"]
}
},
view : ( { filterTerm, filterFunc, someData }, attrs ) =>
m('form',
m('p',
m('input[type=text]', {
oninput : m.withAttr( 'value', filterTerm ),
placeholder : 'filter data'
})
),
m('p',
m('ul',
someData
.reduce( ( acc, val ) =>
( ( filterTerm() && filterTerm() == '/(?:)/' ) || filterFunc(val) )
? acc.concat( val )
: acc,
[]
)
.map( value =>
m('li',
m('input', { value } ),
m(inputWrapper, { value } )
)
)
)
)
)
} )
<script src="https://cdnjs.cloudflare.com/ajax/libs/mithril/0.2.5/mithril.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
但是,此修复揭示了其他问题:因为生成列表(和组件)的数据是在每次绘制时动态创建的,所以输入绑定到的数据结构只是在每次重绘时被丢弃,从父组件中的reduce和map函数生成一个新数组。
该问题的解决方案是在接收数据的父控制器中执行缩减,以便可以在下一次绘制中检索它。
我对代码做的其他一些小调整:
let
作业中执行的解构可以在函数参数签名中执行,从而减少冗长。const
代替let
清楚地表明分配给引用的值无法更改,这样可以更轻松地找到代码可能执行意外操作的位置。concat
允许您在单个表达式中生成新结构(而不是push
ing和然后 return
ing。答案 1 :(得分:0)
在又一轮挖掘秘银的文件后,我来这里回答我自己的问题。
如果我在初始化组件时提供了键:
m.component( InputWrapper, { key: 'distinguishingKey', value: ... } )
事情会好起来的。
谢谢,巴尼,提示:
......并且组件没有区分密钥 - ...
Leo Horie提供优秀的文件。 (如果我这周才读过......) http://mithril.js.org/mithril.component.html#data-driven-component-identity