【问题标题】:Like/dislike hyperlink does not work in an Object-oriented manner?喜欢/不喜欢超链接不能以面向对象的方式工作?
【发布时间】:2019-02-28 04:11:34
【问题描述】:

我想要一个喜欢/不喜欢的超链接来在我的页面上显示不同的内容:点击“喜欢”时,显示“好”;单击“不喜欢”时,显示“不好”。我的代码是这样的:

<html>
<head>
<script>
function Homepage(){

    this.like = document.getElementById("like");
    this.dislike = document.getElementById("dislike");

    Homepage.prototype = {
        constructor: Homepage,
        likeGame: function(event){
            if(this.like.style.display == "none"){
                this.like.style.display = "block";
            }
            event.preventDefault();
            },
        dislikeGame: function(event){
            if(this.dislike.style.display == "none"){
                this.dislike.style.display = "block";
            }
            event.preventDefault();
            },
        setListeners: function(){
            console.log('in listen');
            document.getElementById("hyperLike").addEventListener("click", this.likeGame);
            document.getElementById("hyperDislike").addEventListener("click", this.dislikeGame);
        }
    }
}
</script>

</head>
<body>
<p style="display:block">
<a id="hyperLike" href="";>Like</a>/<a id="hyperDislike" href="";>Dislike</a> the game.
</p>
<p id="like" style="display:none">
good
</p>
<p id="dislike" style="display:none">
bad
</p>
<script>
var homepage = new Homepage();

window.onload = homepage.setListeners;
</script>
</body>
</html>

但是它不起作用。点击超链接没有反应。我在setListeners 中添加了console.log,没有任何记录,所以它甚至没有进入setListeners。这里有什么问题?

我有另一个非 OO 版本,它的代码基本相同,它可以工作。

【问题讨论】:

    标签: javascript html oop


    【解决方案1】:

    问题是likeGame()函数中的this.likeHomepage()函数中的this.like不一样,因为函数有自己的作用域。解决这个问题的一种方法是使用箭头函数作为方法。现在this 将始终引用Homepage

    function Homepage() {
    
      this.like = document.getElementById("like");
      this.dislike = document.getElementById("dislike");
    
    
      this.likeGame = (event) => {
    
        if (this.like.style.display == "none") {
          this.dislike.style.display = "none"
          this.like.style.display = "block";
        }
        event.preventDefault();
      };
      this.dislikeGame = (event) => {
        if (this.dislike.style.display == "none") {
          this.like.style.display = "none"
          this.dislike.style.display = "block";
        }
        event.preventDefault();
      };
      this.setListeners = () => {
        console.log('in listen');
        document.getElementById("hyperLike").addEventListener("click", this.likeGame);
        document.getElementById("hyperDislike").addEventListener("click", this.dislikeGame);
      }
    }
    
    var homepage = new Homepage();
    
    window.addEventListener("load", () => {
      homepage.setListeners();
    })
    <html>
    
    <body>
      <p style="display:block">
        <a id="hyperLike" href="">Like</a>/<a id="hyperDislike" href="" ;>Dislike</a> the game.
      </p>
      <p id="like" style="display:none">
        good
      </p>
      <p id="dislike" style="display:none">
        bad
      </p>
    
    </body>
    
    </html>

    【讨论】:

    • this 将引用 Homepage 的实例,不是吗?
    • @CollinD 当您向元素添加事件处理程序时,处理程序中的this 将始终等于元素,如果未显式设置(箭头函数、绑定、调用、应用或匿名函数包装器)
    • @extempl 我同意,我指出答案有一点不准确。 this === HomePage 将是错误的。 this instanceof HomePage 是真的。
    • 如果 likeGame 函数中的 this.likeHomePage 函数中的 this.like 不同,那么如果在 this.likeGamethis.dislikeGame 函数中它会起作用,我将所有 @ 更改987654340@ 和 this.dislike 到他们原来的:document.getElementById("like")document.getElementById("dislike")?
    • 是的,这也应该可以,但是每次有人单击链接时,您都必须搜索 DOM 元素。
    【解决方案2】:

    以下演示可以将多个元素绑定到任何适用的事件和回调函数。使用此类的优点是参数selectoreventcallback 可以是任何值,并且不需要为多个侦听器采取额外的步骤。


    演示

    详情在demo中注释

    这是对 article 中的代码的修改。

    // Define class
    class Homepage {
      // Pass a CSS selector
      constructor(selector) {
        // Reference selector
        const elements = document.querySelectorAll(selector);
        // Get amount of elements
        this.length = elements.length;
        // Merge the constructor and elements
        Object.assign(this, elements);
      }
      // Pass a callback function
      each(callback) {
        // Iterate elements...
        for (let node of Array.from(this)) {
          // ...call callback function fore each element...
          callback.call(node);
        }
        // ...make the method chainable
        return this;
      }
      // Pass event and callback
      bind(event, callback) {
        // Iterate constructor...
        return this.each(function() {
          // ...regiter each element to the event and assign callback
          this.addEventListener(event, callback, false);
        });
      }
    };
    
    // Instantiate Homepage class
    const likeHate = selector => new Homepage(selector);
    // Callback rate()
    const rate = e => {
      // Reference clicked element
      const tgt = e.target;
      // If the clicked has .btn class...
      if (tgt.matches('.btn')) {
        // ...get the clicked value...
        const val = e.target.value;
        // ...reference article#rate...
        const rate = document.getElementById('rate');
        // ...assign the value of clicked to [data-rate] of #rate
        rate.dataset.rate = val;
        // If the value of clicked is 'Superior' =  thumbs up/down
        let icon = val === 'Superior' ? '?' : '?';
        // Assign icon to [data-icon] of #rate
        rate.dataset.icon = icon;
      }
    }
    /*
    Call the .bind() method on all .btn and register the click event
    to each .btn. Assign rate() as callback function.
    */
    likeHate('.btn').bind('click', rate);
    html,
    body {
      font: 700 16px/1.3 Raleway;
    }
    
    header {
      font-size: 1.5rem;
      margin: 10px 0;
    }
    
    .btn {
      border: 0 none transparent;
      background: none;
      cursor: pointer;
      font: inherit;
      margin: 0;
    }
    
    .btn:hover {
      color: blue;
      text-decoration: underline;
    }
    
    .btn:focus {
      outline: none;
    }
    
    #rate {
      font-size: 1.5rem;
    }
    
    #rate::before {
      content: attr(data-icon)'\a0';
    }
    
    #rate::after {
      content: attr(data-rate)'\a0';
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet">
    </head>
    
    <body>
      <header>
        <button class='btn' value='Superior'>Like</button>/<button class='btn' value='Inferior'>Hate</button> the game.
      </header>
      <article id="rate" data-icon='' data-rate=''></article>
    </body>
    
    </html>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-26
      • 1970-01-01
      • 1970-01-01
      • 2021-07-18
      • 1970-01-01
      • 2014-02-13
      相关资源
      最近更新 更多