秘银过滤组件列表

时间:2016-06-23 10:22:31

标签: components filtering mithril.js

尝试使用mithril.js过滤数据列表时遇到了问题。

我有两个组件:表单和inputWrapper。

  • 表单显示一个包含多个输入字段的表单,每个字段都有一个值。
  • 表单还有一个允许过滤数据的搜索输入。

在表单视图中直接使用m('input', { value: ...} )时,过滤效果很好。

当使用包含输入且m.prop与其值耦合的组件时,一切都变为amis。 在表单中我们有类似的内容:m.component( inputWrapper, { value: ... }) 尝试过滤此列表时,视图会呈现错误的组件。

请查看this codepen以获得更清晰的图片。

我的猜测是,mithril diff引擎存储了一组缓存的组件并渲染它们,而不是在每次重绘时实例化新的组件。 然而,我还没有找到解决方案来做到这一点。请帮忙。

2 个答案:

答案 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函数生成一个新数组。

该问题的解决方案是在接收数据的父控制器中执行缩减,以便可以在下一次绘制中检索它。

我对代码做的其他一些小调整:

  • 视图中虚拟DOM子项的数组括号是不必要的(我删除了更多标点符号,个人偏好:)。
  • 您在let作业中执行的解构可以在函数参数签名中执行,从而减少冗长。
  • 删除这些赋值允许使用箭头函数表达式的“隐式返回”形式,这样可以更容易地查看视图输出的结构,同时删除要考虑的变量数。
  • 使用const代替let清楚地表明分配给引用的值无法更改,这样可以更轻松地找到代码可能执行意外操作的位置。
  • 将reduce表达式的回调减少为三元组,可以清楚地表明只有1个逻辑条件和2个可能的结果,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