使用模块模式的变体附加javascript事件的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用模块模式的变体附加javascript事件的问题相关的知识,希望对你有一定的参考价值。

我正在尝试使用“模块模式”中的代码将javascript事件附加到svg元素。我非常喜欢javascript,因为我确信下面的代码会很明显。我试图使用我实际使用的更简单的代码版本重新创建这种情况。具有讽刺意味的是,我实际上远远没有让它与这个例子一起工作,但我的大脑因试图让它在这个网站的其他地方工作和研究而受到伤害。所以,我正在向所有聪明的人伸出援手,看看他们是否可以提供帮助。我遇到的问题(当我让它工作!)是javascript事件似乎没有绑定到DOM元素,只是在页面加载时触发。当我再次触发事件时(通过移动鼠标)我得到一个由D3库引起的javascript错误“未捕获的TypeError:n.apply不是函数”

如果任何人都可以通过重新创建模块模式并让这个示例工作 - 我希望能够将相同的内容合并到我的实际代码中(示例和实际代码之间唯一真正的区别在于有一堆) “扩展器”模块而不是一切都在其中。

亲切的问候

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
    <div id="box1"></div>
    <div id="box2"></div>

    <script>

        function mouseOver(i) {
            return this.targets[i].select("#" + this.targets[i].container).select("circle").attr("fill", "blue");
        }

        function mouseOut(i) {
            return this.targets[i].select("#" + this.targets[i].container).select("circle").attr("fill", "green");
        }

        var example = (function () {

            return {

                addRect: function addRect(container) {
                    this.box = d3.select("#" + container).append("svg");

                    this.rect = this.box.append("rect")
                        .attr({
                            "fill": "red",
                            "width": 50,
                            "height": 50,
                        });

                },

                addCircle: function addControl(targets) {
                    this.targets = targets

                    for (target in this.targets) {
                        tt = this.targets[target]

                        tt.circle = tt.box.append("circle")
                            .attr({
                                "fill": "green",
                                "cx": -10,
                                "cy":-10,
                                "r": 10,
                                "transform": "translate(30,30)"
                            })
                    };
                },

                addControl: function addControl(targets) {
                    this.targets = targets

                    for (target in this.targets) {
                        tt = this.targets[target]

                        tt.control = tt.box.append("rect")
                            .attr({
                                "fill": "none",
                                "width": 50,
                                "height": 50,
                            })
                            .on("mouseover", mouseOver(target))
                            .on("mouseout", mouseOut(target))
                    };  

                },

            };
        })();


        var first = new example.addRect("box1");
        var second = new example.addRect("box2");

        var circs = new example.addCircle([first, second]);
        var controls = new example.addControl([first, second]);


    </script>
</body>
</html>
答案

问题1:事件在页面加载时被触发

原因:

你在做

.on("mouseover", mouseOver(target)) //this is wrong the second parameter should have been a function.

这样的事情

.on("mouseover", function(){mouseOver(target)})

问题2:

tt.control = tt.box.append("rect")
                            .attr({
                                "fill": "none",//this should not be none else mouse over will not work as you expect
                                "width": 50,
                                "height": 50,
                            })
                            .on("mouseover", mouseOver(target))
                            .on("mouseout", mouseOut(target))

应该使用不透明度0来完成它,使其不可见

for (target in this.targets) {
            tt = this.targets[target]
            tt.control = tt.box.append("rect")
              .attr({
                "fill": "blue",
                "width": 50,
                "height": 50,
                "opacity": 0
              })

问题3:

您可以将参数设置为DOM,而不是将其传递给函数。像这样的东西

  for (target in this.targets) {
    tt = this.targets[target]
    tt.control = tt.box.append("rect")
      .attr({
        "fill": "blue",
        "width": 50,
        "height": 50,
        "opacity": 0
      })

      .on("mouseover", function() {
        mouseOver(tt)
      })
      .on("mouseout", function() {
        mouseOut(tt)
      });
      tt.control.node().dataset = tt;//binding the data to the dom
  };

并在鼠标事件中获取绑定对象,如下所示:

function mouseOver(target) {
      //gettting the data from the dom
      event.target.dataset.circle.attr("fill", "blue");
    }

    function mouseOut(target) {
      event.target.dataset.circle.attr("fill", "green");
    }

工作代码here

以上是关于使用模块模式的变体附加javascript事件的问题的主要内容,如果未能解决你的问题,请参考以下文章

javascript 将变体附加为URL参数

构造器模式与模块模式

JavaScript 模块模式和拖放 API

JavaScript事件详解-zepto的事件实现

JavaScript异步编程 分布式事件

什么 A* 变体包括附加限制