If you are new to Vue and want to refresh your basics, this fun exercise will help you build an interesting game.

如果您是Vue的新手,并且想刷新基础知识,那么这个有趣的练习将帮助您构建有趣的游戏。

In this post, I will take your through the step by step process of building a memory card game in VueJS.

在本文中,我将逐步指导您使用VueJS构建存储卡游戏。

Here is what you can expect to learn by the end of this article:

这是您期望在本文结尾处学习的内容:

  • How to use the v-for directive to loop through Array of Objects.

    如何使用v-for指令遍历对象数组。

  • Dynamic class & style binding using the v-bind directive

    使用v-bind指令的动态类和样式绑定

  • How to add Methods and Computed Properties.

    如何添加方法计算属性。

  • How to add reactive properties to an object using Vue.set如何使用Vue.set向对象添加React特性
  • How to use the setTimeout method to delay JavaScript execution.

    如何使用setTimeout方法延迟JavaScript执行。

  • Shallow cloning vs Deep Cloning of Javascript objects.

    浅克隆与深克隆 Javascript对象。

  • How to use the Lodash utility library.

    如何使用Lodash实用程序库。

Let's dive into the steps.

让我们深入到步骤。

准备-包括图书馆 (Getting Ready - Including Libraries)

The first step is simple: just import the libraries from the CDN into our basic HTML5 markup so that we can get started with our tiny little project.

第一步很简单:只需将CDN中的库导入到我们的基本HTML5标记中,就可以开始我们的小项目了。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Memory Card Game</title><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"><!-- development version, includes helpful console warnings --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body></body>
</html>

允许用户看到卡片网格 (Allow user to see the card grid)

Next up, let's define the necessary HTML markup, CSS styling, and a basic Vue instance so that the user can see the card grid.

接下来,让我们定义必要HTML标记,CSS样式和基本的Vue实例,以便用户可以看到卡片网格。

Vue实例 (Vue Instance)

Let's create a new Vue instance and define the single data property named cards which holds the list of cards.

让我们创建一个新的Vue实例,并定义名为cards的单个数据属性,该属性保存卡片列表。

let app = new Vue({el: '#app',data:{cards: [{name: 'Apple',img: 'apple.gif',},{name: 'Banana',img: 'banana.gif',},{name: 'Orange',img: 'orange.jpg',},{name: 'Pineapple',img: 'pineapple.png',},{name: 'Strawberry',img: 'strawberry.png',},{name: 'watermelon',img: 'watermelon.jpg',},],},
});

Each object in the array contains two properties: the name of the image (which will be used to perform matching) and the image of the card.

数组中的每个对象都包含两个属性:图像的名称(将用于执行匹配)和卡的图像。

HTML标记 (HTML MarkUp)

Since we now have the data ready in our Vue instance, we can use the v-for directive in VueJS to loop through it.

由于我们现在已经在Vue实例中准备好数据,因此可以在VueJS中使用v-for指令遍历它。

<div id="app"><div class="row"><div class="col-md-6 col-lg-6 col-xl-5 mx-auto"><div class="row justify-content-md-center"><div v-for="card in cards" class="col-auto mb-3 flip-container"><div class="memorycard"><div class="front border rounded shadow"><img width="100" height="150" src="/assets/images/memorycard/pattern3.jpeg"></div><div class="back rounded border"><img width="100" height="150" :src="'/assets/images/memorycard/'+card.img"></div></div></div></div></div></div></div>

We have used some basic Bootstrap markup and the v-for directive of VueJS to loop through the cards and show them in the grid format.

我们使用了一些基本的Bootstrap标记和VueJS的v-for指令来遍历卡并以网格格式显示它们。

Each memory-card is made up of two parts:

每个存储卡均由两部分组成:

  • front: This contains a common pattern image for all the cards (default card view)正面:包含所有卡的通用图案图像(默认卡视图)
  • back: This contains the actual card image (needs to be hidden by default)背面:包含实际的卡片图片(默认情况下需要隐藏)

Let's add in some basic CSS so that we only show the front part of the card (common design pattern):

让我们添加一些基本CSS,以便仅显示卡的前部(通用设计模式):

.flip-container {-webkit-perspective: 1000;-moz-perspective: 1000;-o-perspective: 1000;perspective: 1000;min-height: 120px;cursor: pointer;}.front,.back {-webkit-backface-visibility: hidden;-moz-backface-visibility: hidden;-o-backface-visibility: hidden;backface-visibility: hidden;-webkit-transition: 0.6s;-webkit-transform-style: preserve-3d;-moz-transition: 0.6s;-moz-transform-style: preserve-3d;-o-transition: 0.6s;-o-transform-style: preserve-3d;-ms-transition: 0.6s;-ms-transform-style: preserve-3d;transition: 0.6s;transform-style: preserve-3d;top: 0;left: 0;width: 100%;}.back {-webkit-transform: rotateY(-180deg);-moz-transform: rotateY(-180deg);-o-transform: rotateY(-180deg);-ms-transform: rotateY(-180deg);transform: rotateY(-180deg);position: absolute;}

Refresh the page and you should see six cards stacked up in the grid format facing the front. The actual card image is hidden on the back.

刷新页面,您应该看到六张卡以面对前的网格格式堆叠。 实际的卡图像隐藏在背面。

让我们翻转卡片 (Let's flip the cards)

Next up, let's bind an event to our cards so that when it's clicked it should flip and show the image behind it.

接下来,让我们将事件绑定到卡片上,以便在单击事件时将其翻转并在其后面显示图像。

Let's modify our original cards array to add another property to each card. This will determine if the card is currently flipped.

让我们修改原始的纸牌数组,为每个纸牌添加另一个属性。 这将确定卡当前是否已翻转。

Add the following CSS. When the flipped class is added to the class it will show the card image. It also gives us a nice turn effect.

添加以下CSS。 将翻转的班级添加到班级时,它将显示卡片图像。 这也给我们带来了不错的转向效果。

.flip-container.flipped .back {-webkit-transform: rotateY(0deg);-moz-transform: rotateY(0deg);-o-transform: rotateY(0deg);-ms-transform: rotateY(0deg);transform: rotateY(0deg);}.flip-container.flipped .front {-webkit-transform: rotateY(180deg);-moz-transform: rotateY(180deg);-o-transform: rotateY(180deg);-ms-transform: rotateY(180deg);transform: rotateY(180deg);}

Let's use the Vue created lifecycle event to add the new property and add a flipCard method to flip the card

让我们使用Vue 创建的生命周期事件添加新属性,并添加flipCard方法翻转卡片

created(){this.cards.forEach((card) => {card.isFlipped = false;});},methods:{flipCard(card){card.isFlipped = true;}}

First we'll bind the click event to cards to invoke the flipCard method. Then we'll also use the v-bind directive to bind the flipped class to the card.

首先,我们将click事件绑定到卡上以调用flipCard方法。 然后,我们还将使用v-bind指令将翻转的类绑定到卡上。

...
<div v-for="card in cards" class="col-auto mb-3 flip-container" :class="{ 'flipped': card.isFlipped }" @click="flipCard(card)">...

Sounds about right – let's see if the cards flip on a click.

听起来不错–让我们看看卡是否在点击时翻转。

It didn't work. Why not?

没用 为什么不?

Let's go back to our created lifecycle method, where we looped through the list of cards and added a new property named isFlipped. It looks alright – but Vue didn't like it.

让我们回到创建的生命周期方法,在其中循环浏览卡片列表并添加了一个名为isFlipped的新属性。 看起来不错–但是Vue不喜欢它。

For the new object properties to be reactive, you have to add them to the object using the Vue.set method.

为了使新的对象属性具有React性,必须使用Vue.set方法将它们添加到对象中。

created(){this.cards.forEach((card) => {Vue.set(card,'isFlipped',false)});},

Now the cards should flip on click:

现在,卡应该在点击时翻转:

Alrighty, great job. Let's move on to the next one.

好,辛苦了 让我们继续下一个。

加倍并洗牌 (Double it and shuffle it)

Yep, that's right! To make a memory game out of these cards we need to have exactly one pair of each card. We also we need to shuffle the order of the cards every time the game is loaded.

是的,没错! 为了用这些卡制作记忆游戏,我们需要每张卡上恰好一对。 每次加载游戏时,我们还需要洗牌顺序。

Let's define a new property in our Vue instance named memoryCards. Here we will store the cards that will be played (that is, double the amount of actual cards and also shuffled).

让我们在Vue实例中定义一个名为memoryCards的新属性。 在这里,我们将存储将要玩的纸牌(即,将实际纸牌数量翻倍,并随机播放)。

...
memoryCards: [],
...

加倍 (Doubling)

To create two copies of all the cards, let's concatenate the cards array to create and assign it to the memoryCards property.

要创建所有卡的两个副本,让我们串联卡数组以创建并将其分配给memoryCards属性。

Change the v-for directive in the HTML markup to loop over the property memoryCards instead of cards:

更改HTML标记中的v-for指令以遍历属性memoryCards而不是card:

<div v-for="card in memoryCards" class="col-auto mb-3 flip-container" :class="{ 'flipped': card.isFlipped }" @click="flipCard(card)">

Next, modify the lifecycle method created to assign the concatenated array into memoryCards:

接下来,修改创建的生命周期方法以将串联的数组分配给memoryCards:

created(){this.cards.forEach((card) => {Vue.set(card,'isFlipped',false)});var cards1 = this.cards;var cards2 = this.cards;this.memoryCards = this.memoryCards.concat(cards1, cards2);},

Looks simple, right?

看起来很简单,对吧?

But this isn't gonna work correctly. There are two problems with this code:

但这无法正常工作。 此代码有两个问题:

  1. Direct assignment of this.cards into cards1 is not going to make another copy of cards object. cards1 is still referencing the original object.直接将this.cards分配到cards1不会使cards对象成为另一个副本。 cards1仍在引用原始对象。
  2. Since cards1 and cards2 are still referencing same object this means that we have concatenated two arrays which point to same array of objects.由于cards1和cards2仍​​在引用同一对象,这意味着我们已将指向同一对象数组的两个数组连接在一起。

Changing any property of the object in the memoryCards object will change the original array as well as its own pair in the array.

更改memoryCards对象中对象的任何属性将更改原始数组以及该数组中它自己的对。

Well, that's a problem.

好吧,那是个问题。

If you look around for solutions to properly copy an array or object so that it doesn't refer to the original array, you might come across solutions that do a shallow-copy of the array.

如果四处寻找可以正确复制数组或对象的解决方案,以使其不引用原始数组,则可能会遇到对数组进行浅表复制的解决方案。

什么是浅表副本? (What's a shallow copy?)

A shallow copy refers to the fact that only one level is copied. That will work fine for an array or object containing only primitive values.

浅表副本是指仅复制一个级别的事实。 对于仅包含原始值的数组或对象,这将很好地工作。

One way to do shallow-copy is via the spread operator, which in our case will be something like the below code:

进行浅表复制的一种方法是通过散布运算符,在我们的情况下,它将类似于以下代码:

...var cards1 = [...this.cards];var cards2 = [...this.cards];this.memoryCards = this.memoryCards.concat(cards1, cards2);
...

But this is not the solution for us, because in our case we have an array of objects and not of any primitive values. Thus our problem can be solved if we do a deep copy of our array.

但这不是我们的解决方案,因为在我们的情况下,我们有一个对象数组,没有任何原始值。 因此,如果我们对数组进行深层复制,则可以解决我们的问题。

什么是深层副本? (What's a deep copy?)

For objects and arrays containing other objects or arrays, copying these objects requires a deep copy. Otherwise, changes made to the nested references will change the data nested in the original object or array.

对于包含其他对象或数组的对象和数组,复制这些对象需要深度复制。 否则,对嵌套引用的更改将更改嵌套在原始对象或数组中的数据。

There are multiple ways of doing a deep copy, but we'll go with the simplest and most common way of using the Lodash library.

进行深层复制有多种方法,但是我们将使用使用Lodash库的最简单,最常见的方法。

Now, whats the Lodash library?

现在,什么 Lodash库?

Lodash makes JavaScript easier by taking the hassle out of working with arrays, numbers, objects, strings, etc.

Lodash消除了处理数组,数字,对象,字符串等的麻烦,从而使JavaScript变得更容易。

For our case Lodash has a method to perform deepCopy which makes it ridiculously simple.

对于我们的情况,Lodash有一种执行deepCopy的方法,这使其非常简单。

First include Lodash in your page by either downloading or referencing it through the CDN.

首先,通过CDN下载或引用Lodash将Lodash包含在页面中。

<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>

Next, you can use Lodash's cloneDeep method to perform the deep copy of our cards array.

接下来,您可以使用Lodash的cloneDeep方法执行卡片阵列的深层复制。

var cards1 = _.cloneDeep(this.cards);var cards2 = _.cloneDeep(this.cards);this.memoryCards = this.memoryCards.concat(cards1, cards2);

改组 (Shuffling)

Now we want to shuffle the concatenated array. Lodash has a method to shuffle as well. Let's use the method and also simplify the code to concatenate and shuffle in a single line.

现在,我们想改组连接的数组。 Lodash也有洗牌的方法。 让我们使用该方法,并简化代码以在一行中进行串联和混洗。

created(){this.cards.forEach((card) => {Vue.set(card,'isFlipped',false)});this.memoryCards = _.shuffle(this.memoryCards.concat(_.cloneDeep(this.cards), _.cloneDeep(this.cards)));},

Cards are now shuffling and flipping as expected.

卡现在像预期的那样洗牌和翻转。

On to the next thing!

接下来的事情!

配套卡 (Matching Cards)

The next step is to match the flipped cards. A user is allowed to flip a maximum of two cards at a time. If they are same, its a match! If they are not, then we flip them back.

下一步是匹配翻转的卡。 允许用户一次最多翻转两张卡。 如果它们相同,那就匹配了! 如果不是,那么我们将它们翻转回去。

Let's tackle this.

让我们解决这个问题。

We'll add a new property to each card to track if the card has already been matched. Modify the created method to include this code:

我们将为每个卡添加一个新属性,以跟踪该卡是否已匹配。 修改创建的方法以包括以下代码:

this.cards.forEach((card) => {Vue.set(card,'isFlipped',false);Vue.set(card,'isMatched',false);
});

Create a new data property to store the flipped cards:

创建一个新的数据属性来存储翻转的卡:

flippedCards: [],

Next up, we modify the flipCard method to perform matching:

接下来,我们修改flipCard方法以执行匹配:

flipCard(card){card.isFlipped = true;if(this.flippedCards.length < 2)this.flippedCards.push(card);if(this.flippedCards.length === 2)    this._match(card);
},_match(card){if(this.flippedCards[0].name === this.flippedCards[1].name)this.flippedCards.forEach(card => card.isMatched = true);elsethis.flippedCards.forEach(card => card.isFlipped = false);this.flippedCards = [];
},

The logic here is simple: we keep adding cards to the flippedCards array until there are two cards.

这里的逻辑很简单:我们不断将卡片添加到flippedCards数组中,直到有两张卡片为止。

Once there are two cards, we perform matching.

一旦有两张卡,我们执行匹配。

  • If the name of both the cards is the same, we mark the cards as matched by setting the isMatched property to true.如果两个卡的名称相同,则通过将isMatched属性设置为true来将卡标记为匹配。
  • Else, we set the isFlipped property back to false.否则,我们将isFlipped属性设置回false。

We clear out the flippedCards array after this.

在此之后,我们清除了flippedCards数组。

Add a new CSS property to fade out the cards that match:

添加一个新CSS属性以淡出匹配的卡片:

.matched{opacity: 0.3;
}

Add a class binding to the container to add matched cards if the property is set to true:

如果属性设置为true,则向容器添加类绑定以添加匹配的卡:

:class="{ 'flipped': card.isFlipped, 'matched' : card.isMatched }"

Here the logic works fine, but everything happens too fast for the player to understand whats going on. If the cards don't match they are flipped back even before the user can see the revealed card.

此处的逻辑工作正常,但是一切发生得太快,以至于玩家无法理解发生了什么。 如果卡片不匹配,它们甚至会在用户看到显示的卡片之前向后翻转。

Let's use the setTimeout method of JavaScript to add a deliberate delay of few microseconds.

让我们使用JavaScript的setTimeout方法来添加几微秒的故意延迟。

_match(card){if(this.flippedCards[0].name === this.flippedCards[1].name){setTimeout(() => {this.flippedCards.forEach(card => card.isMatched = true);this.flippedCards = [];}, 400);}else{setTimeout(() => {this.flippedCards.forEach((card) => {card.isFlipped = false});this.flippedCards = [];}, 800);}
},

We added 400 microseconds of delay before marking them as matched, and 800 microseconds to delay before flipping them back.

在将它们标记为匹配之前,我们增加了400微秒的延迟,而在将它们翻转回之前增加了800微秒的延迟。

Also modify the flipCard method to not flip the cards when

还要修改flipCard方法,以在以下情况下不翻转卡片

  • Card is already matched卡已匹配
  • Card is already flipped卡已被翻转
  • User has already flipped two cards用户已经翻转了两张卡
flipCard(card){if(card.isMatched || card.isFlipped || this.flippedCards.length === 2)return;card.isFlipped = true;if(this.flippedCards.length < 2)this.flippedCards.push(card);if(this.flippedCards.length === 2)    this._match(card);
},

We are almost there, just few more steps.

我们快到了,只需要几个步骤。

完成游戏 (Finish the Game)

The game is marked as finished when all the cards are matched.

当所有纸牌都匹配时,游戏被标记为完成。

Let's quickly write the code condition for that. We introduce a new data property in our Vue instance:

让我们快速编写代码条件。 我们在Vue实例中引入了一个新的data属性:

...
finish: false

Next, we modify the match method to check if all cards are matched after every successful match.

接下来,我们修改匹配方法,以在每次成功匹配后检查所有卡是否都匹配。

setTimeout(() => {this.flippedCards.forEach(card => card.isMatched = true);this.flippedCards = [];//All cards matched ?if(this.memoryCards.every(card => card.isMatched === true)){this.finish = true;}}, 400);

We use the every method of JavaScript arrays which evaluates the given condition for truth, if not it returns false.

我们使用JavaScript数组的every方法,该方法会评估给定条件是否为真,否则返回false。

跟踪总转弯和总时间 (Keep Track of Total Turns and Total Time)

We have built the game, so now let's make it more interesting by giving it some finishing touches. We will add how many turns a user has taken, and also how they are doing on time taken to complete the game.

我们已经构建了游戏,所以现在让我们通过一些画龙点睛的使其变得更有趣。 我们将添加用户进行了多少回合,以及他们如何按时完成游戏。

First we'll introduce some new data properties:

首先,我们将介绍一些新的数据属性:

start: false
turns: 0,
totalTime: {minutes: 0,seconds: 0,
},

Once there are two cards flipped we will increase the count. Thus we'll modify the _match method to increment the turns.

一旦翻转了两张卡,我们将增加计数。 因此,我们将修改_match方法以增加转弯。

...
_match(card){this.turns++;...

Next up we modify the flipCard method to start the timer:

接下来,我们修改flipCard方法以启动计时器:

flipCard(card){if(card.isMatched || card.isFlipped || this.flippedCards.length === 2)return;if(!this.start){this._startGame();}......

Add two new methods to start the clock once the game is started:

游戏开始后,添加两种新方法来启动时钟:

_startGame(){this._tick();this.interval = setInterval(this._tick,1000);this.start = true;
},_tick(){if(this.totalTime.seconds !== 59){this.totalTime.seconds++;return}this.totalTime.minutes++;this.totalTime.seconds = 0;
},

We use computed properties to pad up a '0' in front of minutes and seconds when they are single digits:

当它们是个位数时,我们使用计算属性在分钟和秒的前面填充“ 0”:

computed:{sec(){if(this.totalTime.seconds < 10){return '0'+this.totalTime.seconds;}return this.totalTime.seconds;},min(){if(this.totalTime.minutes < 10){return '0'+this.totalTime.minutes;}return this.totalTime.minutes;}
}

Add the following HTML just above your HTML to display the total number of turns and total time:

在HTML上方添加以下HTML,以显示总匝数和总时间:

<div class="d-flex flex-row justify-content-center py-3"><div class="turns p-3"><span class="btn btn-info">Turns : <span class="badge" :class="finish ? 'badge-success' : 'badge-light'">{{turns}}</span> </span></div><div class="totalTime p-3"><span class="btn btn-info">Total Time : <span class="badge" :class="finish ? 'badge-success' : 'badge-light'">{{min}} : {{sec}}</span></span></div>
</div>

Modify the finish game condition to stop the timer once the game is finished:

修改完成游戏条件以在游戏结束后停止计时器:

if(this.memoryCards.every(card => card.isMatched === true)){clearInterval(this.interval);this.finish = true;
}

重启 (Reset)

We are at our last step – good job if you've made it to this point.

我们已经走到了最后一步-如果您做到了这一点,那就很好。

Let's add a button to reset the game:

让我们添加一个按钮来重置游戏:

<div class="totalTime p-3"><button class="btn btn-info" @click="reset" :disabled="!start">Restart</button></div>

Bind the click event to the reset method:

将click事件绑定到reset方法:

reset(){clearInterval(this.interval);this.cards.forEach((card) => {Vue.set(card, 'isFlipped',false);Vue.set(card, 'isMatched',false);});setTimeout(() => {  this.memoryCards = [];this.memoryCards = _.shuffle(this.memoryCards.concat(_.cloneDeep(this.cards), _.cloneDeep(this.cards)));this.totalTime.minutes = 0;this.totalTime.seconds = 0;this.start = false;this.finish = false;this.turns = 0;this.flippedCards = [];}, 600);},

We clear out the timer, reshuffle the cards, and reset all the fields back to their default value.

我们清除计时器,重新洗牌,然后将所有字段重置为默认值。

We also modify the created lifecycle method to call the reset method to avoid code duplication:

我们还修改了创建的生命周期方法以调用reset方法,以避免代码重复:

created(){this.reset();
},

There you go ! You now have a memory game in VueJS.

你去! 您现在在VueJS中有一个记忆游戏。

If you are looking to learn VueJS basics along with such fun practice exercises, you can read the VueJS Tutorial series on my personal blog 5Balloons VueJS Course.

如果您想学习VueJS基础知识以及此类有趣的练习,可以在我的个人博客5Balloons VueJS课程中阅读VueJS教程系列。

翻译自: https://www.freecodecamp.org/news/how-to-build-a-memory-card-game-with-vuejs/

如何使用Vue.js构建存储卡游戏相关推荐

  1. python django vue_Django+Vue.js构建项目

    本文主要讲述如何从0开始,用Django和Vue.js构建一个项目.文章提要:Django与vue.js整合开发原理 从头新建一个Django项目 新建一个前端页面,使用vue应用 在Django中设 ...

  2. vue.js 构建项目_使用Vue.js和AWS Amplify构建Chatbot

    vue.js 构建项目 Over the last few years, chatbots have exploded in popularity. It makes sense that busin ...

  3. 使用Pusher和Vue.js构建实时聊天应用

    如今,实时通信的应用程序越来越流畅,用户体验也变得越来越流行. 在本教程中,我们将使用由Chater提供的服务ChatKit提供支持的Vue.js构建实时聊天应用程序. ChatKit服务将为我们提供 ...

  4. vue查看本地相册_使用Vue.js构建的Google相册相册查看器

    vue查看本地相册 google-photos-vue (google-photos-vue) Google Photos album viewer built with Vue.js. 使用Vue. ...

  5. Asp.net+Vue2构建简单记账WebApp之六(vue.js构建记账统计页面)

    Asp.net+Vue2构建简单记账WebApp之一(设计) Asp.net+Vue2构建简单记账WebApp之二(使用ABP迅速搭建.Net后台) Asp.net+Vue2构建简单记账WebApp之 ...

  6. 使用 Vue.js 构建 VS Code 扩展

    使用 Vue.js 构建 VS Code 扩展 Visual Studio (VS) Code 是开发人员在日常任务中最喜欢使用的代码编辑器之一.它的构建考虑到了可扩展性.在某种程度上,VS Code ...

  7. 使用 Vuex + Vue.js 构建单页应用 1

    鉴于该篇文章阅读量大,回复的同学也挺多的,特地抽空写了一篇 vue2.0 下的 vuex 使用方法,传送门:使用 Vuex + Vue.js 构建单页应用[新篇] ------------------ ...

  8. 使用 Vuex + Vue.js 构建单页应用

    原文地址:https://coligo.io/learn-vuex-by-building-notes-app/ 前言:在最近学习 Vue.js 的时候,看到国外一篇讲述了如何使用 Vue.js 和 ...

  9. 如何使用Vuex+Vue.js构建单页应用

    原文地址:https://coligo.io/learn-vuex-by-building-notes-app/ 前言:在最近学习 Vue.js 的时候,看到国外一篇讲述了如何使用 Vue.js 和 ...

最新文章

  1. Python矩阵处理库—Numpy库的基本使用
  2. oracle execute immediate执行多条语句_用数据库的方式思考SQL是如何执行的
  3. MySQL 我们来聊聊 count(*) 语句的优化方式有哪些?
  4. Ubantu install jdk
  5. kafka手动调整分区副本数
  6. centos安装mysql5.6系统崩溃_CentOS中安装MySQL5.6报错的解决方法
  7. 计算机网络技术的专业认识,计算机网络技术课程学习后的自我认识
  8. 面试问sql优化怎么回答
  9. NIUDAY 七牛美图 AI 共享日 | 大咖云集 邀您共同探索各场景下的 AI 应用与落地...
  10. jsp项目连接mysql_JSP程序使用JDBC连接MySQL的教程
  11. nvme分区选mbr还是guid_小白也会装系统 固态硬盘Win10热门主板Bios设置教程NVME和SATA...
  12. 分享75个商务商城PHP源码,总有一款适合你
  13. el-select和el-tree结合的下拉树
  14. ckplayer x2去logo,改右键
  15. 使用IDEA+gradle构建spring5源码-手把手教程全图解
  16. Windows 下rsync同步数据报错7456
  17. 野山参怎么吃好,这样炖是不是效果最好
  18. 13 Python总结之估值
  19. stb_image图像库处理tga转png
  20. 网络骗子的特征。大家一定要转载。

热门文章

  1. 变焦控制ZoomControls
  2. Huffman树(哈夫曼树)、哈夫曼编码、最优前缀码、前缀码
  3. 用cocos2dx做一个简单的单机捕鱼达人游戏(5)
  4. 爬虫-起点-selenium-动态页面
  5. windows10下两台电脑连接局域网怎么设置?
  6. Python全栈开发之MySQL
  7. Leetcode答题 --- 独一无二的出现次数
  8. “四大名旦”如何唱红上海滩?(图)
  9. 【第74篇】 FasterNet:CVPR2023年最新的网络,基于部分卷积PConv,性能远超MobileNet,MobileVit
  10. IntStream.iterate的简单使用