React’s official tutorial tic tac toe do a good job to guide the newbie to enter React’s world step by step, I think that similar tutorial will inspire Vue.js’s newbie, so I use Vue.js to rewrite it
First you can see the final result, and try to click and experience, we will fulfill this effect gradually
Initial Code
Initial Effect
Open Initial status and edit directly, or copy the code to corresponding files in the same directory
For now it’s just a simple tic tac toe grid, and a hard-coded “Next Player”
Initial Code Description
Now three component has been defined, which are Square
, Board
and Game
respectively
Square is just a normal button now
1 | Vue.component('Square', { |
- After component is defined like this, other component can use <Square /> to reference this component directly
Board component is composed by current status and 9 Square
1 | Vue.component('Board', { |
- the current
status
and value ofboard
is defined indata
, thus you can use {{ status }} to reference the value of status, and usev-for
to iterate two dimension arrayboard
twice to compose tic tac toe grid data
in component must be a function which return a object, but not literal objectv-for
must havekey
to make sure performance without alert
Game
component is formed by Board
, and status and history which will be added later
1 | Vue.component('Game', { |
Add Data Handling
Add Props
Deliver a prop
whose name is value
to Square in Board
1 | <Square v-for="square in row" :key="square" :value="square" /> |
- :value is short for v-bind:value, which means that its value is an expression
Add value
prop in the component definition and template of Square
1 | Vue.component('Square', { |
props
are variables which parent component can deliver to child component, set corresponding attribute in tag when parent component invoke child component, and the usage method is the same asdata
in child component
Current code and effect: number 0 - 8 are filled into the tic tac toe respectively
Add Interactive
Add click event to button element to update value
1 | Vue.component('Square', { |
@click
is short forv-on:click
, whose value is the function which will run when click, here set to setValue which is defined in methods of the component- Child component can not update data of parent directly, so change value from props to data
data
‘s value will be updated, and corresponding template will update automatically to display the content.
Current Code and Effect: click the tic tac toe grip, the cell will be filled by X
Improve Game
Data Upward
To alternatively play and confirm winner, we need to determine status of every cell uniformly, so the value will be lifted to Board
Add data squares
and method handleClick
to Board
1 | Vue.component('Board', { |
- Init
squares
to a array with 9 null, so the tic tac toe grip will be empty handleClick
accepts parameter of corresponding cell number, and will update correspondingsquare
element- the event handler is not the return value of
handleClick(square)
, buthandleClick
, andsquare
will be parameter when trigger
Trigger click event of Board in the click event handler of Square
1 | Vue.component('Square', { |
value
need to be changed from data back toprops
$emit
can invoke event handler which parent component deliver- value of prop is updated in parent component, and the child template will update display content correspondingly
Current Code and Effect: click the tic tac toe grid, if it’s not taken, it will be filled with X
Play Alternatively
Add data xIsNext
, and switch when click
1 | data() { |
- Init
xIsNext
astrue
, which means X will be first player - After click, reverse xIsNext to switch
- Update
status
to the next player
current code and effect: click the tic tac toe grid, X and O will play alternatively
Determine Winner
Add function the calculate winner
1 | function calculateWinner(squares) { |
- Enumerate the combination which will win the game, and compare with value of
squares
array
Add winner logic of click handler function
1 | if (calculateWinner(squares)) { |
- After click, if there’s winner before, than the clicking is invalid
- After placement proceeding, judge winner again, and update status
Current code and effect: status and click handler will be updated after one side win
Add Time Tour
Save History Record
To fulfill functionality of retraction, we need to record entire status of every placement, equivalent to the snapshot of the chessboard, which will became a history record, upward to the Game
component
Add history
data in Game
, transfer xIsNext
, status
and handleClick
method from Board to Game
1 | Vue.component('Game', { |
- Utilize the last record of history to assign value to squares (only one record for now)
- After placement, squares will record the placement, and history will add a record
Add prop squares to Board, and update handleClick to invoke event handler of parent component
1 | Vue.component('Board', { |
Current code and effect: status location is updated, and store history is recorded
Show History Step Record
Iterate history records to display, and bind click event, show record of corresponding step via update of stepNumber
1 | Vue.component('Game', { |
- Add
stepNumber
in Game, and init it as0
, record current display step - Utilize corresponding step of
this.stepNumber
to assign value to propsquares
of Board - Handle
history
with current step as foundation in handleClick, and update stepNumber - Add method
jumpTo
to handle display of going back to history, updatestepNumber
,xIsNext
andstatus
Current code and effect: there will be one more history step after every placement, and click the step can return to this step
Summarize
Game Accomplishment
- Place cell alternatively
- Determine Winner
- Retract and play again
Technology Showcase
- v-bind: bind data in template
- v-for: Iterate array in template
- v-on, $emit: transfer and trigger event between components
- data: define in component and automatically update in template
- prop: transfer between components and automatically update in template