Minesweeper: A playful intro to Vue | Hunor Borbély | Skillshare

Minesweeper: A playful intro to Vue

Hunor Borbély, Web developer

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
18 Lessons (59m)
    • 1. Introduction

    • 2. Creating and running a project

    • 3. Tooling

    • 4. Going through the initial project

    • 5. Breaking down the app into components

    • 6. The tiles

    • 7. The minefield

    • 8. Data

    • 9. Utility functions

    • 10. Resetting the game

    • 11. Surrounding bombs

    • 12. Computed properties

    • 13. Flagging a tile

    • 14. Revealing a tile

    • 15. Did we win already?

    • 16. Every second counts

    • 17. Review & Next steps

    • 18. Bonus: Share your game


About This Class

Do you want to learn Vue the fun way? In this class, you will learn the key concepts of Vue while building a Minesweeper game.

While building a fully functioning game we dive into some basic concepts in Vue like:

  • How to break down your application or game into smaller pieces, into components
  • How to structure your logic and how to connect these components with props and custom events
  • How to deal with change and make your game data-driven
  • How to add interaction and game logic
  • And how to publish the final result to the web to share it with your friends

This is an intro course, no prior Vue knowledge is required, but some HTML, CSS, and basic Javascript skills are necessary. You should also know how to navigate in your terminal.


1. Introduction: Hi there, I'm monarch. And in this course we are going to learn how to create a nicely per game while learning USGS. If you haven't used UG as before, don't worry, we are going to cover all the basics of huge AS by building this game. There's a lot to cover though. This course is going to be duns. We start from scratch by creating a new project and setting up the environment. And we finished by publishing or game on the web. Or you need to have is some prior HTML, CSS, and JavaScript knowledge. And you should be able to navigate than your terminal. And by the end of this course, UNL, how to create a simple game or website. Did you GS 2. Creating and running a project: In this course, we are going to build a mine sweeper game from scratch. And along the way, I'm going to explain the fundamentals of few JS. So let's jump straight into it and create a project. For that, we are going to use a command line tool that comes from the view JS team. This tool will help us to generate the initial thighs, the foundation of our project, and provide some scripts that are able to create a live preview of the project during development. And the final bundle that's become published on the internet. In order to get and use this tool, we need to set up note first if you don't already have it. If you don't already have note on your computer, go to node js.org and install the latest stable version marked as LTS y. So did that. You can check if it works by going to the terminal and typing node. Dash will be. If you see a version number, null is working. Once we have node, we can install the command line tool for view in the terminal type npm install dash g at view slash ci. This might take awhile, but once it's done, we can create our project. Navigate to a folder where you want to have your project. I usually have all my project and a project folder and run view create my sweeper. It asked if you want to go with the default settings or you want to change that. But in this course, we just go with the default. Once again, this takes awhile. It sets up a lot of things. Now let's check out how we can see our project. If you open the project, you can see it comes with a README file that says for development, we can compile and hatchery dot the project with npm run serve. This means that vibe you run the script. It will generate a live preview for our project. That's the refresh automatically when we change any of the thighs. So let's move to the terminal again. Make sure that we are in the folder where our project is and run NPM run serve. This gives us a URL where we can't see the Life Review. And voila, there it is. Mpm does serve gives you an error. Lag, no file or directory and something about package.json. That means you are in the wrong folder. Makes sure you navigate where your project is. This script were continuously run in the background until you stop it, adds it to the terminal or shut down your computer. You can always stop it with Control C or Command C, depending on your OS. When you stop the script, you get back to the terminal and then you can run the strip the same way again. During this war course, I'm going to run the script in the background to generate a live preview for us. So make sure you are also running this script to see what you are doing. If your browser gets out of sync, which can happen sometimes, then tried to refresh the browser and that should fix it. If Apple refreshing the browser says this side can be reached, death means the script is not running. So go to the terminal and navigate to the folder where your project is and run NPM run serve. 3. Tooling: As a code editor in this course, I'm going to use Visual Studio Code, which is nowadays the de facto standard for web development. Even on Macs winds coming from Microsoft. Forever development, I recommend using the prettier and ES lint extensions. Let me show what they do. I opened the project we generated previously. And before getting into the details, let me just change this a bit. Now this is technically the same code as before, but it's a bit harder to read. When we save the file doe, it jumps back to its previous nicer shape. This is about prettier does formats the code based on best practices. We have the formatting doesn't happen automatically. Go to Settings, lookup the format of the save option, and make sure that it's checked. You can also override some settings, like if you'd prefer single quotes instead of double codes. Or you don't want to have semicolons at the end of your lines. You can configure that. I'm prettier, we'll take care of it. Let me make another change. This is also valid JavaScript, but it gets highlighted in red. This is ES lens doing. If you have r over your mouse, it gives a brief message about the problem. And if you still need to know more about it, you can click this link and read more. White is better, is considered harmful. And how could you fix it? If you don't agree? Just like IT, pretty clear, ES lint can also be configured for this project because we are using view, I also recommend using the V2 extension that comes with US specific code formatting out to completion and error checking. 4. Going through the initial project: Let's check out the example project that we just created because we can learn a lot from it already. There's a main.js file. This is the starting point and it's also the only place where we are going to see new you. This bit defines that our root component is app, which is coming from an app.use file and not the dot js file, a dot view file. You finds refer to single Phi components. They are called single Phi components because they include both the HTML, JavaScript, and CSS part of a component. Once we open up that view, we can see these parts. The template is basically the output of the component piece of HTML that is going to be part of the website. It starts the usual way. It hasn't div, then it has an image. But then it gets interesting how the word is not an HTML tag. If the tag's name appears to be an upper CamelCase than it refers to a subcomponent. View is a component-based library and it has a tree structure of components. Let me show what that means. Let's imagine that this is a huge HTML file with hundreds of lines and it became hard to understand. On a closer look, we can notice that it causes of distinct parts. In view. We can move these parts into separate components. And then suddenly our original HTML that now we can call root component, becomes much shorter because it delegated all the details of the menu and the content, the subcomponents, and now it only refers to them. Of course, the result of this composition in the browser, we were the same long HTML, but during development, we can work with smaller, more manageable bits. Vector code. What we are looking at is the root component and hello word is our first subcomponent. How do we know that this file is the root? We know this because this was referred in main.js. Otherwise, these looks the same as any other component. The sample app is aware of. Simple one. It has one root component and one subcomponent. But the root component could have many more subcomponents. And those subcomponents could have their own subcomponents and so on. Now let's check out where the subcomponent hello word is coming from. For that, we need to go to the Script which can be interpreted as a companion for our template. Every Component Script has a default export object that can define the component's name, its behavior, data, and subcomponents. This object can be a bit intimidating at first, but it's just an object with key value pairs. Some of the values are represented by a string, sum by an object, some by a function, and some by an object that contain functions. Sometimes we also use shorthands indice object, like in the components option, don't get misguided here, this is a shorthand of a key-value pair. This means the same as this, where the key is referring to the handle word in the template. The value refers to the import that points to another that few file. If you go to that file, we see a similar structure. There's a template with a bit more tags. There's a script and the style. But before checking this, let's go back for a second and not something else here. When we have this unusual HTML tag, hello word, we also have an attribute here. This is a way of passing on a message or a variable to a subcomponent. If you think of components as functions, which they are not. But just for the analogy, if you imagine them as functions, then their template could be interpreted as their output. What you can see here is an input in the code. If you go back to helloworld component, we seen the script that has no subcomponents. Pete has prompts. This is where we define that this component requires a message property that should be a string. Then if you dig deeper in the template, we see a reference to this variable between double curly brackets. These double curly brackets are called Mustache template, and they basically open a window from HTML to JavaScript. Here we have a JavaScript variable, which we could also have any other JavaScript expression here. The last thing we should note before creating our own components is the style. By default, CSS is global. It doesn't matter which way you define a rule. It affects every HTML tag that it fits. This can lead to a huge global CSS file that is hard to maintain. Instead of that weed single Phi components, we can define scope style. If we add the scope attribute to the style tag down view, we'll make sure that this style is only affecting these component. This way we'd single Phi components were not only encapsulate layout, logic, and style, that we can also make sure that the style redefine does not interfere with other components. 5. Breaking down the app into components: Once we saw how the initial application looks like, let's try to break down our nicely per game into components. As we saw, there's always a root component. That is the frame of the wall app to Gambia client to build is not too big nor complex. So technically we could feed the OLAP into this one component. But if you tried to fit everything in one file, that's so becomes long and hard to understand. In general, even fight is longer than a 100 or a 150 lines. You might want to break it down into smaller bits. There are two ways to create new components. One is to avoid repetition. If the sampling appears multiple times or at multiple locations on our website, we create a new component for it. The duties, even if they're not entirely the same, but the changes could be defined by some simple parameters. In our case, we are creating a component for the tides. The another same, some high the bomb, some container number. But they're still roughly look the same and they all do something once you click them. The attr method of breaking down an app into components is to find a smaller meaningful bits. Maybe we found a piece that is not repeating both Haidt's own behaviour that is not relevant to any other part of the game or application. By breaking down app visa repetition is usually rather easy. Breaking down an app based on logic or style is less obvious and there are multiple good solutions. In our case, we're going to create a separate component for the timer. Because as we are going to see, it held its own unique logic. We could also create a component for the heterosexual dap to make our root components tie simpler. But in this course, we are not going to do that. We are only going to have a root component that takes care of the main layout and the logic. We'll have a time component that is responsible for how the ties look. And we're going to have a timer that causes seconds. Was looking at her, started. 6. The tiles: So let's start building our game. In this first step, we are creating the tag component that we show a number and add a few ties to the board. So that's really new file called dilutes you in the components folder. Then we had a template for it. The Stamp Act for now we only contain a div with the class tile. And as a content, I just add the number one here. This is already a valid component, either without the script or the style tag. But if you don't see it in the website yet because it's not used. So let's save this file and go back to the Atlas view file. And let's import it the same way as the handle words component is imported. Dan we added to the components. And now we can use it in the template. Now if we save this file that we can already see our basic type components in the browser. We want to make them look more like ties though. So let's go back to a time that view file and define the style for the tag class. We want our ties to look like squares. So let's set the width and the height of 50 pixels. Also lets add the border to make them more visible. And finally, I'm using flexbox to center the accountant. So now we have treat dies, but they all have the same. Let's make them unique. We are going to pass on an index number two down the same way as the head awards component receives a message. First, let's go to the TI components, add the script part and define them to have a prompt called index, which should be a number. Then we can use this index crab in our template between that work curly brackets. Now this component is able to show a number. We only have to pass it on from app. Let's go back to lab component and personal memoir for these ties. Now this looks all good and the numbers are showing up in the browser. As you can see, that this is actually not correct. If you go to the counseling, the browser, we will see why. It says expected number with value tree, got string with the value tree. Seems like the same thing, but it's actually different. We've passed on tree as a text. When passing on, perhaps there are still ways of doing it. We can pass down like a normal HTML attribute, like what we just did here. And then the way you we pass on it will behave like a string. Or we can prefix the attribute name with a colon. And then the value will be here like a JavaScript expression. Now we have a number here which will act as a number because we could also have a JavaScript expression here or reference to value. This is going to be important later on when we pass some variables instead of hardcoded values. We already saw a way of using JavaScript be specialists in our template that was with double curly brackets. In a way, we are doing the same thing here. Different syntax. They are not interchangeable DO double curly brackets are used in the content of an HTML tag. Prefixing of Cuba calendar works when you are using JavaScript as a value of an attribute. So basically the same thing, but different context. Now we've fixed the issue, but the air is still there in the puzzle of the browser. This is because previous messages under cancel don't disappear automatically. But if you refer to warpage, we see that it's not there anymore. Generally, a cube. The browser scans are open during development because you gives a lot of useful messages. But I wanted to fit this recording in a smaller screen, same closing it now, before moving on, let's clean up things that we won't need from the original code. We're not going to need the image tag in the app's template. So let's delete it along with the asset folder. Also less delete the hello word component without any reference to it from the template and the script tag. And let's get rid of the style tag as well, because we are going to create our own style. Hokey analogy piano claim. Look. In the next chapter, we are going to move from three times to the wall grid. 7. The minefield: In the previous lesson, we managed to create a component and pass on a prop to its instances. But our minds sleeper game is going to cause us to have more than tree ties. Instead of manually adding more and more ties, we are going to generate the ties of Eden Luke. In view, you can enrich the template with directives. One of them is the v4 directive. The v4 directive can repeat an HTML tag or a component. It looks like an HTML attribute. You write V dash four equal index in a 100. This will generate a 100 times for us. It also creates a new index variable that we can use in other attributes of these tags or beaten that tag. In order to make the loop work for technical reasons, we also need to provide a unique key attribute for each of the tile instances. As a value, we can simply pass on the new index variable because that is going to be unique. But remember to add the column prefix to the key attribute. Because otherwise the value of the key rehabilitated text index instead of a number which is represents. To have a visual representation of the index of the loop. Let's pass on our new variable to the index prop of the component. Now we see a bunch of ties having numbers from one to 100. But it doesn't exactly look like a grid. So let's add some layout. First, let's remove the other two ties and move this time with a loop inside of a new div. We'll have the plasma board. Then define the class of this board. We're going to use CSS grid to have the layout. We want also to the app to make sure our content is centered and that stretched out. And now we have a layout. Before moving on, I like to point out an important bit here why we see the index values in our data model now, and along the course will be 1-dimensional. This means that our ties don't have a separate row index and column index, but they have one index. And only CSS makes it look like two-dimensional. This is going to be a bit tricky when we have to calculate the bomb surrounding the tile. But we worry about that when we get there. 8. Data: We managed to generate the amount of ties when aid. As a next step, let's make a data-driven. Let's switch from showing the index of the tie to show whether the tag contains a bomb or not. For these two different data offshore in the Component Script, the data option is practical and object with a list of properties that we can refer to in the template. But for technical reasons, instead of defining its simply as an object, it has to be defined as a function that returns an object. That's why if you defined as an object that I'll save ES lint will automatically replace it with a function. Here we are going to define the type property, ties property verb into the metadata of our app. Therefore, it Cuban array representing the ties. For simplicity, ledgers that a bunch of zeros and ones indicating if the tie should contain a bump or not. The properties in the data option can be used in the template. So it can be also used in RV for loop. We can replace a number 100 with the Thais property and see what happens. We see a representation of our ties array in the browser, but to behavior of this loop is slightly different. Now, previously it was generating a range from one to 100. Therefore calling its variable index was appropriate. But now it's representing the item itself, which can be either 0 or one, which leads us to a problem, the loops variable, essentially unique anymore. If you turned your browser's console, it says we are using the keys and the Q1 multiple times. So let's clean up things a bit. First, let's rename the index to Tyler, built in the loop, and then the tie component. Secondly, we still need to use the unique key for our ties. Luckily, the v4 directive can also provide an index. We just need a slightly different syntax for it. So now we can pass on this index to the key. Can we pass on the time variable as the prop for the component? Everything is set. 9. Utility functions: Let's create a utility fire that generates our ties. This is going to be a separate file outside of our components. Why is it going to be separate? Because we can separate it. It's a good practice to keep profile's relatively short. Components already have their own template, script and style. So if you can separate a piece of the logic that makes sense on its own, then that's usually a good thing. And not everybody can be moved outside though, suddenly to interact with the component itself. But if a function has no side effects or dependency on its surrounding, then we can move it to a utility file. So let's create a file called UTRs that JS. And let's explore the function called generate ties from it. We also going to need the constant defining how many bonds do we have on the field. Let's call this total number of bombs and set it to 14. Inside the generate ties function, we first generate an empty array that has a length of 100 items. To run a loop that keeps on going till it planted as many bumps in the array as the total number of bombs constant indicates. You need cycle, we generate a random index. And then the selector does not already have a bomb. Once the array is ready and it'll return it. And now we're going to import it in the app. In App that view, we can import this function in the script part. Then we can assign it to the Thais property in the data option. Now every time we refresh the page, we see another layout of bombs. But how could we get a new layout without refreshing the browser? 10. Resetting the game: It's time to add some interactivity to our game. As a first step, we create the reset button. The Reset button is the smiley face located into header. So first we need to create the header. Let's go to add that view and add the header above the board. This will contain the number of remaining bombs, which for now is a hard-coded number 14. The reset button itself, we the smiley, and a timer. The timer will be later a separate component, but for now it's just a hard-coded number 0. After adding these bits, let's fix the style by adding a new div that contain both the header and the Board. Then let's add some style. Let's align the items in the header with CSS flexbox at some margin, and increase the font size to make it look more like a header. Unfortunately, the button doesn't have funnel the Increase Font Size automatically. So let's change that as well. Now we get to the script part. We need to change the value of ties in the data option. For this, we can create a method for our view component. The methods option is a collection of functions that can change the data and can be called from our template. So let's create a methods option in our default export. Its value is going to be an object. And let's add the function called reset to it. Then we write this that ties equal generate ties. Before linking this method to the button, we have to talk about the disk keyword. The least keyword is one of the most complicated things in JavaScript. And I'm not even trying to explain what it actually is. To give you a simplified explanation. You can think of them in the context of EU development as the component itself. In the default export of the script, we define component data, props, methods. And as later we are going to see computer properties. If you want to access or change any of these inside the script, we need the this keyword. The this keyword only works in the context of default export though. Within JavaScript component data, perhaps methods are computed. Properties can only be accessed within the default export. The January ties function does not need any of that. That's why we didn't move it outside of the component, is just a function that returns something that will be assigned to a data. But the assignment itself where we need the DES key word is within the default export. Another thing you might notice is when we use data preps are methods in the template that we do not use the this keyword. We can refer to them directly. Why is that? Well, not everything is consistent. View is a library on top of other technologies and it has to follow their rules. So as a rule of thumb, if you refer to data, perhaps more computer properties in the script, then we need to use the this keyword. If we refer to the same things within the template that we don't. Now that said all that, let's link this method to the button in the template. We can define an event handler like an attribute starting with the add key. There are several events we can choose from, but we just use the most simple one and the click event in our template. After the bottom, we can write at clique equal reset. That's it. Now every time you click the smiley face, it generates a new minefield. 11. Surrounding bombs: That's updates our data model and include the number of surrounding bombs for each trial. For this, we need to update our Generate ties function and return an object for each died that's been encapsulated, bolded Bambi indicator, and the number of surrounding bombs. This chapter we've onto any of you specific things. We are going to adjust the game logic and I am not going to lie. It will involve some mathematics. The difficulty is finding the neighboring ties. Van we map our bombs array for each died, we only have the value indicating if the TI contains a bomb or not. The index of the tile, the original array. The problem is that despite appearances, are data model is still a one-dimensional array. So the index is a number between 0 and the number of items in the array minus one. That is 24 here. But in our game we are developing that's 99. How do we know, for instance, that the neighbors of ties six are the tower numbers 01257101112. First, to figure out the coordinates for dissects it create a function that gives back and will be true and which column the tide is located. You can get the row by dividing the index six with the number of items in the row, which here is five. In our real application, it's ten. That gives us 1.2, but the row number has to be a whole number. So we use Math.floor. Calculating the column is similar, but instead of dividing by the number of items in their own views, the modulo operator that gives the remainder of a division. In this case one. We ended up with coordinate 11, which can be a bit misleading because times six is in the second row and in the second column bits we are using zero-based indexes here. So remember the first story is actually rho 0. For this function, we can calculate the row and the column for each of our tile indexes. Now we can easily figure out the coordinates of the surrounding tides, but we still need to figure out their indexes. We create another function that takes a row and the column and gives back an index. This is an easier calculation. We simply multiply the row number with the number of items in a row and we add the column number, fit this function, we can finally calculate the surrounding bombs for each tile. V define a variable that's your content, the number of surrounding bombs. Then go through each neighbor and check if it contains a bomb. We first got the top left index ten. Tracking of the original array had a bump indicator at that position. Then we've got the top index and checking the original array had a bump adaptive tile, and so on. At the end of the map view, return the object that contains the Bambi indicator and the number of surrounding. For each diet. We ended up with a data model we originally wanted. But this calculation has some edge cases. One, if we want to calculate the neighbors of Thai 14, the neighbors should be DIE 89131819. But this calculation at some extra ties to the mics. And I've tried to calculate the top-right style, we will get the coordinate row one, column five, which is outside of our grid. But their logic does not handle that. It's simply looks up its index that feel be onetime five plus five, ending up at Titan, which is not a neighbor of tile 14. So we have to handle us some edge cases here. The easiest way to solve this is to return undefined Bambi or looking up an index for a coordinate that is outside of our grid. So in are getting index function. If a column or row is below 0 or it's higher than it should be, then we should simply return. Okay, these mount fixed it. In a note. There was a lot to digest here, but it wasn't necessary in order to make our mind sleeper game work. I promised this was the hardest bit. Now let's add the same code to our app, except our field is not a 5.2.5 grid. Soviet need slightly different numbers. So let's go to the utility file and let's add a new function for getting the index. These facts show the Oberlin are used in another scenario as well. So it should be exported. Here the difference is that the width and height of our grid is ten. So we want to make sure that the coordinates do not go beyond nine, which is ten minus one, because of the 0-based index. And because we have ten items in a row, you multiply the number of rows. And then we also explored the gut coordinates function and WMAP or existing palms array function. I'm writing things in a bit shorter way instead of calculating the index on the neighboring tile and then check if the original array had a bomb and that index. I just do these two steps in one line. So there we go. Now or generate ties function is providing our metadata in a new format. But that obviously messes up things because our time component is still expecting the number instead of an object. So let's fix that. 12. Computed properties: And that's cool. Back to tie that view and fix up a few things. First of all, our prompt is an object now. But what do we show now that if you have two separate properties, if the tag contains a bomb, it should show a bump. Otherwise, if the titus surrounded by bombs, we should show how many bonds are around. This is a good scenario for a computer property. Computer properties look like methods, but act like prompts. Each computer properties of function that coconut so value you should have based on a prop or data. And then we can use this value as if it was a prop. So let's go to our tire component and define a computed property called content. It's a tag contains a bomb, they should return a bumpy Muji. And if it contains an indicator of surrounding bombs, we should show how many bombs and around. Remember to use the this keyword when referring to these variables. We can stop here though, computer properties should always return something. In this case, if there's no bump nor surrounding bombs, we should return an empty string. Now this computer property content can be referred in our template. And now our grid looks much better. Now that we have a bit more text and bolting the header and then the ties, that's quickly change the font family. We want to change this everywhere. So we go to the app.js file and change the font family there to make things even nicer. And other places where we can use a computer property is to cut are the numbering on the board. So let's create a computer property called Color and return a color for each possible value. If there is one surrounding bulb, then it should be blue. If two than green. If she'd done read. Four should be purple. Five is brown. 60 store cars, seven is black, and 48 and any other case grey. Now this computer property should be used to affect the CSS. But unlike in the template, we cannot use computer properties or in fact editor variable coming from the script in CSS. What we can do instead that online style tag to our div, very buying our CSS color property to our computer property. Now it looks almost like a game. We just have to make it interactive. 13. Flagging a tile: In this part, we had the option to flag the ties. We have to change a few things to make flagging work. First of all, our data model needs to be able to store if a tireless, flagged or not. For this, we should go to our Generate ties function and extend the generated tidal object with a new flat property that we'll be false by default. Dan, we should smart an apartheid component to handle this flag. If a tiniest flagged than it should show this flag above everything else signed a function that provides the content property, we should add an if condition to show a flag. If the tile is flagged. Dan, we should define a method that flags or unpleasant tile. Here we said the flag property of the tire to the opposite value. Now we should link this to an event handler the same way as we did with the recent button. We still listen to the click event. But if you add the modifier to listen to the right-click instead of the left cake. By adding that right. Now if you click a tile, it should work, but it has an unwanted side effects. The context meant it comes up. To avoid this, we could use prevent default in the method. This pattern is so common that view created a shorthand for it. We can add another modifier that prevent, to avoid showing the context Linux. Now that we can flag things, we can also count how many bombs the player should still fly to finish the game. We can get this in a new carpet, the property in public view file. That calculates how many flag types do we have in total, then extracts the result from the total number of bombs. The total number of bombs we defined already in our utility file. And my editor was smart enough to automatically imported. But if yours did not, please make sure that you exported it from the utility file. And it is imported at the top of your app script. Now this, we have the bugs remaining computer property. We combine the two, its rightful place, it double curly brackets. Now, if you start flagging ties to number of remaining bombs, starts to decrease. Lets move on. Which revealing ties. 14. Revealing a tile: Let's move on without revealing the ties. For now, all the ties were revealed by default to make development easier, but that's going to change. Revealing the ties will be similar to flagging the ties, but it'll be habits, differences. We start the same way. We extend our ties objects in generate ties function of it. A new property revealed. Dance called to the Thai component. Let's not hide the content of the ties yet, but to indicate if they are revealed or not, let's add a background color that depends on the revealed flag. It's VRBO, new computer property called background-color. That's been returned a light shade of grey if the TI has been revealed. And a white atom wise. We can add this to our style binding next to color to set the background color property of CSS. You might notice that the background-color property in CSS is usually written with a dash in between the words. And now we are using lower camelcase. But remember here we are binding a JavaScript object to the style attribute. And in JavaScript, we don't use dash in variable names. So that's why I heard different syntax. But don't worry, it will work. Now let's move on to event handling. Let's start the other way around and add the event handler first. We are going to react to the click event. Again, no modifiers needed, and we link it to reveal method. W defined a reveal method the same way as we did with flagging. But here's, there's going to be a difference. We could change a revealed flag here, but only for the style. In mine sweeper. If you click a tile, the tides no bombs, and has no surrounding bumps either, then not only the clicked I should be revealed, but its neighbors as well. And Dan, the neighbors of those neighbors, if they also fit the criteria and so on. Entire component, we can do that. Tack component instances have simply no access to their neighbors. And who has access to the advertise the App component. The general structure of components have you apps is start to bottom. Usually top-level components contained the data and the main logic of the app, and they pass on the necessary information to their children, were rather visual, tanned, smart. But what if they need to tell the App component that something happened? In that case, they can emit a Custom Event. Customer events have a name and their parents can react to these events just like with any other event handling we saw at the Reset button or at flagging tie. So we are the reveal method in the Thai component. And right, does that dollar sign emitter reveal? Damming the App component? We have an event handler for our new customer event and link it to a method we're about to write. Here's another difference comparing to the previous event handlers. Earlier, V only wrote the method's name at the event handler. Here we call the method and pass on the index of the tile has a parameter. We are going to need that to know which tie should they up reveal. As you're going to see, both syntaxes are working. Binding a method name only or binding method call its parameters. Now let's write this method. It starts with diabetes. We need to reveal the tile for dad. We first look up the selected tile, then check if it's not already revealed. And if it's not ten, let's reveal it. At this phase, if you start clicking ties, their programs should turn gray, but only the click ties of background, now the surrounding ones. Let's move on. If the tide does not contain a bomb and the number of surrounding Bob's is 0, then we shouldn't reveal the surrounding tags. This is going to be a recursive function. Working in a similar fashion has are generated ties function does. First VLookup the coordinate of the revealing type. Think out the index of the neighboring ties and trivial dennis, Well, it's easy to run into an infinite loop or other problems here though, we tried to reveal a neighbor that does not exist. In case the index is undefined, law just return straight away. Now that should work. If you click a bomb or number on the map on it that I should be revealed. But 20 click and empty area, the wall area should be shown. You know what's next? We're going to hide the content of the ties before they are revealed. For this, we got to the content property in the tile and return an empty string if the tile is nor flagged, nor revealed. Now our game looks almost ready. 15. Did we win already?: Okay, we're after the finishing touches, the game is almost fully functioning, that we still missiles. That modifies the player if the game was won or lost. We're going to derive the game status with computed properties. First, let's start with the game fared computer property in the update view file. If you review at anytime that contains a bomb. Tammy last again. We can check this by going to the ties with the find. And if it returns editing for this criteria, then we failed. Then let's create another computer property that tells us if we want the game, we win the game. If we revealed all the ties, do not contain a bomb. First, we need to count how many times did we reveal. Then add the total number of bulbs. And that should equal to the total number of ties, which is 100. In our case. If this condition is true, then we've loved again. Now let us derive a game studies out of these two computed properties. This will tell us which smile it is show in the header. You can create computer properties on top of other computer properties. Just remember that you need to use the keyword when referring to them. So let's create a computer property called Game status. Then return a set phase. If the game failed. A smile with sunglasses into game is one. And the regular smiley in any other case. Now we combine this computer property to the header. If you fail again, then we're going to see the sad face into header. But if you win now you can feel like a rock star. 16. Every second counts: We arrived to the final bit, the timer. We said that this is going to be a separate component. So let's create a new file timer that view. Its template is going to be very simple, just a div that shows how many seconds have passed. We decided to make the timer a separate component because it has its own data and own logic. The seconds variable, for instance, would not be needed in the context of the wall app. So that's why we have it here in the timer components on Data option. By default, it will be 0. That's clear, but how should it change? The timer should start counting when the game has started, and it should stop once we failed or won the game. In other terms, the timer should count if the game is in progress. Let's assume that there's a computer property that tells us if the game is in progress and the timer component has access to it, we should start a timer if this property is true and stop it. When it turns false. In short, we have to watch out for the changes of this prop. This is what watchers do. They watched data, computed property or a prop. And once they change, they trigger a function. The function's name should be the same as the name of the washed variable. In this example, age is an incoming prop for this component. And the function watching out for his changes is also called age. What's your functions also received the new value of the change variable in an attribute. Let's put this to use. First, let's use this new timer component in our app. The last field, a computed property that tells us if the game is in progress or not. If the game is already one or failed, then it should return false. Otherwise, if there are ties revealed, then true, the game is in progress. And if that condition is not true either, then return false. The game haven't even started. The last pass on this computer property to timer. On the other side in the timer component. And we register that this component requires a prop called Gaming progress. And the right. Watch her for it. If it's valued, turned to true. Then first let's reset the timer. Then create an interval that increases the timer every second. But this is only one side of it. We also have to clear this interval once the game stops. For this. First, we saved the intervals ID when we created. This is going to be in the data as well. Everything that's changing and we need to store it for later, is defined in data. Then backing the watcher, if the where you did not turn to true. But to force the, let's clear this interval. Okay, we have a nice week per game that has all the major functions. Let's review what we did during this course and what we're still missing. 17. Review & Next steps: Let's review what we learned. We learned how to create a project which you use CLI. Dan, we learned that use a component-based library where each component has its own template, logic and style. We learned how to add the child to a component and how to pass on a path to it. We learned about data storing variables in R components. We learned a directive that generates multiple components based on an array. We learn about methods that can manipulate their data and how to bind these methods to EventHandlers. We learned how the children can trigger customer events to their parents to notify them about changes. We learned about computer properties that can derive new information out of existing values. And finally, we learned about watchers who can react to changes of variables. Oh, and by the way, we created the masonry per game. It has its flaws. And of course the design could be improved. But I'll let you be creative with that. Feel free to add your own style. Here's a few challenges for you. There. We left a few bugs in the game that you could try to fix. In the current game, you can flag a tile even if it has been already revealed. And you can reveal a tile that has already been flagged. This should be an easy fix. The game also doesn't stop. Once you failed. You can keep a revealing or flagging ties. That's a bit harder to fix. The fair scenario could be improved in other ways as well. Maybe highlight the clip bomb in red. Or if they were anesthetized that being wrongly flagged, they should be highlighted in red as well. And finally, the timer does not reset. If you reset the wallboard, that also shouldn't be too hard to fix. You could also experiment with different grid sizes or maybe even add a selector for difficulty. You can find a more advanced version of this game down in the links. So good luck on your journey on learning view JS and making the best apps out there. I can't wait to see what you did there. Oh, and don't forget to check out the bonus video that explains how to put your game on the web and share it with your friends. 18. Bonus: Share your game: I'm sure you improve their game in many ways after the course. Nice time to brag about it and share it with your friends. Here I'm showing you a free and easy way to put it on the web so you can share it. First of all, we need to create a version of our game that we can run in the browser. So far, we were generating a live preview of the game by running MPM around serving the background. But once you stopped at script, the game is gone. If you open the Read Me, you see another command that complies and minifies your fight for production. Before running this script, First, we need a short configuration that says the public paths through relative. Done. We can run the script. This regenerate phi's that contain everything we built so far. If you open them, they will probably look like gibberish because they are not meant for humans. These fires can run now though in a browser simply by double-clicking on index.html, readout any script in the background. Okay, how do we put this on the web? I suggest to use GitHub pages because it's for free. First, you need the GitHub account. If you don't already have one. Make sure you have a good username, because your username will be part of the URL where your game will be, then you should create a repository that will contain our game. Here naming counts again, it should be either your username that it had that IO, and then your game, we'll be available under the same URL. Or you can give it an arbitrary name, like mine sweeper. And then the game will be available. And there your username, that GitHub dot io slash mine sweeper. I suggest the second option, because to your primary URL, you might want to applaud your portfolio or main website later on. Then upload your files. If you're familiar with Git, you can upload your project with good. But if not, you can also manually upload your files, lead to add fire button. There you have to give a commit message, click the big green button, and it's uploaded. It should look something like this. Then go to your repository settings, scroll down and made sure that GitHub Pages is pointing to the location where you're building is. Here. Sometimes you have to wait for a minute, but then you can just open the link and play.