简体   繁体   English

第一次在无法正常运作的Clicker游戏中使用JavaScript

[英]First time using javascript for a clicker game that doesn't work

this is my first time using javascript. 这是我第一次使用javascript。 I basically wanted to create a "clicker" game. 我基本上想创建一个“点击器”游戏。 The target of the game is clicking an image to make points. 游戏的目标是单击图像以取得积分。 I've tryed fixing it by myself and looking on the internet but I found nothing. 我已经尝试过自己修复它并在互联网上查找,但没有发现任何问题。 What's is cauising the problem ? 解决问题的原因是什么?

Basically everytime I open the page the score is already set to 1 but when i click on the image it does not increases. 基本上,每次我打开页面时,分数已经设置为1,但是当我单击图像时分数不会增加。

<div id="bgk">
<div class="layer">
        <div class="row p-2">
            <div class="col-lg-6 col-xl-6 text-left"><p>Score: <span class="score"><script>document.write(scorecounter());</script></span></p></div>
            <div class="col-lg-6 col-xl-6 text-right"><p>Time: <span class="time">2</span></p></div>

            <div class="p-2">
                <img src="png.png" id="image" onclick="scorecounter()">
            </div>
        </div>
    </div>
</div>

While this is the script that increases the score 虽然这是增加分数的脚本

<script>
var score = 0;
function scorecounter() 
{
    score ++;
    return score;
}
</script>

Your score is initially one because you call your function when you use 您的score最初是1,因为您在使用时会调用函数

document.write(scorecounter());

This will increase the value of score then return it, thus displaying the number 1. 这将增加score的值,然后将其返回,从而显示数字1。

The reason why your click doesn't increase the value of score is because you're not displaying the score again. 您的点击没有增加score的原因是因为您没有再次显示score At the moment you are simply just displaying the score when the page loads. 目前,您只是在页面加载时显示分数。 Then when you click your image the value of score is increased but you're not displaying it to the DOM (ie the page) again. 然后,当您单击图像时, score的值会增加,但不会再次显示在DOM(即页面)上。 To display the value of score to the page you can use .innerHTML on the element where you want the score to appear. 要在页面上显示分数的值,可以在要显示分数的元素上使用.innerHTML

See a working example below: 请参见下面的工作示例:

 var score = 0; function scorecounter() { score++; document.getElementById('score').innerHTML = score; // Set the element with the id 'score' to have the value 'score' inside of it. Also note that .innerHTML can be replaced with .textContent to help resolve XSS vulnrabilities. } 
 /* css - ignore this */ .red { background-color: red; height: 50px; width: 100%; color: white; text-align: center; cursor: pointer; } 
 <p>Score: <span id="score">0</span></p> <div class='red' onclick="scorecounter()"> Click me (imagine this as your image) </div> 

Edit: As @BrandonBuck pointed out, .innerHTML is prone to cross-site scripting (XSS). 编辑:正如@BrandonBuck指出的那样, .innerHTML倾向于跨站点脚本(XSS)。 To help avoid this using .textContent instead of .innerHTML can help avoid this. 为了避免这种情况,请使用.textContent而不是.innerHTML来避免这种情况。

Here is a JSFiddle of it working. 这是它的一个JSFiddle。

So there are quite a few things you're doing that you probably shouldn't be doing. 因此,您正在做很多事情,您可能不应该做。 And it's not necessarily your fault. 这不一定是你的错。 JavaScript is old, and there are a lot of resources online and some of those resources are bound to be bad. JavaScript很旧,并且在线上有很多资源,其中某些资源注定是不好的。 Not to mention, I have no idea where you started from so you could have been given some really old example or what-have-you. 更不用说,我不知道您从哪里开始,所以您可能会得到一些非常古老的例子或您拥有什么。

So where to begin, let's see... we don't use document.write anymore. 那么从哪里开始,让我们看看...我们不再使用document.write了。 As a matter of fact, when I started using JS about 17 years ago it was not really that common. 事实上,大约17年前我开始使用JS时,它并不是那么普遍。 The problem with document.write is that it's not doing what you think it's doing. document.write的问题在于它没有按照您认为的那样做。 When the page is initially parsed that will be executed, and it's going to write whatever you told it to, and that's it. 最初解析页面时,将执行该页面,并将编写您告诉它的内容,就是这样。 It's done its job and it's over. 它已经完成工作,并且结束了。 It will never write again until you reload the page. 在重新加载页面之前,它将永远不会再写入。

As @NickParsons pointed out in his comment, your score "starts" at 1 because you're calling scorecounter in your write statement, so you're incrementing the score and writing it's new value at the same time. 正如@NickParsons在他的评论中指出的那样,您的分数“始于” 1因为您在写语句中调用了scorecounter ,因此您要增加分数并同时写入新的值

Next, you're using HTML attributes to associate JavaScript actions. 接下来,您将使用HTML属性来关联JavaScript操作。 This is generally frowned upon in modern web development as we tend to like to keep our JS and HTML pretty separate. 由于我们倾向于将JS和HTML保持非常独立,因此在现代Web开发中通常对此并不满意。 I'll show you some examples of how to do that. 我将向您展示一些示例。

Okay, so another thing is global values. 好的,另一件事是全局值。 Of course in your example it's not necessarily avoidable but we can do some cleaning up for that. 当然,在您的示例中,这不一定是可以避免的,但是我们可以为此进行一些清理。 So let's take a go. 所以,让我们去吧。 First, let's clean up the HTML. 首先,让我们清理HTML。 Most of it (aside from the JS) is not bad at all. 除了JS之外,大多数都还不错。

this is my first time using javascript. 这是我第一次使用javascript。 I basically wanted to create a "clicker" game. 我基本上想创建一个“点击器”游戏。 The target of the game is clicking an image to make points. 游戏的目标是单击图像以取得积分。 I've tried fixing it by myself and looking on the internet but I found nothing. 我已经尝试过自己修复它并在互联网上查找,但没有发现任何问题。 What's is causing the problem? 是什么引起了问题?

Basically everytime I open the page the score is already set to 1 but when I click on the image it does not increase. 基本上,每次我打开页面时,分数已经设置为1,但是当我单击图像时分数不会增加。

<div id="bgk">
  <div class="layer">
    <div class="row p-2">
      <div class="col-lg-6 col-xl-6 text-left">
        <p>
          Score: <span class="score-value"></span>
        </p>
      </div>
      <div class="col-lg-6 col-xl-6 text-right">
        <p>
          Time: <span class="time-value">2</span>
        </p>
      </div>
      <div class="p-2">
        <img src="png.png" id="image">
      </div>
    </div>
  </div>
</div>

So the biggest thing I've done outside of formatting is remove all the JS code, and change the class on the value spans to <name>-value , so score is a perfectly fine class name, don't get me wrong -- but score-value is more clear about what we're going to put there. 因此,除了格式化之外,我要做的最大事情是删除所有JS代码,并将值范围内的类更改为<name>-value ,所以score是一个很好的类名,请不要误解我-但是score-value对于我们要放置的内容更加清楚

Next thing we need to do is clean up the JavaScript. 接下来,我们需要清理JavaScript。 As a base, it's not bad. 作为基础,这还不错。 But it's not where we want to go. 但这不是我们想要去的地方。 Let's do this in steps. 让我们逐步进行。 I'm going to start from scratch here since we're going to change it quite a bit. 我将在这里从头开始,因为我们将对其进行很多更改。 First thing is we have a Game , and our game will have a score associated with it. 首先,我们有一个Game ,我们的游戏将获得一个与之相关的score So let's make a class (class syntax is new, but supported natively by the majority of major browsers in use). 因此,让我们创建一个类(类语法是新的,但是大多数使用的主要浏览器都本身支持)。

class Game {
  constructor() {
    this.score = 0;
  }
}

Bam. am Got our class. 上了我们的课。 What else do we need? 我们还需要什么? Well -- we need to increment our score. 好吧-我们需要增加分数。 So let's do that. 因此,让我们这样做。

class Game {
  constructor() {
    this.score = 0;
  }

  incrementScore() {
    this.score += 1;
  }
}

Easy enough. 很简单。 Next, we need to render our score, or add it to the DOM (the HTML after it's been processed by the browsers becomes the "DOM" or Document Object Model, which is an API that lets us interact with the page programmatically). 接下来,我们需要呈现分数,或将其添加到DOM(浏览器处理后的HTML变成“ DOM”或文档对象模型,这是一个API,可让我们通过编程方式与页面进行交互)。

Now, rendering this score could be part of our game, but it's not really -- our game is supposed to be just the game itself. 现在,渲染此分数可能是我们游戏的一部分,但事实并非如此-我们的游戏应该仅仅是游戏本身。 It really shouldn't contain a bunch of other logic. 它实际上不应该包含其他逻辑。 Otherwise we get a super class and we may as well have not tried to do this. 否则,我们将获得超类,并且我们可能还没有尝试这样做。 But we can make a new class... let's call it UserInterface , since, y'know, it's our UserInterface . 但是我们可以创建一个新的类...称之为UserInterface ,因为您知道这是我们的UserInterface Most JavaScript libraries will refer to the HTML/DOM aspect of your app as a "view" or "component," I'm using "user interface" since we're talking about a "game" and the common term there is UI. 大多数JavaScript库会将应用程序的HTML / DOM方面称为“视图”或“组件”。我使用的是“用户界面”,因为我们是在谈论“游戏”,而通用术语是UI。

class UserInterface {}

Okay, so we need to render text . 好的,所以我们需要渲染text To do that, we need to fetch the DOM node we want to store the score , and then we need to set it's text to the current score . 为此,我们需要获取要存储分数的DOM节点 ,然后将其文本设置为当前score The UserInterface doesn't know that the score is, the Game does so we need to pass some data around. UserInterface不知道得分是多少,游戏知道,所以我们需要传递一些数据。

class UserInterface {
  renderScore(score) {
    const el = document.querySelector('.score-value');
    el.textContent = score;
  }
}

You see I've used const . 你看我用过const For the most part, you can imagine that const does that var does -- it declares a variable. 在大多数情况下,您可以想象const就像var一样-它声明了一个变量。 Underneath they work quite differently. 在下面,它们的工作方式完全不同。 Without going in depth about JavaScript variable scoping let me just say that var is old school, and const is new school. 在不深入讨论JavaScript变量作用域的情况下,我只想说var是老派,而const是新派。 const defines not only a variable like var but it also makes it so that it cannot be reassigned. const不仅定义了像var这样的变量,而且还对其进行了定义,以使其无法重新分配。 Since we never reassign el in the body of renderScore I made it const . 由于我们从未在renderScore主体中重新分配el ,因此将其设置为const Now, var is old school as I said and its new school alternative is let , which does pretty much the same thing as const (as far as scope goes) but allows you to reassign the value. 现在, var就像我说的那样是老派,而新的替代是let ,它和const (就作用域而言),但允许您重新分配值。 I encourage you to dive more into why let and const were added but that's beyond this answer. 我鼓励您更多地研究为什么添加letconst ,但这超出了这个答案。

There is an optimization here -- you see I'm searching for the .score-value element every time I render . 这里有一个优化-您看到我每次渲染时都在搜索.score-value元素。 This is bad. 这不好。 There are a few approaches I could take here but for the sake of simplicity, let's just do the easiest and get it up front. 我可以在这里采取几种方法,但是为了简单起见,让我们最简单地进行一下准备。

class UserInterface {
  constructor() {
    this.scoreValueEl = document.querySelector('.score-value');
  }

  renderScore(score) {
    this.scoreValueEl.textContent = score;
  }
}

As an aside, you may not know what document.querySelector does, but you can think of it as searching the DOM (again, what the HTML page becomes after the browser processes it) for an element that matches the text you pass to it. 顺便说一句,您可能不知道document.querySelector做什么,但是您可以将其视为在DOM(同样,在浏览器处理HTML页面之后,HTML页面变成什么)中寻找与您传递给它的文本匹配的元素。 The term selector comes from CSS, where you define your rules by "selecting" elements. selector一词来自CSS,您可以在其中通过“选择”元素来定义规则。 You can select by tag, h3 , div , etc.. or you can select by class name (just append a . in front of the class name, like .score-value for class="score-value" elements) or you can select by an ID (just append a # similar to . for class names). 您可以按标签, h3div等进行选择。也可以按类名进行选择(只需在类名前面附加一个. ,例如class="score-value"元素的.score-value )即可通过ID选择(只需在类名后附加一个类似于.# )即可。 You can get more complex but for now, leave it at that. 您可能会变得更加复杂,但现在就不要说了。 So document.querySelector('.score-value') says, "Hey DOM, can you find some element that has a class "score-value" on it and give it back to me?" 因此document.querySelector('.score-value')说,“嘿DOM,您能找到上面带有“ score-value”类的元素并将其还给我吗?”

Okay, so now I have the Game to track the score (and other future game elements) and then I have the User Interface to render this stuff to the user. 好的,现在我有了Game来跟踪得分(以及其他将来的游戏元素),然后有了User Interface来将这些内容呈现给用户。 Next, we need to do some interaction. 接下来,我们需要进行一些交互。 This part can be quite a topic of passing around lots of functions, etc.. so I'm going to keep it relatively simple. 这部分可能是传递许多函数等的主题。因此,我将使其保持相对简单。 With our Game and UserInterface class ready we'll just bind the click to our image and increment the score and render it. 准备好Game和UserInterface类后,我们将点击绑定到我们的图像上并增加分数并进行渲染。 So let's give all that a go. 因此,让我们放手一搏。 First, let's create our new values: 首先,让我们创建新的值:

const game = new Game();
const ui = new UserInterface();

// we want to show the score on load, so let's do that
ui.renderScore(game.score);

Okay, so first part down. 好吧,所以第一部分下来。 Now let's handle clicks. 现在让我们处理点击。 Using document.querySelector again to fetch the image: 再次使用document.querySelector来获取图像:

// see here, we only have one img tag on the page, so I use the tag
// as the selector to find it
const img = document.querySelector('img');

img.addEventListener('click', () => {
  game.incrementScore();
  ui.renderScore(game.score);
});

Okay, so two new things here. 好的,这里有两个新内容。 addEventListener is the JS way to say "hey element, when the user does X do Y", in this case we say "when the user clicks this image, run this function." addEventListener是JS表示“嘿元素,当用户执行X做Y时”的方式,在这种情况下,我们说“当用户单击此图像时,运行此功能”。 So the first value we pass to addEventListener is the name of the event we want to handle and the second value is the function we want to execute when the event is triggered. 因此,我们传递给addEventListener的第一个值是我们要处理的事件的名称,第二个值是我们要在触发事件时执行的函数。 Now that function, I wrote it as an "arrow function" which is shorthand and means the same thing as function() {} . 现在,该函数是作为“箭头函数”编写的,它是简写形式,与function() {}含义相同。 So () => {} is the same thing as function() {} (there are, again, some differences I'm glossing over because it's out of scope for this answer and you should definitely look those up). 因此, () => {}function() {} () => {}是相同的东西function() {}同样,我掩盖了一些差异,因为它超出了此答案的范围,您肯定应该查找这些差异)。 So don't be alarmed by the arrow function there, it's simple a JS function we're passing in to call. 因此,不要被其中的箭头功能惊慌,它是我们传递给调用的简单JS函数。 Notice inside this function we increment the score and then render it. 请注意,在此函数内部,我们增加了分数,然后进行渲染。

So the final JS should be something like this: 所以最终的JS应该是这样的:

class Game {
  constructor() {
    this.score = 0;
  }

  incrementScore() {
    this.score += 1;
  }
}

class UserInterface {
  constructor() {
    this.scoreValueEl = document.querySelector('.score-value');
  }

  renderScore(score) {
    this.scoreValueEl.textContent = score;
  }
}

const game = new Game();
const ui = new UserInterface();

ui.renderScore(game.score);

const img = document.querySelector('img');
img.addEventListener('click', () => {
  game.incrementScore();
  ui.renderScore(game.score);
});

Here is a JSFiddle of it working. 这是它的一个JSFiddle。

Add On 添加在

(yes sadly I have more to say) (是的,我还有更多话要说)

All that being said, learning JS is easy and accessible. 综上所述,学习JS很容易且容易上手。 If you'd like to brush up or learn new things, you can head over to CodeAcademy, or if you don't mind some out of pocket expense SkillShare, PluralSight, CodeSchool, and many more offer JavaScript courses. 如果您想复习或学习新知识,可以前往CodeAcademy,或者如果您不介意一些自费技能,SkillShare,PluralSight,CodeSchool等提供JavaScript课程。

In addition to learning more about JavaScript, most real-world JavaScript is written with some framework as a starting point. 除了学习更多有关JavaScript的知识外,大多数现实世界中的JavaScript都是以某种框架为起点编写的。 Vue was mentioned to you, so as you feel you're knowledge and comfort increase with JS you should look into Vue. 提到了Vue,因此当您觉得自己有了JS的知识和舒适度时,就应该研究Vue。 It's great because it features minimum boilerplate (the amount of code necessary to "get started") and offers, essentially, feature parity to other popular solutions. 很棒是因为它具有最少的样板(“入门”所需的代码量),并且从本质上讲,与其他流行的解决方案具有同等的功能。 Other solutions are React, Angular, maybe Ember still exists, Meteor (for full stack stuff) and many more. 其他解决方案包括React,Angular,也许Ember仍然存在,Meteor(用于完整堆栈的东西)等等。 Also, despite it being "on the way out" as more people move away from it, jQuery is still around and still provides a huge set of conveniences instead of working directly with the DOM. 同样,尽管随着越来越多的人离开它,jQuery正在“走出困境”,但jQuery仍然存在,并且仍然提供了大量便利,而不是直接与DOM一起使用。 So there is always that route as well. 因此,总会有这条路线。

The world of JavaScript is too big , and still growing. JavaScript的世界太大了 ,并且还在增长。 So you can really find whatever you want for whatever purpose it serves. 因此,您可以真正找到满足其目的的任何产品。 There's hundreds of MVC frameworks, component frameworks, DOM wrappers, other basic utils, game engines, and on and on and on. 有成百上千的MVC框架,组件框架,DOM包装器,其他基本utils,游戏引擎等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM