致力于开发一个项目是学习编码的最有效方法之一。这是一个有趣的小项目,可了解Vue.js,HTML和CSS。单击上方的"新游戏"以尝试完成产品。
{#introduction-to-vue-js}
Vue.js简介 {#introduction-to-vue-js}
Vue.js是一个非常强大且快速的Javascript框架,也很容易学习。您可以使用它来开发从复杂的单页应用程序到简单站点的所有内容。
为了制作Hangman游戏,我们将探索Vue的一些核心功能:
-
声明式渲染和模板语法。这只是意味着,如果我们声明将Javascript属性设置为某个值,则Vue会将其呈现在页面上。然后,如果稍后更改属性,Vue将检测到更改并以反应方式更新页面。
-
列表渲染。您可以使用
v-for
Vue指令来迭代数组并呈现列表中的单个项目。 -
事件处理和方法。使用Vue,您可以侦听事件,例如单击按钮,然后使用Javascript方法处理这些事件。
-
条件渲染。
v-if
Vue也很容易实现基于条件显示和隐藏事物。
建立游戏 {#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
。
事件处理和方法 {#event-handling-and-methods}
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
}
}})
有条件的渲染 {#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="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的最新动态。