Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript-Mithril嵌套组件_Javascript_Design Patterns_Model View Controller_Mithril.js - Fatal编程技术网

Javascript-Mithril嵌套组件

Javascript-Mithril嵌套组件,javascript,design-patterns,model-view-controller,mithril.js,Javascript,Design Patterns,Model View Controller,Mithril.js,我正在使用mithril组件构建仪表板。仪表板由通用小部件组件组成,这些组件嵌套更具体的组件,如twitter小部件、销售小部件等。通用小部件与嵌套组件无关 现在我需要从嵌套组件中补充通用小部件。例如,通用小部件有一个带有删除和刷新的常用操作的工具栏,我想添加内部组件特定的操作,例如销售小部件的更改日期范围,twitter小部件的更改帐户 直截了当的方法是将内部组件分解为两个子组件一个工具栏和内容,例如sales_toolbar_组件和sales_content_组件。这两个子连接都需要通过aj

我正在使用mithril组件构建仪表板。仪表板由通用小部件组件组成,这些组件嵌套更具体的组件,如twitter小部件、销售小部件等。通用小部件与嵌套组件无关

现在我需要从嵌套组件中补充通用小部件。例如,通用小部件有一个带有删除和刷新的常用操作的工具栏,我想添加内部组件特定的操作,例如销售小部件的更改日期范围,twitter小部件的更改帐户

直截了当的方法是将内部组件分解为两个子组件一个工具栏和内容,例如sales_toolbar_组件和sales_content_组件。这两个子连接都需要通过ajax加载相同的数据,因此会导致重复。一种方法是遵循混合体系结构(),其中顶级组件将执行ajax调用,并在每个子组件的构造函数中传递数据。然而,在这种情况下,父组件是通用的,不知道子数据需求

另一种方法是让一个子组件执行ajax调用,并通过观察者模式通知同级,这似乎有点内部耦合/依赖

另一个考虑事项是创建一个可以有多个视图的组件&让父级使用相同的控制器实例根据需要呈现每个视图。类似于:

//create a component whose controller and view functions receive some arguments
var component = m.component(MyComponent, {name: "world"}, "this is a test")

var ctrl = new component.controller() // logs "world", "this is a test"
m.component(MyComponent.toolbar(ctrl));
m.component(MyComponent.content(ctrl));   

这些似乎都不完整,有没有我可以考虑的参考模式?

< P>记忆模式可能适合你。memonization涉及包装一个函数——在本例中是AJAX请求——这样,任何给定输入的第一次调用都会触发底层函数,但其返回值存储在内部缓存中;具有相同输入的后续调用检索缓存值,而不涉及底层函数。下面是一个简单的实现1和一个记忆化的AJAX请求函数,它封装了Mithril的
m.request

function memoize( fn ){
  var cache = {}

  return function memoized( input ){
    if( !( input in cache ) )
      cache[ input ] = fn( input )

    return cache[ input ]
  }
}

var get = memoize( function( url ){
  return m.request( { method : 'GET', url : url } )
} )
这样,无论哪个组件首先执行,都将发出请求;下一个组件(随后将立即执行)将检索相同的值

关于拥有多视图组件的想法,这与您最初的提议在实践上没有任何不同。考虑下面的代码:

var Wrapper = {
  controller : function(){
    // AJAX or whatnot
  },

  view : function( ctrl ){
    return m( '.Wrapper', 
      m( Toolbar, ctrl )
      m( Content, ctrl )
    )
  }
}

m( Wrapper, { name : 'world' }, 'This is a test' )
在这里,我使用了reference
Wrapper
而不是
MyComponent
,而
工具栏
内容
正是最初提出的组件。包装器不是泛型的,但也不是
MyComponent
。我发现,尽可能地将Mithril代码的各个单元简化为组件(即使在理想情况下您更愿意使用较少的组件),通常会使代码更易于维护,因为虽然最终可能会使用许多特定于上下文的模块,而不是一些高度可配置的通用模块,所有这些特定于上下文的模块在调用方式上都是通用的,这在代码可预测性方面更有用

话虽如此,还是有可能改进您对将一个控制器传递给多个视图的模式的想法。同样,我会将此模式简化为组件形式,这样我们就可以在内部处理复杂问题,但会在整个Mithril中公开一个一致的接口:

var MultiView = {
  controller : function( controller ){
    return new controller()
  },

  view : function( ctrl ){
    var views = [].slice.call( arguments, 2 )

    return m( 'div',
      view.map( function( view ){
        return view( ctrl )
      } )
    )
  }
}

m( MultiView, function controller(){ /* AJAX or whatnot */ }, Toolbar.view, Content.view )

1此记忆功能适用于任何接受单个字符串参数的函数,非常适合AJAX请求。如果您想要更全面的记忆解决方案,请查看。

谢谢@barny,基于多视图方法,我创建了2个Fiddler-这是您描述的模式的实现,但是它假设小部件是一个没有控制器的视图组件。其中as-支持widget拥有一个控制器&引用内部widgets控制器作为属性,很高兴听到您的想法,特别是第二小提琴手接受了答案,希望您有机会看一看jsfiddle.net/chifer/f8y1ndwg/1&jsfiddle.net/chifer/rLv1pLg8评论。这将是很好的米特里尔食谱包括西米拉哈酷。不过,我不明白这些例子的要点。为什么不只是有一个正常的组成部分?我的目标是让内部的外部组件不可知,这两个例子都不好我已经创建了一个包含内部子组件(标题和内容)的外部组件和对象包装器,我不想重复加载ajax调用,但只有外部组件知道如何渲染内部子组件,希望能得到一些反馈