Mithril withAttr(attrName, callback)

withAttr(attrName, callback)

描述

返回一个事件处理函数,用指定 DOM 元素的值作为参数。

var state = {
    value: "",
    setValue: function(v) {state.value = v}
}

var Component = {
    view: function() {
        return m("input", {
            oninput: m.withAttr("value", state.setValue),
            value: state.value,
        })
    }
}

m.mount(document.body, Component)

签名

m.withAttr(attrName, callback, thisArg?)
参数 类型 是否必须 描述
attrName String 属性名称,该属性的值会被传入回调函数
callback any -> undefined 回调
thisArg any 在回调函数中,绑定到 this 关键字上的对象
返回 Event -> undefined 事件处理函数

工作原理

m.withAttr 方法创建一个事件处理函数。该事件处理函数会调用一个函数,且以指定 DOM 元素的指定属性值作为参数。

这个辅助函数可以用于把浏览器的事件模型从应用代码中分离。

// 独立使用
document.body.onclick = m.withAttr("title", function(value) {
    console.log(value) // 点击时,输出 <body> 元素的标题
})

通常,m.withAttr() 可以用在组件的视图中,避免 DOM 事件模型污染数据层:

var state = {
    email: "",
    setEmail: function(email) {
        state.email = email.toLowerCase()
    }
}

var MyComponent = {
    view: function() {
        return m("input", {
            oninput: m.withAttr("value", state.setEmail),
            value: state.email
        })
    }
}

m.mount(document.body, MyComponent)

预测事件目标

m.withAttr() 会读取事件处理函数绑定的元素的值,不需要和触发事件的元素相同。

var state = {
    url: "",
    setURL: function(url) {state.url = url}
}

var MyComponent = {
    view: function() {
        return m("a[href='/foo']", {onclick: m.withAttr("href", state.setURL)}, [
            m("span", state.url)
        ])
    }
}

m.mount(document.body, MyComponent)

在上面的代码中,如果用户点击了链接中的文本,e.target 会指向 <span>,而不是 <a>

虽然这个行为是按照规范进行的,但很多时候并不使用。因此,m.withAttr 使用 e.currentTarget 的值,它会指向 <a>,通常会更适合。

属性(attribute 和 property)

m.withAttr() 的第一个参数是属性名(attribute 或 property 都可以)。

// 从 `select.selectedIndex` 属性中读取值
var state = {
    index: 0,
    setIndex: function(index) {state.index = index}
}
m("select", {onclick: m.withAttr("selectedIndex", state.setIndex)})

如果参数名既是 attribute,也是 property,则会使用 property 的值。

// value 是布尔值,因为 `input.checked` 属性是布尔值
var state = {
    selected: false,
    setSelected: function(selected) {state.selected = selected}
}
m("input[type=checkbox]", {onclick: m.withAttr("checked", state.setSelected)})