使用Vue CLI脚手架一键搭建项目——井字棋

3×3连子棋(也叫做井字棋)其实还并不算复杂,3×3的棋盘最多可以放9个棋子,一旦有一方连成三子,则此局棋结束。现使用Vue.js来使用Vue CLI搭建井字棋项目,并将其发布到github上

井字棋项目预览链接

一:需要用到的工具

Node.js、Vue CLI、VScode

二:项目搭建

1. 搭建好项目原型后,将项目拖入VScode中:

项目初始结构如下:
屏幕快照 2019-11-06 下午7.13.50.png
2. 打开src目录下的App.vue,清空里面的内容,只保留如下结构,我们可以在标签template中写html结构,script标签中写 js代码,在style标签中写css代码
<template>
    
</template>>
<script>
export default {
    
}
</script>
<style>
</style>
3. 在src目录下新建一个Cell.vue,创建井字格组件

实现的功能:点击井字格,切换格子里的棋子x0
主要点:条件渲染v-if,v-else;事件处理v-on,简写为@

<template>
  <div class="cell" @click="change">
    <template v-if="a">x</template>
    <template v-else>o</template>
  </div>
</template>
<script>
export default {
  data(){
    return {
      a: false
    }
  },
  methods:{
    change(){
      this.a = !this.a
    }
  }
}
</script>

4. 将Cell.vue引入App.vue中,打开App.vue,

主要点:在 模块系统中局部注册组件import xx from './xx',components{xx}
此时,我们就可以在App模版中使用Cell组件了

<template>
  <Cell></Cell>
</template>
<script>
import Cell from './Cell'
export default {
  components:{Cell}
}
</script>
5. 创建完整的井字棋结构,3*3结构

坑:不能直接在template中直接复用多个Cell,会报Component template should contain exactly one root element这样的错误,此时我们应该用一个元素将他们包裹起来

//错误写法
<template>
  <Cell></Cell>
  <Cell></Cell>
  <Cell></Cell>
  <Cell></Cell>
</template>
//正确写法
<template>
  <div class="container">
    <div class="row">
      <Cell />
      <Cell />
      <Cell />
    </div>
    ...
  </div>
</template>
...

此时页面展示的如下图
屏幕快照 2019-11-06 下午9.02.38.png
6. 我们希望点击的时候再出现ox

实现思路:在 App中设置一个参数n,每点击一次格子则n加1,再将n传到组件Cell中,判断此时n的值为奇数还是偶数,偶数时格子中显示x,奇数时显示o
主要点:父子组件中传递参数,
父组件 to 子组件:父组件v-bind:n="n",@click="cellClick" 子组件:props:['n']
子组件 to 父组件:子组件:this.$emit('xxx',data),父组件:<Cell @click="cellClick($event)" />

// App.vue
<template>
  <div class="container">
    <div class="row">
      <Cell :n="n" @click="cellClick" />
      <Cell :n="n" @click="cellClick" />
      <Cell :n="n" @click="cellClick" />
    </div>
   ...
  </div>
</template>
<script>
import Cell from './Cell'
export default {
  components:{Cell},
  data(){
    return {
      n:0
    }
  },
  methods: {
    cellClick(){
      this.n += 1
    }
  }
}
</script>
//Cell.vue
<template>
  <div class="cell" @click="change">
    <template v-if="a">{{text}}</template>
    <template v-else></template>
  </div>
</template>
<script>
export default {
  props:['n'],
  data(){
    return {
      a: false,
      text:''
    }
  },
  methods:{
    change(){
      this.a = true
      if(this.text !== '') return //点击过的格子不能再点击
    //   console.log(this.n)
      this.text = this.n % 2 === 0? 'x':'o'
      this.$emit('click')
    }
  }
}
</script>

此时,大概完成了井字棋的雏型,点击格子轮流切换棋子

7. 判断输赢

思路:将点击过的格子里的值用3x3的数组记录下来,再判断数组相关值是否相等,相等则游戏结束。游戏结束,则重新渲染页面,开始新一轮游戏
主要点:1. 子组件向父组件传递参数 2. 游戏胜利的条件判断 3. 游戏结束后如何重新渲染页面this.$nextTick()

//App.vue
<template>
  <div class="container">
    <div>第{{n}}手</div>
    <div class="row">
      <Cell :n="n"  @click="cellClick(0,$event)" v-if="update"/>
      ...
    </div>
    ...
</template>
<script>
import Cell from './Cell'
export default {
  components:{Cell},
  data(){
    return {
      n:0,
      result:'',
      update:true, //用来判断组件页面重新渲染与否
      isend: false, //用来判断是游戏是否结束
      map:[[null,null,null],[null,null,null],[null,null,null]]
    }
  },
  methods: {
    cellClick(i,text){
      this.n += 1
      this.map[Math.floor(i/3)][i%3] = text
      this.win()
      this.isended()
    },
    win(){
     ...
    },
    isended(){
      ...
        }

    },
    reload() {
   ...
    }
}
</script>
8. 将项目部署到 github上
  • 手动推送更新
    在 vue.config.js 中设置正确的 publicPath。
  • 如果打算将项目部署到 https://<USERNAME>.github.io/上,publicPath将默认被设为 "/",你可以忽略这个参数。
  • 如果打算将项目部署到https://<USERNAME>.github.io/<REPO>/上 (即仓库地址为https://github.com/<USERNAME>/<REPO>),可将 publicPath设为 "/<REPO>/"。举个例子,如果仓库名字为“my-project”,那么vue.config.js 的内容应如下所示:
module.exports = {
  publicPath: process.env.NODE_ENV === 'production'
    ? '/my-project/'
    : '/'
}
9. 具体部署
    1. 新建一个名为vue.config.js的文件,文件内容为:
module.exports = {
  publicPath: process.env.NODE_ENV === 'production'
    ? '/Tic-Tac-Toe/dist/'
    : '/'
}
    1. 将文件build,npm run build完成后会自动生成一个dist文件夹(dist文件夹用于存放编译后用于发布的线上代码),完成后我们将dist文件夹上传到github上Tic-Tac-Toe上即可

三:总结,遇到的坑

  1. 游戏结束时,我想使用alert函数来通知游戏结束,没想到先弹出来alert,后才在页面上渲染最后一颗棋子
  • 原因:div加载到页面需要时间,还没等加载到页面就执行到alert了,此时alert会阻塞线程,这里阻塞的是GUI渲染线程.所以等alert执行完毕后这个线程才会继续执行,将div内容显示到页面上
  • 解决办法:给把alert放进setTimeout中去执行
  1. 好,我想alert后页面重新渲染,添加 this.reload()函数。什么?函数未定义?
  • 原因,setTmeout里的this指向的是window
  • 解决办法,先在外层赋值let _this = this,再在setTimeout内部调用_this.reload()
  1. 啥,为什么我的reload函数明明执行里,页面却没有重新渲染?
  • 原因,粗心忘记在组件上使用v-if=Boolean来控制页面了,加上
  • <Cell :n="n" @click="cellClick(0,$event)" v-if="update"/>
  1. 要点:
    a)父子组件间相互传值
    b)页面重新渲染: data重置,$nextTick()函数的使用
    c)各种条件的设置与判断

具体代码:见我的github=======https://github.com/PingerL/Tic-Tac-Toe

PS :项目的具体创建

  1. 在官网下载对应版本的Node.js,下载完后常规安装,打开终端,运行node -v来查看是否安装成功,若安装成功会显示对应的版本号
    屏幕快照 2019-11-06 下午6.41.59.png
  2. 全局安装CLI,在终端里运行命令sudo npm install -g @vue/cli
  3. 进入到要创建的文件夹的目录,比如我要创建的文件放在在桌面上名为89的文件夹下:cd /Users/PingerL/Desktop/89
  4. 在当前文件夹下创建一个项目,项目名为demovue1,运行指令:vue create demovue1,选择默认方式创建,至此就创建好了一个项目的原型,具体创建可参考官网
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 1、Oracle在已经存在主键的表中插入复合主键的SQL语句 如已有一个表test_key,其中a1列为主键。 现...
    看看你的肥脸阅读 2,664评论 0 0
  • 参加了一场婚礼,跟着外公,到城里的一个平时根本不会去的大酒店里。 我也不太清楚这到底是谁的婚礼,只知道是以前一...
    湮灭i阅读 132评论 0 0
  • 【要点梳理】 第一步:确认主题、听众、时长 第二步:写下要点,需要哪些故事和案例 第三步:直接说出来,把脑子里的内...
    PZ坚持行动ING阅读 924评论 0 6
  • 考公务员的动机是40%姐姐考上了,别人都觉得她生活过的很轻松,日子过的很不错。心里产生了一种向往,有看得见有方向的...
    23f3fb3cf006阅读 168评论 0 0
  • 他问过我, 花是不是都是女的? 花成了精都是女妖精么? 我想了想 估计别的花都有男女 只有桃花是女的吧 恩,我固执...
    欧阳昊东阅读 233评论 0 0