像配置函数一样在事件处理程序中获取组件
Get component in event handler like config functions do
在事件处理程序中访问组件的正确方法是什么?或者,我应该怎么做?
我有一个 UI 部分,它本质上是一个 div 按钮。当用户单击它时,"button" 将替换为输入。当用户完成输入时,它返回到 "button".
因为我是从 Backbone 移植的,所以我使用 jQuery 翻转两个部分的可见性并将焦点设置在输入上。在阅读了有关如何为组件提供组件中的配置函数之后,我想知道是否应该为组件提供 DOM 元素,或者完全采用另一种方法(也许在 m() 函数中有条件?)。
{
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}),
])
])
}
}
就个人而言,我希望使用条件,这意味着 DOM 仅包含当前相关的元素。
一个粗略的 JSBin 示例,说明我认为我将如何构建它:http://jsbin.com/razisicelo/edit?html,js,output
ctrl.inputValue 的使用只是说明性的。
Mithril 和 Backbone 组件之间的关键实际区别是 Mithril 视图是用 Javascript 编写的。由于这带来的机会,Web MVC 的一些旧的最佳实践被颠覆了:
- 您可以轻松地在视图中表达条件逻辑。正如 Bryce 所展示的,三元运算 (
condition ? true : false
) 是使视图自我完成的好方法:换句话说,视图函数可以表达 DOM 的所有可能状态,以及它需要的一切做。
- 您还可以在视图本身中定义事件处理程序和元素绑定,这意味着您不再需要控制器了解视图的结构或定义视图逻辑。这使您能够编写控制器,其唯一功能是定义组件的状态和整体操作。
仅当您绝对需要将对 DOM 元素的引用传递给控制器或其他组件时才需要特殊的 config
属性 - 这种情况很少见 - 或者在第一次呈现元素时触发特殊逻辑,如动画。在这种情况下,没有必要。
在下面的代码中,我设法隔离了 2 个属性 input
和 active
,以及一个重置这些属性的操作 cancel
。这些描述了组件需要的所有状态。剩下的纯粹是视图的关注点。
视图根据 DOM API 的关注点决定如何读取和写入这些属性。例如,如何读取输入的值是输入本身的关注点:同样,确定 keyCode 27 表示 'esc' 是 DOM 逻辑,并且可以与更改状态的控制器逻辑分开。
当 UX 和业务需求发生变化时,将这些关注点分开会变得很有用:例如,我做出了武断的决定,让点击关闭或 Tab 键离开输入同时清除输入和松散的活动状态。这不需要在控制器中添加额外的操作 - 我们将相同的 cancel
函数绑定到 onblur
事件处理程序。
其他小调整:
- 将视图表示为箭头函数会丢失
return
关键字,IMO 可以更轻松地将视图作为单个声明语句来阅读。
- 我们可以松开 ID,因为我们不再需要从控制器引用视图:我们所有的状态绑定都直接在视图本身中进行。
- 像
class
和placeholder
这样的静态属性可以直接在选择器字符串中表达。这清楚地表明这些属性始终是相同的:现在 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', '+' )
)
)
}
在事件处理程序中访问组件的正确方法是什么?或者,我应该怎么做?
我有一个 UI 部分,它本质上是一个 div 按钮。当用户单击它时,"button" 将替换为输入。当用户完成输入时,它返回到 "button".
因为我是从 Backbone 移植的,所以我使用 jQuery 翻转两个部分的可见性并将焦点设置在输入上。在阅读了有关如何为组件提供组件中的配置函数之后,我想知道是否应该为组件提供 DOM 元素,或者完全采用另一种方法(也许在 m() 函数中有条件?)。
{
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}),
])
])
}
}
就个人而言,我希望使用条件,这意味着 DOM 仅包含当前相关的元素。
一个粗略的 JSBin 示例,说明我认为我将如何构建它:http://jsbin.com/razisicelo/edit?html,js,output
ctrl.inputValue 的使用只是说明性的。
Mithril 和 Backbone 组件之间的关键实际区别是 Mithril 视图是用 Javascript 编写的。由于这带来的机会,Web MVC 的一些旧的最佳实践被颠覆了:
- 您可以轻松地在视图中表达条件逻辑。正如 Bryce 所展示的,三元运算 (
condition ? true : false
) 是使视图自我完成的好方法:换句话说,视图函数可以表达 DOM 的所有可能状态,以及它需要的一切做。 - 您还可以在视图本身中定义事件处理程序和元素绑定,这意味着您不再需要控制器了解视图的结构或定义视图逻辑。这使您能够编写控制器,其唯一功能是定义组件的状态和整体操作。
仅当您绝对需要将对 DOM 元素的引用传递给控制器或其他组件时才需要特殊的 config
属性 - 这种情况很少见 - 或者在第一次呈现元素时触发特殊逻辑,如动画。在这种情况下,没有必要。
在下面的代码中,我设法隔离了 2 个属性 input
和 active
,以及一个重置这些属性的操作 cancel
。这些描述了组件需要的所有状态。剩下的纯粹是视图的关注点。
视图根据 DOM API 的关注点决定如何读取和写入这些属性。例如,如何读取输入的值是输入本身的关注点:同样,确定 keyCode 27 表示 'esc' 是 DOM 逻辑,并且可以与更改状态的控制器逻辑分开。
当 UX 和业务需求发生变化时,将这些关注点分开会变得很有用:例如,我做出了武断的决定,让点击关闭或 Tab 键离开输入同时清除输入和松散的活动状态。这不需要在控制器中添加额外的操作 - 我们将相同的 cancel
函数绑定到 onblur
事件处理程序。
其他小调整:
- 将视图表示为箭头函数会丢失
return
关键字,IMO 可以更轻松地将视图作为单个声明语句来阅读。 - 我们可以松开 ID,因为我们不再需要从控制器引用视图:我们所有的状态绑定都直接在视图本身中进行。
- 像
class
和placeholder
这样的静态属性可以直接在选择器字符串中表达。这清楚地表明这些属性始终是相同的:现在 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', '+' )
)
)
}