致力于开发一个项目是学习编码的最有效方法之一。这是一个有趣的小项目,可了解Vue.js,HTML和CSS。单击上方的“新游戏”以尝试完成产品。
Vue.js简介
Vue.js是一个非常强大且快速的Javascript框架,也很容易学习。您可以使用它来开发从复杂的单页应用程序到简单站点的所有内容。
为了制作Hangman游戏,我们将探索Vue的一些核心功能:
声明式渲染和模板语法。这只是意味着,如果我们声明将Javascript属性设置为某个值,则Vue会将其呈现在页面上。然后,如果稍后更改属性,Vue将检测到更改并以反应方式更新页面。
列表渲染。您可以使用
v-for
Vue指令来迭代数组并呈现列表中的单个项目。事件处理和方法。使用Vue,您可以侦听事件,例如单击按钮,然后使用Javascript方法处理这些事件。
条件渲染。
v-if
Vue也很容易实现基于条件显示和隐藏事物。
建立游戏
以下各节将更详细地介绍上述Vue核心概念,并解释如何在Hangman游戏中使用它们。
列表的声明式渲染
我们使用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
。
事件处理和方法
Vue.js提供了一种方便的语法,用于将事件侦听器附加到HTML元素。事件侦听器通常调用Vue实例中定义的方法。通过使用@
符号+事件名称添加事件侦听器。例如,@click
。
在Hangman游戏中,我们在可能的字母选择上使用事件侦听器。每个字母选择div都有一个click事件监听器,该监听器调用一个tryLetter
声明为的方法<div @click="tryLetter(letter)">
。
如果tryLetter方法在中找到匹配项wordLetters
,则displayLetters
数组将使用进行更新,splice
Vue将在页面上呈现更新。如果您想知道为什么使用拼接,请参阅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 } }})
有条件的渲染
您可以使用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="en" > <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" /> <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("resize", "*"); } </script> </head> <body translate="no" > <div id="app" class="container"> <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;fill:none;stroke-width:2px;" /> <line v-if="strikes > 1" x1="100" y1="257" x2="100" y2="40" style="stroke:black;fill:none;stroke-width:2px;" /> <line v-if="strikes > 2" x1="100" y1="40" x2="230" y2="40" style="stroke:black;fill:none;stroke-width:2px;" /> <line v-if="strikes > 3" x1="100" y1="80" x2="130" y2="40" style="stroke:black;fill:none;stroke-width:2px;" /> <line v-if="strikes > 4" x1="230" y1="40" x2="230" y2="80" style="stroke:black;fill:none;stroke-width:2px;" /> <circle v-if="strikes > 5" cx="230" cy="90" style="fill:khaki;stroke:black;stroke-width:2px;" r="20" /> <line v-if="strikes > 6" x1="230" y1="110" x2="230" y2="170" style="stroke:black;fill:none;stroke-width:2px;" /> <line v-if="strikes > 7" x1="230" y1="140" x2="250" y2="120" style="stroke:black;fill:none;stroke-width:2px;" /> <line v-if="strikes > 8" x1="230" y1="140" x2="210" y2="120" style="stroke:black;fill:none;stroke-width:2px;" /> <line v-if="strikes > 9" x1="230" y1="170" x2="250" y2="200" style="stroke:black;fill:none;stroke-width:2px;" /> <line v-if="strikes > 10" x1="230" y1="170" x2="210" y2="200" style="stroke:black;fill:none;stroke-width:2px;" /> </svg> <div> <div class="letter" v-for="letter in wordDisplayLetters"> {{letter}} </div> </div> <template v-if="initialized"> <div> <div @click="tryLetter(letter)" class="possibleLetter" :class="getStrikethroughClass(letter)" v-for="letter in possibleLetters1"> {{letter}} </div> </div> <div> <div @click="tryLetter(letter)" class="possibleLetter" :class="getStrikethroughClass(letter)" v-for="letter in possibleLetters2"> {{letter}} </div> </div> <div> <div @click="tryLetter(letter)" class="possibleLetter" :class="getStrikethroughClass(letter)" v-for="letter in possibleLetters3"> {{letter}} </div> </div> </template> <button @click="initialize()">New Game</button> </div> <script src="https://static.codepen.io/assets/common/stopExecutionOnTimeout-157cd5b220a5c80d4ff8e0e70ac069bffd87a61252088146915e8726e5d9f147.js"></script> <script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js'></script> <script id="rendered-js" > new Vue({ el: "#app", data: function () { return { strikes: 12, word: "HANGMAN", wordLetters: ['H', 'A', 'N', 'G', 'M', 'A', 'N'], wordDisplayLetters: ['H', 'A', 'N', 'G', 'M', 'A', 'N'], usedLetters: [], possibleLetters1: ["A", "B", "C", "D", "E", "F", "G", "H", "I"], possibleLetters2: ["J", "K", "L", "M", "N", "O", "P", "Q", "R", "S"], possibleLetters3: ["T", "U", "V", "W", "X", "Y", "Z"], 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的最新动态。
网友评论文明上网理性发言 已有1人参与
发表评论:
评论列表