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

标签 javascript mithril.js

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

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

因为我是从 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}),
            ])
        ])
    }
}

最佳答案

Mithril 和 Backbone 组件之间关键的实际区别在于 Mithril View 是用 Javascript 编写的。由于这带来了机遇,一些旧的 Web MVC 最佳实践被彻底颠覆:

  1. 您可以轻松地在 View 本身中表达条件逻辑。正如 Bryce 所示,三元操作( condition ? true : false )是使 View 自完成的好方法:换句话说, View 函数可以表达 DOM 的所有可能状态,以及所有内容它需要这样做。
  2. 您还可以在 View 本身中定义事件处理程序和元素绑定(bind),这意味着您不再需要 Controller 了解 View 的结构或定义 View 逻辑。这使您能够编写 Controller ,其唯一功能是定义组件的状态和整体操作。

仅当您绝对需要将对 DOM 元素的引用传递给 Controller ​​或其他组件(这种情况很少发生)或触发特殊逻辑(例如动画)时,才需要特殊的 config 属性。第一次渲染元素。在这种情况下,没有必要。

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

View 根据 DOM API 的关注点决定如何读取和写入这些属性。例如,如何读取输入的值是输入本身的问题:同样,确定keyCode 27表示“esc”是DOM逻辑,并且可以与改变状态的 Controller 逻辑保持分离。

当用户体验和业务需求发生变化时,分离这些问题变得很有用:例如,我做出了任意决定,让单击或按 Tab 键远离输入也会清除输入并释放事件状态。这不需要在 Controller 中添加额外的操作 - 我们将相同的 cancel 函数绑定(bind)到 onblur 事件处理程序。

其他小调整:

  • 将 View 表示为箭头函数会失去 return 关键字,在我看来,这使得将 View 作为单个声明性语句来阅读变得更容易。
  • 我们可以释放 ID,因为我们不再需要从 Controller 引用 View :所有状态绑定(bind)都直接在 View 本身中进行。
  • 诸如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', '+' )
      )
    )
} 

关于javascript - 像配置函数一样在事件处理程序中获取组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40413870/

相关文章:

html - 如何在 Mithril 中将字符串转换为 HTML 元素?

javascript - 使用 javascript 检测 html5 验证

javascript - Node.js 使用哪种线程模型?

javascript - 卡住 JavaScript 对象

javascript - 将可拖动事件委托(delegate)给父元素

mithril.js - Mithril 只重绘1个模块

javascript - blob 不接受 ios 上的 Uint8Array

javascript - 这是什么 comboBox 或 dropDownList?

javascript - IIFE View 模型似乎未定义

javascript - 为了相互对应Mithril的多个输入?