vue 井号_使用Vue 2制作井字游戏:第1部分

vue 井号

This tutorial assumes that you have a little prior knowledge of JavaScript and the Vue framework. You also need to have Node and Git installed on your system.

本教程假定您具有JavaScript和Vue框架的先验知识。 您还需要在系统上安装Node和Git。

介绍 ( Introduction )

This tutorial focuses on building a game with the Vue framework. You will also learn about vue-cli, vue-loader and the workflow of making user interfaces for the web using Vue. At the end of the tutorial, you will have a playable Tic-Tac-Toe game like this below:

本教程重点介绍使用Vue框架构建游戏。 您还将了解vue-clivue-loader和使用Vue制作Web用户界面的工作流程。 在本教程的最后,您将拥有一个可玩的井字游戏,如下所示:

什么是井字游戏? ( What is Tic-Tac-Toe? )

In this tutorial, we are going to build a simple tic-tac-toe game with the Vue framework. Tic-Tac-Toe is a two-players pencil and paper game. One player is Cross 'X' and the other one is Nought 'O'. The game is based on a 3x3 grid with each box in the grid having the space to be marked with either X or O. One move consists of one mark. The game is turn-based meaning that players own a move one after the other. Once a mark has been placed, it cannot be altered. So, who wins the game? The one who is able to place 3 consecutive Xs or Os in a line. The line can be vertical, horizontal or diagonal. And to get acquainted with it, search Google for tic-tac-toe and play it the times until you don't want to any longer.

在本教程中,我们将使用Vue框架构建一个简单的井字游戏。 Tic-Tac-Toe是两人玩的纸笔游戏。 一个球员是十字“X”,另一个是徒劳“O”。 游戏基于3x3网格,网格中的每个框都有要用XO标记的空间。 一招由一分组成。 游戏是基于回合制的,这意味着玩家拥有一个接一个的动作。 标记一旦放置,就无法更改。 那么,谁赢得了比赛? 能够在一行中连续放置3个X或O的人。 该线可以是垂直,水平或对角线。 并且要熟悉它,请在Google上搜索 井字游戏,并播放几次,直到您不再想要。

Game Board

Hey Hammad, I already knew all this stuff and I've played it a hundred times before? I know, I know. Forgive me for this intro and let's get started to dive in.

嘿哈玛德,我已经知道所有这些东西了,我玩过一百次了吗? 我知道我知道。 请原谅我的介绍,让我们开始深入。

为什么选择Vue ( Why Vue )

Vue Website

This version of Tic-Tac-Toe is going to be browser-based and implemented using Vue. The reason we are building it with Vue is that there can't be anything simpler than that. And by anything, I mean any other JavaScript framework. You know you can use something else. But in this particular tutorial, you have to stick by me.

此版本的Tic-Tac-Toe将基于浏览器并使用Vue实施。 我们之所以用Vue构建它,是因为没有比这更简单的了。 而到任何东西 ,我的意思是任何其他JavaScript框架。 您知道您可以使用其他东西。 但是在这个特定的教程中,您必须坚持我。

建立 ( Setup )

For the setup, we are going to use vue-loader with vue-cli.

对于设置,我们将使用vue-loadervue-cli

Vue-Cli (vue-cli)

vue-cli is a simple CLI (Command Line Interface) tool for scaffolding Vue projects. It provides project boilerplate, allows you to write ES2015, convert processors into plain CSS and handles all the rest. Install vue-cli on your machine using the following command:

vue-cli是用于搭建Vue项目的简单CLI(命令行界面)工具。 它提供了项目样板,允许您编写ES2015,将处理器转换为纯CSS并处理所有其余内容。 使用以下命令在您的计算机上安装vue-cli:

npm install -g vue-cli

Now that you vue-cli, run the following commands in the terminal for vue-cli to scaffold the project structure for you:

现在您已经建立了vue-cli,在终端中运行以下命令以使vue-cli可以为您搭建项目结构:

vue init webpack-simple vue-tic-tac-toe

Here, vue-tic-tac-toe is the name of the project, in which vue-cli will init in. webpack-simple is a template that includes both Webpack and vue-loader.

在这里,VUE,井字棋是项目,其中VUE-CLI将在初始化的名字。 的WebPack,简单的是包括的WebPack和VUE装载机的模板。

After that, cd in the vue-tic-tac-toe and install the dependencies using npm:

之后,在vue-tic-tac-toe中使用cd并使用npm安装依赖项:

cd vue-tic-tac-toe
npm install

加载器 (vue-loader)

vue-loader is a loader for Webpack that allows you to write the template and CSS for a component all in one file. The file needs to have .vue extension. This is how an example .vue file looks like:

vue-loader是Webpack的加载器,它使您可以在一个文件中编写组件的模板和CSS。 该文件必须具有.vue扩展名。 这是一个示例.vue文件的样子:

<template>
    <div class="message">
        {{ speaker }} says: {{ message }} to the <world></world>
    </div>
</template>

<script>
    import World from './World.vue'

    export default {
        components: { World },
        data () {
            return {
                speaker: 'Hammad',
                message: 'I will rule the world'
            }
        }
    }
</script>

<style>
    .message {
        padding: 10px;
        background-color: steelblue;
        color: #fff;
    }
</style>

Create a components folder in the src directory present in the root. It will contain all of our components. Now that everything is ready, run this command to view this app in the browser:

在根目录下的src目录中创建一个components文件夹。 它将包含我们所有的组件。 现在一切就绪,运行以下命令在浏览器中查看此应用程序:

npm run dev

This command will load http://localhost:8080/ in the browser. Every change you make in your code will be reflected in the browser even without refreshing the page. Open App.vue in your code editor and delete all the unnecessary stuff present in the template and script tag. Now your App.vue file looks like this:

该命令将在浏览器中加载http://localhost:8080/ 。 您对代码进行的每项更改都将反映在浏览器中,即使不刷新页面也是如此。 在代码编辑器中打开App.vue,然后删除模板和脚本标签中存在的所有不必要的内容。 现在,您的App.vue文件如下所示:

<template>
  <div id="app">

  </div>
</template>

<script>
export default {
  name: 'app',
  data () {
    return {

    }
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

h1, h2 {
  font-weight: normal;
}

ul {
  list-style-type: none;
  padding: 0;
}

li {
  display: inline-block;
  margin: 0 10px;
}

a {
  color: #42b983;
}
</style>

游戏元素 ( Game Elements )

Thinking of this game, all the things that come to my mind are:

考虑到这个游戏,我想到的所有东西都是:

  • 2 Players (X and O)

    2位玩家(X和O)
  • The Board Grid

    板格

Grid Board

  • 3 Rows

    3排
  • 3 Columns

    3栏
  • 9 Grid Cells

    9个网格单元
  • Scoreboard (The number of wins for each player)

    计分板(每个玩家的获胜数)

Scoreboard

  • Number of match being played

    参加比赛的次数

Match Number

  • Player turn

    玩家回合

Game Status

  • Restarting the game

    重新开始游戏

Game Restart

We will extract some of them elements into their own components and others as properties of those components.

我们将其中一些元素提取到它们自己的组件中,并将其他元素提取为那些组件的属性。

Vue组件 ( Vue Components )

The benefit of using components is that we can reuse them. Like, we can use the Cell component 9 times, without having the need to duplicate it. This keeps our code DRY (Don't Repeat Yourself). Our component structure will look like this:

使用组件的好处是我们可以重用它们。 就像,我们可以使用Cell组件9次,而无需重复它。 这使我们的代码保持干燥(不要重复自己)。 我们的组件结构如下所示:

-- App
---- Board
------ Cell x9

Create these components: Board.vue and Cell.vue in the components folder with the following boilerplate code.

创建以下组件:具有以下样板代码的components文件夹中的Board.vue和Cell.vue。

<template>

</template>

<script>
    export default {
        data () {}
    }
</script>

<style>

</style>

造型 ( Styling )

To make sure that this game doesn't hurt your eyes, you can grab all the styling and fonts from here and paste them in your code.

为确保该游戏不会伤害您的眼睛,您可以从此处获取所有样式和字体,并将其粘贴到代码中。

In the index.html file, I only added two fonts and changed the title. The Dosis font is for the whole body and the Gochi Hand font is for the X and O placed in the grid. Both are taken from Google Fonts. This is how our index.html file looks like:

index.html文件中,我仅添加了两种字体并更改了标题。 Dosis字体适用于整个身体, Gochi Hand字体适用于放置在网格中的X和O。 两者均取自Google字体。 这就是我们的index.html文件的样子:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Tic-Tac-Toe Game</title>
    <link href="https://fonts.googleapis.com/css?family=Dosis|Gochi+Hand" rel="stylesheet">
  </head>
  <body>
    <div id="app"></div>
    <script src="/dist/build.js"></script>
  </body>
</html>

Change the <style> tag of your App component to this:

将您的App组件的<style>标记更改为此:

<style>
body {
  background-color: #fff;
  color: #fff;
  font-family: 'Dosis', Helvetica, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  margin: 0px;
}

#app {
  margin: 0 auto;
  max-width: 270px;
  color: #34495e;
}

h1 {
  text-transform: uppercase;
  font-weight: bold;
  font-size: 3em;
}

.restart {
  background-color: #e74c3c;
  color: #fff;
  border: 0px;
  border-bottom-left-radius: 10px;
  border-bottom-right-radius: 10px;
  font-family: 'Dosis', Helvetica, sans-serif;
  font-size: 1.4em;
  font-weight: bold;
  margin: 0px;
  padding: 15px;
  width: 100%;
}

.restart:hover {
  background-color: #c0392b;
  cursor: pointer;
}

.scoreBoard {
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  align-items: center;
  width: 100%;
  height: 15px;
  background-color: #16a085;
  box-shadow: 10px solid #fff;
  padding: 20px;
  overflow-x: none;
}

.scoreBoard h2 {
  margin: 0px;
}

.scoreBoard span {
  float: right;
  font-size: 1.5em;
  font-weight: bold;
  margin-left: 20px;
}
</style>

Add this to the <style> tag of the Grid component:

将此添加到Grid组件的<style>标记中:

.grid {
  background-color: #34495e;
  color: #fff;
  width: 100%;
  border-collapse: collapse;
}

.gameStatus {
  margin: 0px;
  padding: 15px;
  border-top-left-radius: 20px;
  border-top-right-radius: 20px;
  background-color: #f1c40f;
  color: #fff;    
  font-size: 1.4em;
  font-weight: bold;
}

.statusTurn {
    background-color: #f1c40f;
}

.statusWin {
    background-color: #2ecc71;
}

.statusDraw {
    background-color: #9b59b6;
}

And this to that of the Cell component:

这与Cell组件有关:

.cell {
  width: 33.333%;
  height: 90px;
  border: 6px solid #2c3e50;
  font-size: 3.5em;
  font-family: 'Gochi Hand', sans-serif;
}

.cell:hover {
    background-color: #7f8c8d;
}

.cell::after {
  content: '';
  display: block;
}

.cell:first-of-type {
  border-left-color: transparent;
  border-top-color: transparent;
}

.cell:nth-of-type(2) {
  border-top-color: transparent;
}

.cell:nth-of-type(3) {
  border-right-color: transparent;
  border-top-color: transparent;
}

tr:nth-of-type(3) .cell {
  border-bottom-color: transparent;
}

组件模板 ( Component Templates )

The template section of a component contains all the markup that makes up the component. Our App component will contain the Gird component and the Gird component will contain 9 Cell components. The App component is very simple and only contains a heading and a grid for the game. We will add more functionality later.

组件的模板部分包含组成该组件的所有标记。 我们的App组件将包含Gird组件,而Gird组件将包含9个Cell组件。 App组件非常简单,仅包含游戏的标题和网格。 稍后我们将添加更多功能。

<div id="app">
  <div id="details">
    <h1>Tic Tac Toe</h1>
  </div>
  <grid></grid>
</div>

The Grid component contains a table that has three rows and three cells in each row. The cell number is passed down as a prop to uniquely identify each cell. The template of the Grid component:

网格组件包含一个表,该表具有三行和每行三个单元格。 信元编号作为唯一标识每个信元的道具向下传递。 Grid组件的模板:

<table class="grid">
  <tr>
    <cell name="1"></cell>
    <cell name="2"></cell>
    <cell name="3"></cell>
  </tr>
  <tr>
    <cell name="4"></cell>
    <cell name="5"></cell>
    <cell name="6"></cell>
  </tr>
  <tr>
    <cell name="7"></cell>
    <cell name="8"></cell>
    <cell name="9"></cell>
  </tr>
</table>

The Cell component contains only a <td> tag to hold the mark X or O.

Cell组件仅包含<td>标记,以保留标记XO。

<td class="cell">{{ mark }}</td>

游戏流程 ( The Game Flow )

To start adding functionality to our game, we need to determine the flow of events which will take place with each user interaction. The flow of the game is as follows:

要开始为我们的游戏添加功能,我们需要确定每次用户交互都会发生的事件流。 游戏流程如下:

  • The App is loaded.

    该应用已加载。
  • All cells are empty.

    所有单元格均为空。
  • O is the first player.

    O是第一位玩家。
  • The player can place an O in any of the cells.

    玩家可以在任何单元格中放置一个O。
  • The player-turn is changed X.

    玩家回合更改为X。
  • Each time a player places a mark, the turn is handed to the non-active player.

    每次玩家放置一个标记,该回合将移交给无效玩家。
  • After each strike, we need to check if the game meets any winning condition.

    每次罢工后,我们需要检查游戏是否满足任何获胜条件。
  • We also need to check if the game is a draw.

    我们还需要检查游戏是否平局。
  • After or anytime in between a game, a button called Restart can be clicked to restart the game.

    在游戏之后或之间的任何时间,都可以单击名为“ 重新启动”的按钮以重新启动游戏。
  • The status of the game that is if the game is in progress or won or is a draw.

    游戏的状态,即游戏进行中,获胜或平局。
  • In terms of progress, the status displays the turn of the respective player.

    根据进度,状态显示相应玩家的回合。
  • The game also displays the number of matches and the number of wins for each player.

    游戏还会显示每个玩家的比赛次数和获胜次数。

For all of this to be able to happen, our components need some data properties and methods.

为了使所有这些事情都能发生,我们的组件需要一些数据属性和方法。

资料属性 ( Data Properties )

We will divide the data among the components according to their relation or ease of access to that component.

我们将根据组件之间的关系或访问该组件的难易程度在组件之间划分数据。

The App component will hold the number of matches and the number of wins for each player.

应用程序组件将保留每个玩家的比赛次数和获胜次数。

data () {
    return {
      matches: 0,
      wins: {
        O: 0,
        X: 0
      }
    }
}

The Grid component holds the data for the active player (X or O), the game status, status message, status color (for displaying on the top bar), the number of moves played by both players to (check for a draw), the mark placement for each cell and all (8) the winning conditions. The winning conditions array contains 8 arrays, and each array contains possible winning same cell (all X or all O) mark arrangement of cell number. These conditions can be compared with the cells object to check for a win.

网格组件保存活动玩家的数据( XO ),游戏状态,状态消息,状态颜色(用于显示在顶部栏上),两个玩家进行的移动次数(检查抽签),每个单元的标记位置以及所有(8)获胜条件。 获胜条件数组包含8个数组,每个数组包含可能的获胜同一个单元格(所有X或所有O )标记的单元格编号排列。 可以将这些条件与单元格对象进行比较以检查获胜。

data () {
  return {
      // can be O or X
      activePlayer: 'O',
      // maintains the status of the game: turn or win or draw
      gameStatus: 'turn',

      gameStatusMessage: `O's turn`,
      // status color is used as background color in the status bar
      // it can hold the name of either of the following CSS classes
      // statusTurn (default) is yellow for a turn
        // statusWin is green for a win
        // statusDraw is purple for a draw
      gameStatusColor: 'statusTurn',
      // no. of moves played by both players in a single game (max = 9)
      moves: 0,
      // stores the placement of X and O in cells by their cell number
        cells: {
            1: '', 2: '', 3: '',
            4: '', 5: '', 6: '',
            7: '', 8: '', 9: ''
        },
        // contains all (8) possible winning conditions
        winConditions: [
            [1, 2, 3], [4, 5, 6], [7, 8, 9], // rows
            [1, 4, 7], [2, 5, 8],    [3, 6, 9], // columns
            [1, 5, 9], [3, 5, 7]             // diagonals
        ],
  }
}

The Cell component holds the mark that the player placed in it. By default that value is set to an empty string. The frozen property is used to ensure that the player is not able to change the mark, once it is placed.

Cell组件保留玩家放置在其中的标记。 默认情况下,该值设置为空字符串。 冻结属性用于确保放置标记后玩家无法更改标记。

props: ['name'],
data () {
    return {
     // enables the player to place a mark
     frozen: false,

        // holds either X or O to be displayed in the td
        mark: ''
    }    
}

The Cell component also has a name prop for uniquely identifying each cell with a number.

单元组件还具有名称道具,用于用数字唯一标识每个单元。

活动巴士 ( Event Bus )

Our components need to talk to each other to inform them about a change in their data property or an action performed by the user like placing a mark in a cell. To do so, we will use an event bus. To make an event bus, we will assign a new Vue instance to a property called Event on the window object. You can change this to anything you want depending on the context of your code, but Event, here, will do just fine.

我们的组件需要互相交谈,以通知他们有关其数据属性的更改或用户执行的操作,例如在单元格中放置标记。 为此,我们将使用事件总线。 为了创建事件总线,我们将新的Vue实例分配给窗口对象上名为Event的属性。 您可以根据代码的上下文将其更改为所需的任何内容,但是这里的Event会很好。

window.Event = new Vue()

With it, you can do things like Event.$emit() and Event.$on for firing and listening to events respectively. The event name as the first argument. You can also include any other data after the name argument. The other data is called Payload. Consider this example:

有了它,您可以分别执行Event.$emit()Event.$on来触发和监听事件。 事件名称作为第一个参数。 您还可以在name参数之后包含其他任何数据。 其他数据称为有效负载。 考虑以下示例:

Event.$emit('completed', this.task)

This fires an event called completed and passes this.task as payload. You can listen to this event fire with the Event.$on() method like this:

这将触发一个名为complete的事件,并将this.task作为有效载荷传递。 您可以使用Event.$on()方法侦听此事件触发:

Event.$on('completed' (task) => {
    // do something
})

To continue listening to an event fire, we can place the Event.$on method in the created method of that Vue component.

为了继续监听事件,我们可以将Event.$on方法放在该Vue组件的创建方法中。

created () {
    Event.$on('completed' (task) => {
        // do something
    })
}

After adding the Event bus to your main.js file, it will look like this:

将事件总线添加到main.js文件后,它将如下所示:

import Vue from 'vue'
import App from './App.vue'

window.Event = new Vue()

new Vue({
  el: '#app',
  render: h => h(App)
})

Now, we are ready to fire and listen for events in our game.

现在,我们准备解雇并监听游戏中的事件。

下一步是什么 ( What's Next )

We will continue, adding functionality to our game, in a follow-up lesson of this two-part series.

在这个分为两部分的系列的后续课程中,我们将继续为游戏添加功能。

结论 ( Conclusion )

In this tutorial, we wireframed almost all the parts of our game. We have added styling, templates and data properties and distributed them among components. At the end, we also created an event bus to handle all of the data flow and user action notifications between our components. If you did not undertand something, experienced a bug or have some other question, feel free to ask in the comments below.

在本教程中,我们对游戏的几乎所有部分进行了线框设计。 我们添加了样式,模板和数据属性,并将它们分布在组件之间。 最后,我们还创建了一个事件总线,以处理组件之间的所有数据流和用户操作通知。 如果您不了解任何内容,遇到错误或有其他问题,请随时在下面的评论中提问。

翻译自: https://scotch.io/tutorials/building-a-tic-tac-toe-game-with-vue-2-part-1

vue 井号

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue.js应用程序中,可以使用环境变量来管理应用程序中的机密信息或配置。为了使这些环境变量在应用程序中可用,需要使用以“VUE_APP_”开头的特殊前缀定义它们。在应用程序中,您可以使用process.env对象访问这些环境变量。下面是一个简单的例子,展示了如何在Vue.js应用程序中定义和使用环境变量: 1. 定义环境变量 在您的Vue.js项目中,您可以在项目根目录下创建一个名为“.env”(或“.env.<mode>”)的文件来定义环境变量。其中,<mode>为您的应用程序环境的名称(例如“development”或“production”)。 在.env文件中,您可以定义以“VUE_APP_”开头的环境变量,如下所示: ``` VUE_APP_TITLE=My App VUE_APP_API_URL=http://localhost:3000/api ``` 请注意,这些环境变量只能在应用程序的JavaScript代码中使用,而不能在HTML或CSS中使用。 2. 在Vue.js应用程序中使用环境变量 您可以在Vue.js应用程序中使用process.env对象来访问这些环境变量。例如,以下代码段展示了如何使用在.env文件中定义的变量: ```javascript <template> <div> <h1>{{ title }}</h1> <p>API URL: {{ apiUrl }}</p> </div> </template> <script> export default { data() { return { title: process.env.VUE_APP_TITLE, apiUrl: process.env.VUE_APP_API_URL }; } }; </script> ``` 在上述代码中,我们使用process.env对象访问在.env文件中定义的环境变量,并将它们绑定到Vue.js组件的数据属性中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值