【问题标题】:Create a list of settings with Next and Previous buttons in the DOM procedurally以程序方式在 DOM 中使用 Next 和 Previous 按钮创建设置列表
【发布时间】:2019-05-20 17:37:32
【问题描述】:

我想创建一个设置列表,用户可以通过 javascript 在 HTML 中更改这些设置。

很像这样:Quality:-0+

我的方法是创建一个带有value 属性的Option 类以及在其范围内更改值的prev()next() 方法。我正在扩展这个类,所以它可以是RangeBool 等。这工作正常。

我的问题是我似乎无法将其合并到 HTML 中。我当前的解决方案仅适用于创建的最后一个选项,其他选项不会触发 onclick 事件函数,即使他们这样做了,我也不觉得这是正确的方法。我怎样才能优雅地完成这项工作?

我已经尝试了in this question 显示的解决方案,但它阻止我使用this 访问类实例。

class UIManager {
    constructor (wrapperID, settings) {
        this.wrapper = document.getElementById(wrapperID)
        this.settings = settings
    }
    updateUI () {
        this.wrapper.innerHTML = ``
        for (let id = 0; id < this.settings.options.length; ++id) {
            let option = this.settings.options[id]

            this.wrapper.innerHTML += `
            <li>
                <div class="label">
                    ${option.name}
                </div>
                <div class="option">
                    <input id="prev${id}" class="open" type="button" value="<">
                    ${option.value}
                    <input id="next${id}" class="close" type="button" value=">">
                </div>
            </li>
            `
            let prevButton = document.getElementById(`prev${id}`)
            let nextButton = document.getElementById(`next${id}`)

            prevButton.onclick = _ => {
                this.settings.options[id].prev()
                this.updateUI()
            }
            nextButton.onclick = _ => {
                this.settings.options[id].next()
                this.updateUI()
            }
        }
    }
}

【问题讨论】:

  • 您可以利用您在开始时链接的方法,并通过使用Function.prototype.bind 方法仍然引用类实例this
  • 另外,我建议使用() 作为箭头函数的空参数签名。它在代码中更常见,并且更容易扩展以包含参数而无需修改。
  • @TimKlein 经过一番摆弄后,我发现您的方法确实工作得很好,但是由于每次迭代都会覆盖包装器的 innerHTML,因此只保留了最后的事件。我通过使用 document.createElement() 添加 DOM 元素来修复它。请随时发表您的评论作为答案,以便我接受。
  • 干杯!会的。

标签: javascript dom


【解决方案1】:

只要您使用Function.protoype.bind 将类实例成员this 绑定到匿名函数,The answer to the question you linked as a potential solution 就可以使用。

代码看起来像这样(使用之前链接的答案作为起点):

for ( var i = 0; i < itemLists.length; i++ ) (function(i){ 
  itemLists[i].onclick = function() {
      // do something using `this`
  }
}).bind(this)(i);

您在 cmets 中提到这不起作用,但它与覆盖 innerHTML 有关,而不是由于绑定。

希望这只是大图的一小部分。

【讨论】:

    【解决方案2】:

    尝试使用闭包来存储从循环内部创建的函数所需的值。

    类似这样的:

    prevButton.onclick = (function(settings, updateUI) {
        return function() {
            settings.options[id].prev();
            updateUI();
        };
    })(this.settings, this.updateUI); 
    
    nextButton.onclick = (function(settings, updateUI) {
        return function() {
            settings.options[id].next();
            updateUI();
        }
    })(this.settings, this.updateUI);
    

    【讨论】:

    • 这种方法会导致闭包内的updateUI(); 调用具有错误的this 值,因此在评估this.wrapper.innerHTML = '' 时会失败。我该如何解决这个问题?
    猜你喜欢
    • 2017-04-28
    • 2013-02-08
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    • 2018-01-14
    • 2017-02-21
    • 2011-08-01
    • 1970-01-01
    相关资源
    最近更新 更多