51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

使用Vue.js构建好玩的Hangman游戏

500.jpg

致力于开发一个项目是学习编码的最有效方法之一。这是一个有趣的小项目,可了解Vue.js,HTML和CSS。单击上方的"新游戏"以尝试完成产品。

image.png {#introduction-to-vue-js}

Vue.js简介 {#introduction-to-vue-js}

Vue.js是一个非常强大且快速的Javascript框架,也很容易学习。您可以使用它来开发从复杂的单页应用程序到简单站点的所有内容。

为了制作Hangman游戏,我们将探索Vue的一些核心功能:

  • 声明式渲染和模板语法。这只是意味着,如果我们声明将Javascript属性设置为某个值,则Vue会将其呈现在页面上。然后,如果稍后更改属性,Vue将检测到更改并以反应方式更新页面。

  • 列表渲染。您可以使用v-forVue指令来迭代数组并呈现列表中的单个项目。

  • 事件处理和方法。使用Vue,您可以侦听事件,例如单击按钮,然后使用Javascript方法处理这些事件。

  • 条件渲染。v-ifVue也很容易实现基于条件显示和隐藏事物。

建立游戏 {#building-the-hangman-game}

以下各节将更详细地介绍上述Vue核心概念,并解释如何在Hangman游戏中使用它们。

列表的声明式渲染 {#declarative-rendering-with-lists}

我们使用Vue的声明式渲染和模板语法来渲染整个Hangman游戏中的列表。这可以通过{{ someData }}在HTML模板中使用双胡子括号并引用来自Vue实例的数据来实现。

这是声明式渲染的基本示例。

<div id="app">
  {{message}}
</div>
new Vue({
  el: '#app',
  data: {
      message: 'Lets build a game'
  }
})

以上将呈现文本Lets build a game<div>页面上。

如果基础数据存储在数组中,则v-for可以使用指令来迭代数组并为每个位置呈现HTML元素。Hangman游戏中的一个很好的例子是可能字母的列表。

<div id="vfor">
  <!-- the v-for directive loops the array giving us access to each
  letter, which we can then render in the template -->
  <div v-for="letter in possibleLetters" class="possibleLetter">
    {{letter}}
  </div>
</div>
new Vue({
  el: '#vfor',
  data: {
    possibleLetters: ['A', 'B', 'C', 'D', 'E', 'F', 'G']
  }
})

这将呈现如下所示的字母。如果右键单击下面的字母,您将看到每个字母都是循环<div>{{letter}}</div>渲染的单个字母v-for

image.png

事件处理和方法 {#event-handling-and-methods}

Vue.js提供了一种方便的语法,用于将事件侦听器附加到HTML元素。事件侦听器通常调用Vue实例中定义的方法。通过使用@符号+事件名称添加事件侦听器。例如,@click

在Hangman游戏中,我们在可能的字母选择上使用事件侦听器。每个字母选择div都有一个click事件监听器,该监听器调用一个tryLetter声明为的方法<div @click="tryLetter(letter)">

如果tryLetter方法在中找到匹配项wordLetters,则displayLetters数组将使用进行更新,spliceVue将在页面上呈现更新。如果您想知道为什么使用拼接,请参阅Vue文档中的此警告

这是the子手游戏的一个例子。单击下面的字母以查看您是否可以完成该单词。


<div id="eventlistener">
  <!-- the @click listener will call the tryLetter method after the click event
  on one of the letters -->
  <div>
    <div v-for="letter in displayLetters" class="letter">
      {{letter}}
    </div>
  </div>
  <div>
    <div @click="tryLetter(letter)" v-for="letter in possibleLetters" class="possibleLetter">
      {{letter}}
    </div>
  </div>
  <div>
   {{console}}
  </div>
</div>
new Vue({  el: '#eventlistener',  data: {    displayLetters: ['','','',''],    wordLetters: ['C','O','O','L'],    possibleLetters: ['A', 'B', 'C', 'L', 'O'],    console: 'Click a letter above to see the result'
  },
  methods: {
    tryLetter(letter) {
      for (let i = 0; i < this.displayLetters.length; i++) {        if (letter === this.wordLetters[i]) {          this.displayLetters.splice(i, 1, letter)
        }
      }
      this.console = 'I tried letter ' + letter
    }
  }})

image.png

有条件的渲染 {#conditional-rendering}

您可以使用v-if指令有条件地在页面中添加或删除元素。甲v-if指令引用的一个布尔数据属性,条件表达式或返回boolean的方法。

在Hangman游戏中,每次选择单词中找不到的字母时,我们都会记录罢工,并使用v-if指令有条件地渲染SVG图的一部分。

这是一个简化的示例。单击按钮记录罢工并查看其动作。

<div id="conditionalrendering">
  <!-- The divs will be automatically rendered when the v-if condition becomes true -->
  <button @click="addStrike">
    Add Strike
  </button>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="350px" height="275px" viewBox="0 0 350 300" preserveAspectRatio="xMidYMid meet">
    <line v-if="strikes > 0" x1="80" y1="257" x2="260" y2="257" style="stroke:black;" />
    <line v-if="strikes > 1" x1="100" y1="257" x2="100" y2="40" style="stroke:black;" />
    <line v-if="strikes > 2" x1="100" y1="40" x2="230" y2="40" style="stroke:black;" />
    <line v-if="strikes > 3" x1="100" y1="80" x2="130" y2="40" style="stroke:black;" />
    <line v-if="strikes > 4" x1="230" y1="40" x2="230" y2="80" style="stroke:black;" />
    <circle v-if="strikes > 5" cx="230" cy="90" style="fill:khaki;stroke:black;" r="20" />
    <line v-if="strikes > 6" x1="230" y1="110" x2="230" y2="170" style="stroke:black;" />
    <line v-if="strikes > 7" x1="230" y1="140" x2="250" y2="120" style="stroke:black;" />
    <line v-if="strikes > 8" x1="230" y1="140" x2="210" y2="120" style="stroke:black;" />
    <line v-if="strikes > 9" x1="230" y1="170" x2="250" y2="200" style="stroke:black;" />
    <line v-if="strikes > 10" x1="230" y1="170" x2="210" y2="200" style="stroke:black;" />
  </svg></div>
new Vue({
  el: '#conditionalrendering',
  data: {
    strikes: 0
  },
  methods: {
    addStrike() {
      this.strikes++
    }
  }
})

OK,大概介绍就这些内容,最后还是放下具体的DEMO实例吧。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="apple-touch-icon" type="image/png" href="https://static.codepen.io/assets/favicon/apple-touch-icon-5ae1a0698dcc2402e9712f7d01ed509a57814f994c660df9f7a952f3060705ee.png" />
<meta name="apple-mobile-web-app-title" content="CodePen">
<link rel="shortcut icon" type="image/x-icon" href="https://static.codepen.io/assets/favicon/favicon-aec34940fbc1a6e787974dcd360f2c6b63348d4b1f4e06c77743096d55480f33.ico" />
<link rel="mask-icon" type="" href="https://static.codepen.io/assets/favicon/logo-pin-8f3771b1072e3c38bd662872f6b673a722f4b3ca2421637d5596661b4e2132cc.svg" color="#111" />
<meta charset="utf-8">
<meta name='viewport' content='width=device-width, initial-scale=1'>
<title>CodePen - hangman-game</title>
<link rel="stylesheet" media="screen" href="https://static.codepen.io/assets/fullpage/fullpage-4de243a40619a967c0bf13b95e1ac6f8de89d943b7fc8710de33f681fe287604.css" />
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,400italic,700,700italic,900,900italic" rel="stylesheet" />
<link rel="apple-touch-icon" type="image/png" href="https://static.codepen.io/assets/favicon/apple-touch-icon-5ae1a0698dcc2402e9712f7d01ed509a57814f994c660df9f7a952f3060705ee.png" />
<meta name="apple-mobile-web-app-title" content="CodePen">
<link rel="shortcut icon" type="image/x-icon" href="https://static.codepen.io/assets/favicon/favicon-aec34940fbc1a6e787974dcd360f2c6b63348d4b1f4e06c77743096d55480f33.ico" />
<link rel="mask-icon" type="" href="https://static.codepen.io/assets/favicon/logo-pin-8f3771b1072e3c38bd662872f6b673a722f4b3ca2421637d5596661b4e2132cc.svg" color="#111" />
<title>hangman-game - Web前端之家https://www.jiangweishan.com</title>
<script>
  if (document.location.search.match(/type=embed/gi)) {
    window.parent.postMessage("resize", "*");
  }
</script>
<style>
    html { font-size: 15px; }
    html, body { margin: 0; padding: 0; min-height: 100%; }
    body { height:100%; display: flex; flex-direction: column; }
    .referer-warning {
      background: black;
      box-shadow: 0 2px 5px rgba(0,0,0, 0.5);
      padding: 0.75em;
      color: white;
      text-align: center;
      font-family: 'Lato', 'Lucida Grande', 'Lucida Sans Unicode', Tahoma, Sans-Serif;
      line-height: 1.2;
      font-size: 1rem;
      position: relative;
      z-index: 2;
    }
    .referer-warning h1 { font-size: 1.2rem; margin: 0; }
    .referer-warning a { color: #56bcf9; } /* $linkColorOnBlack */
  </style>
</head>
<body class="">

<div id="result-iframe-wrap" role="main">
<iframe id="result" srcdoc="
<!DOCTYPE html>
<html lang=&quot;en&quot; >

<head>

  <meta charset=&quot;UTF-8&quot;>
  
<link rel=&quot;apple-touch-icon&quot; type=&quot;image/png&quot; href=&quot;https://static.codepen.io/assets/favicon/apple-touch-icon-5ae1a0698dcc2402e9712f7d01ed509a57814f994c660df9f7a952f3060705ee.png&quot; />
<meta name=&quot;apple-mobile-web-app-title&quot; content=&quot;CodePen&quot;>

<link rel=&quot;shortcut icon&quot; type=&quot;image/x-icon&quot; href=&quot;https://static.codepen.io/assets/favicon/favicon-aec34940fbc1a6e787974dcd360f2c6b63348d4b1f4e06c77743096d55480f33.ico&quot; />

<link rel=&quot;mask-icon&quot; type=&quot;&quot; href=&quot;https://static.codepen.io/assets/favicon/logo-pin-8f3771b1072e3c38bd662872f6b673a722f4b3ca2421637d5596661b4e2132cc.svg&quot; color=&quot;#111&quot; />


  <title>CodePen - hangman-game</title>
  
  
  
  
<style>
.container {
  text-align: center;
}

.letter {
  display: inline-block;
  border-bottom: 1px solid;
  margin: 0px 3px 0px 3px;
  font-size: 35px;
  min-width: 30px;
  vertical-align: bottom;
}

.possibleLetter {
  display: inline-block;
  margin: 10px 3px 0px 3px;
  font-size: 35px;
  min-width: 30px;
  cursor: pointer;
}

.diagonal-strike {
  background: linear-gradient(to left top, transparent 47.75%, currentColor 49.5%, currentColor 50.5%, transparent 52.25%);
  color: dimgrey;
}

button {
  margin-top: 20px;
  padding: 5px;
}
</style>

  <script>
  window.console = window.console || function(t) {};
</script>

  
  
  <script>
  if (document.location.search.match(/type=embed/gi)) {
    window.parent.postMessage(&quot;resize&quot;, &quot;*&quot;);
  }
</script>


</head>

<body translate=&quot;no&quot; >
  <div id=&quot;app&quot; class=&quot;container&quot;>
  <svg xmlns=&quot;http://www.w3.org/2000/svg&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot; width=&quot;350px&quot; height=&quot;275px&quot; viewBox=&quot;0 0 350 300&quot; preserveAspectRatio=&quot;xMidYMid meet&quot;>
<line v-if=&quot;strikes > 0&quot; x1=&quot;80&quot; y1=&quot;257&quot; x2=&quot;260&quot; y2=&quot;257&quot; style=&quot;stroke:black;fill:none;stroke-width:2px;&quot; />
<line v-if=&quot;strikes > 1&quot; x1=&quot;100&quot; y1=&quot;257&quot; x2=&quot;100&quot; y2=&quot;40&quot; style=&quot;stroke:black;fill:none;stroke-width:2px;&quot; />
<line v-if=&quot;strikes > 2&quot; x1=&quot;100&quot; y1=&quot;40&quot; x2=&quot;230&quot; y2=&quot;40&quot; style=&quot;stroke:black;fill:none;stroke-width:2px;&quot; />
<line v-if=&quot;strikes > 3&quot; x1=&quot;100&quot; y1=&quot;80&quot; x2=&quot;130&quot; y2=&quot;40&quot; style=&quot;stroke:black;fill:none;stroke-width:2px;&quot; />
<line v-if=&quot;strikes > 4&quot; x1=&quot;230&quot; y1=&quot;40&quot; x2=&quot;230&quot; y2=&quot;80&quot; style=&quot;stroke:black;fill:none;stroke-width:2px;&quot; />
<circle v-if=&quot;strikes > 5&quot; cx=&quot;230&quot; cy=&quot;90&quot; style=&quot;fill:khaki;stroke:black;stroke-width:2px;&quot; r=&quot;20&quot; />
<line v-if=&quot;strikes > 6&quot; x1=&quot;230&quot; y1=&quot;110&quot; x2=&quot;230&quot; y2=&quot;170&quot; style=&quot;stroke:black;fill:none;stroke-width:2px;&quot; />
<line v-if=&quot;strikes > 7&quot; x1=&quot;230&quot; y1=&quot;140&quot; x2=&quot;250&quot; y2=&quot;120&quot; style=&quot;stroke:black;fill:none;stroke-width:2px;&quot; />
<line v-if=&quot;strikes > 8&quot; x1=&quot;230&quot; y1=&quot;140&quot; x2=&quot;210&quot; y2=&quot;120&quot; style=&quot;stroke:black;fill:none;stroke-width:2px;&quot; />
<line v-if=&quot;strikes > 9&quot; x1=&quot;230&quot; y1=&quot;170&quot; x2=&quot;250&quot; y2=&quot;200&quot; style=&quot;stroke:black;fill:none;stroke-width:2px;&quot; />
<line v-if=&quot;strikes > 10&quot; x1=&quot;230&quot; y1=&quot;170&quot; x2=&quot;210&quot; y2=&quot;200&quot; style=&quot;stroke:black;fill:none;stroke-width:2px;&quot; />
</svg>
  <div>
    <div class=&quot;letter&quot; v-for=&quot;letter in wordDisplayLetters&quot;>
      {{letter}}
    </div>
  </div>
  <template v-if=&quot;initialized&quot;>
  <div>
    <div @click=&quot;tryLetter(letter)&quot; class=&quot;possibleLetter&quot; :class=&quot;getStrikethroughClass(letter)&quot; v-for=&quot;letter in possibleLetters1&quot;>
      {{letter}}
    </div>
  </div>
  <div>
    <div @click=&quot;tryLetter(letter)&quot; class=&quot;possibleLetter&quot; :class=&quot;getStrikethroughClass(letter)&quot; v-for=&quot;letter in possibleLetters2&quot;>
      {{letter}}
    </div>
  </div>
  <div>
    <div @click=&quot;tryLetter(letter)&quot; class=&quot;possibleLetter&quot; :class=&quot;getStrikethroughClass(letter)&quot; v-for=&quot;letter in possibleLetters3&quot;>
      {{letter}}
    </div>
  </div>
  </template>
  <button @click=&quot;initialize()&quot;>New Game</button>
</div>
    <script src=&quot;https://static.codepen.io/assets/common/stopExecutionOnTimeout-157cd5b220a5c80d4ff8e0e70ac069bffd87a61252088146915e8726e5d9f147.js&quot;></script>

  <script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js'></script>
  
      <script id=&quot;rendered-js&quot; >
new Vue({
  el: &quot;#app&quot;,
  data: function () {
    return {
      strikes: 12,
      word: &quot;HANGMAN&quot;,
      wordLetters: ['H', 'A', 'N', 'G', 'M', 'A', 'N'],
      wordDisplayLetters: ['H', 'A', 'N', 'G', 'M', 'A', 'N'],
      usedLetters: [],
      possibleLetters1: [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;, &quot;E&quot;, &quot;F&quot;, &quot;G&quot;, &quot;H&quot;, &quot;I&quot;],
      possibleLetters2: [&quot;J&quot;, &quot;K&quot;, &quot;L&quot;, &quot;M&quot;, &quot;N&quot;, &quot;O&quot;, &quot;P&quot;, &quot;Q&quot;, &quot;R&quot;, &quot;S&quot;],
      possibleLetters3: [&quot;T&quot;, &quot;U&quot;, &quot;V&quot;, &quot;W&quot;, &quot;X&quot;, &quot;Y&quot;, &quot;Z&quot;],
      initialized: false };

  },
  methods: {
    initialize() {
      this.initialized = true;
      this.strikes = 0;
      this.word = 'AWESOME';
      this.wordLetters = this.word.split('');
      this.wordDisplayLetters = Array(this.word.length);
      this.usedLetters = [];
    },
    tryLetter(letter) {
      if (this.usedLetters.includes(letter)) {
        return;
      }

      this.usedLetters.push(letter);
      let match = false;
      for (let i = 0; i < this.wordDisplayLetters.length; i++) {if (window.CP.shouldStopExecution(0)) break;
        if (letter === this.wordLetters[i]) {
          this.wordDisplayLetters.splice(i, 1, letter);
          match = true;
        }
      }window.CP.exitedLoop(0);

      if (!match) {
        this.strikes++;
      }
    },
    getStrikethroughClass(letter) {
      if (this.usedLetters.includes(letter)) {
        return 'diagonal-strike';
      }
      return null;
    } } });
//# sourceURL=pen.js
    </script>

  

</body>

</html>
 
" sandbox="allow-downloads allow-forms allow-modals allow-pointer-lock allow-popups allow-presentation  allow-scripts allow-top-navigation-by-user-activation" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; microphone; midi; payment; vr" allowTransparency="true" allowpaymentrequest="true" allowfullscreen="true">
      </iframe>
</div>
</body>
</html>

总结

用vuejs做游戏还是挺好玩的啊,现在vue3.0也出来了,后面会整理下vue3.0的中文教程,期待吧!您可以留言或者加群,探讨vuejs的最新动态。

赞(0)
未经允许不得转载:工具盒子 » 使用Vue.js构建好玩的Hangman游戏