Vue vs React, Code Comparison
Counter Example
Counter.vue
<template>
<div id="app">
Clicked: {{ $store.state.count }} times, count is {{ evenOrOdd }}.
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementIfOdd">Increment if odd</button>
<button @click="incrementAsync">Increment async</button>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
computed: mapGetters([
'evenOrOdd'
]),
methods: mapActions([
'increment',
'decrement',
'incrementIfOdd',
'incrementAsync'
])
}
</script>
store.js
import { createStore } from 'vuex'
// root state object.
// each Vuex instance is just a single state tree.
const state = {
count: 0
}
// mutations are operations that actually mutate the state.
// each mutation handler gets the entire state tree as the
// first argument, followed by additional payload arguments.
// mutations must be synchronous and can be recorded by plugins
// for debugging purposes.
const mutations = {
increment (state) {
state.count++
},
decrement (state) {
state.count--
}
}
// actions are functions that cause side effects and can involve
// asynchronous operations.
const actions = {
increment: ({ commit }) => commit('increment'),
decrement: ({ commit }) => commit('decrement'),
incrementIfOdd ({ commit, state }) {
if ((state.count + 1) % 2 === 0) {
commit('increment')
}
},
incrementAsync ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('increment')
resolve()
}, 1000)
})
}
}
// getters are functions.
const getters = {
evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd'
}
// A Vuex instance is created by combining the state, mutations, actions,
// and getters.
export default createStore({
state,
getters,
actions,
mutations
})
components/Counter.js
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class Counter extends Component {
constructor(props) {
super(props);
this.incrementAsync = this.incrementAsync.bind(this);
this.incrementIfOdd = this.incrementIfOdd.bind(this);
}
incrementIfOdd() {
if (this.props.value % 2 !== 0) {
this.props.onIncrement()
}
}
incrementAsync() {
setTimeout(this.props.onIncrement, 1000)
}
render() {
const { value, onIncrement, onDecrement } = this.props
return (
<p>
Clicked: {value} times
{' '}
<button onClick={onIncrement}>
+
</button>
{' '}
<button onClick={onDecrement}>
-
</button>
{' '}
<button onClick={this.incrementIfOdd}>
Increment if odd
</button>
{' '}
<button onClick={this.incrementAsync}>
Increment async
</button>
</p>
)
}
}
Counter.propTypes = {
value: PropTypes.number.isRequired,
onIncrement: PropTypes.func.isRequired,
onDecrement: PropTypes.func.isRequired
}
export default Counter
reducers/index.js
export default (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}