像配置函数那样在事件处理程序中获取组件

时间:2016-11-04 01:18:55

标签: javascript mithril.js

在事件处理程序中访问组件的正确方法是什么?或者,我应该做什么呢?

我有一个基本上是div按钮的UI部分。当用户单击它时,“按钮”将替换为输入。当用户完成输入后,它将返回“按钮”。

因为我从Backbone移植它,所以我使用jQuery来翻转两个部分的可见性并将注意力集中在输入上。在阅读了组件中如何给出组件中的配置函数后,我想知道是否应该给出组件的DOM元素,或者完全采用另一种方法(可能在m()函数中有条件?)。

State 1 State 2

{
    controller: function () {
        this.clickPlus = () => {
            $('#newActivityPlusIcon').hide()
            $('#newActivityPlaceholder').css('background-color', 'lightgray')

            const $newActivityInput = $('#newActivityInput')
            $newActivityInput.show()
            $newActivityInput.focus()
        }
        this.keyUpInput = (event) => {
            //If ESC key pressed
            if (event.keyCode === 27) {
                const $newActivityInput = $('#newActivityInput');
                $newActivityInput.hide()
                $newActivityInput.val('')

                $('#newActivityPlaceholder').css('background-color', '')
                $('#newActivityPlusIcon').show()
            }
        }
    },
    view: (ctrl) => {
        return m('section', {id: 'newActivity'}, [
            m('article', {id: 'newActivityPlaceholder', class: 'activityBox', onclick: ctrl.clickPlus}, [
                m('span', {id: 'newActivityPlusIcon'}, '+'),
                m('input', {id: 'newActivityInput', placeholder: 'type name', onkeyup: ctrl.keyUpInput}),
            ])
        ])
    }
}

2 个答案:

答案 0 :(得分:2)

就个人而言,我希望使用条件,这意味着DOM只包含当前相关的元素。

一个粗略的JSBin示例,我认为我的结构如下:http://jsbin.com/razisicelo/edit?html,js,output

使用ctrl.inputValue只是说明性的。

答案 1 :(得分:2)

秘银之间至关重要的实际区别Backbone组件是Mithril视图是用Javascript编写的。 Web MVC的一些旧的最佳实践由于其开放的机会而被打开了:

  1. 您可以在视图中轻松表达条件逻辑。正如Bryce所示,三元操作(condition ? true : false)是使视图自我完成的一种很好的方式:换句话说,视图函数可以表达DOM的所有可能状态,以及它需要做的所有事情。
  2. 您还可以在视图本身中定义事件处理程序和元素绑定,这意味着您不再需要控制器了解视图的结构或定义视图逻辑。这使您可以编写控制器,其唯一的功能是定义组件的状态和整体操作。
  3. 只有在您绝对需要将对DOM元素的引用传递给控制器​​或其他组件(这种情况很少发生)或者在第一次触发动画等特殊逻辑时,才需要特殊的config属性。元素被渲染。在这种情况下,没有必要。

    在下面的代码中,我设法隔离了2个属性inputactive,以及一个重置这些属性的动作cancel。这些描述了组件所需的所有状态。其余的纯粹是观点的关注点。

    视图决定如何根据DOM API的关注来读取和写入这些属性。例如,如何读取输入值是输入本身的一个问题:同样,确定keyCode 27表示“esc”是DOM逻辑,并且可以与改变状态的控制器逻辑分开。

    当用户体验和业务需求发生变化时,将这些问题分开会变得很有用:例如,我已经采取任意决定,使输入点击关闭或标记,同时清除输入和松散的活动状态。这不需要在控制器中添加额外的操作 - 我们将相同的cancel函数绑定到onblur事件处理程序。

    其他小调整:

    • 将视图表示为箭头函数会丢失return关键字,IMO可以更轻松地将视图作为单个声明性语句读取。
    • 我们可以丢失ID,因为我们不再需要从控制器引用视图:我们所有的状态绑定都直接在视图中进行。
    • classplaceholder等静态属性可以直接在选择器字符串中表示。这清楚地表明这些属性总是相同的:现在只为动态代码调用DOM属性对象 - 函数和条件属性。
    • 将子组分组的数组括号是多余的:您可以直接依次插入子项。

    https://jsbin.com/xopinoy/edit?js,output

    {
      controller: function () {
        this.active = m.prop( false )
        this.input  = m.prop( '' )
    
        this.cancel = () => {
          this.active( false )
          this.input( '' )
        }
      },
    
      view: ctrl =>
        m( 'section',
          m( 'article.activityBox', {
            onclick: event => 
              ctrl.active(true),
            style : {
              background : 
                ctrl.active() 
                  ? 'lightgrey' 
                  : ''
            }
          },
    
            ctrl.active()
              ? m( 'input[placeholder="type name"]', { 
                  value: ctrl.input(),
                  oninput: event =>
                    ctrl.input( event.target.value ), 
                  onkeyup: event => {
                    if( event.keyCode === 27 )
                      ctrl.cancel()
                  },
                  onblur: ctrl.cancel
                } )
              : m( 'span', '+' )
          )
        )
    }