这是无关 React 和 Vue 语法比拟的第三篇文章。在本文中,将比拟两种生态系统中最驰名的状态治理库(Redux 和 Vuex)的语法。
其它两篇:
- React.js 和 Vue.js 的语法并列比拟
- Next.js 和 Nuxt.js 的语法比拟
议程
- 创立 Store
- Action
- 异步 Action
- Reducer | Mutation
- Combine-Reducers | Modules
- Connect-with-Component
- 中间件 | 插件
- Selector | Getter
- DevTools
创立 Store
Redux: https://redux.js.org/basics/s…
import React from 'react'
import {render} from 'react-dom'
import {Provider} from 'react-redux'
import {createStore} from 'redux'
import todoApp from './reducers'
import App from './components/App'
const store = createStore(todoApp)
render(<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
Vuex: https://vuex.vuejs.org/guide/
const store = new Vuex.Store({state: { ...},
mutations: {...}
})
...
new Vue({
el: '#app',
store,
});
Action
Redux: https://redux.js.org/basics/a…
const ADD_TODO = 'ADD_TODO'
function addTodo(text) {
return {
type: ADD_TODO,
text,
}
}
Vuex: https://vuex.vuejs.org/guide/…
const store = new Vuex.Store({
actions: {increment (context) {context.commit('increment') // commit a mutation to trigger state update
}
}
})
异步 Action
Redux(redux-thunk): https://redux.js.org/advanced…
// apply redux-thunk
import thunkMiddleware from 'redux-thunk'
const store = createStore(
rootReducer,
applyMiddleware(thunkMiddleware)
)
...
export function fetchPosts() {return function (dispatch) {dispatch(requestPosts())
return fetch('xxx')
.then(response => response.json())
.then(json => dispatch(receivePosts(json)))
}
}
Vuex: https://vuex.vuejs.org/guide/…
actions: {async fetchPosts ({ commit}) {commit('requestPosts');
const res = await fetch('xxx');
commit('receivePosts', res);
},
}
Reducer | Mutation
Redux(reducer): https://redux.js.org/basics/r…
const initialState = {todos: [],
}
function todoApp(state = initialState, action) {switch (action.type) {
case ADD_TODO:
return {
...state,
todos: [
...state.todos,
{
text: action.text,
completed: false,
}
],
}
default:
return state
}
}
Vuex(mutation): https://vuex.vuejs.org/guide/…
const store = new Vuex.Store({
mutations: {addTodo (state, payload) {
state.todos = [
...state.todos,
{text: payload.text, completed: false}
]
}
}
})
Combine-Reducers | Modules
Redux(combine-reducers): https://redux.js.org/api/comb…
import {combineReducers} from 'redux'
const reducers = combineReducers({
reducerA,
reducerB,
})
export default reducers
Vuex(modules): https://vuex.vuejs.org/guide/…
const moduleA = {state: { ...},
mutations: {...},
actions: {...},
getters: {...}
}
const moduleB = {state: { ...},
mutations: {...},
actions: {...}
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
Connect-with-Component
Redux: https://redux.js.org/basics/u…
import {connect} from 'react-redux'
import {addTodo} from '../actions'
import TargetComp from '../components/TargetComp'
// state
const mapStateToProps = (state, ownProps) => {
return {todos: state.todos,}
}
// action
const mapDispatchToProps = (dispatch, ownProps) => {
return {addTodo: (text) => {dispatch(addTodo(text))
}
}
}
const TargetContainer = connect(mapStateToProps, mapDispatchToProps)(TargetComp)
export default TargetContainer
Vuex
state: https://vuex.vuejs.org/guide/…
import {mapState} from 'vuex'
export default {
computed: {...mapState(['count']),
}
}
action: https://vuex.vuejs.org/guide/…
import {mapActions} from 'vuex'
export default {
methods: {...mapActions(['increment']),
}
}
中间件 | 插件
Redux(middleware): https://redux.js.org/advanced…
import {createStore, combineReducers, applyMiddleware} from 'redux'
const logger = store => next => action => {console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
const todoApp = combineReducers(reducers)
const store = createStore(
todoApp,
applyMiddleware(logger)
)
Vuex(plugin): https://vuex.vuejs.org/guide/…
const myPluginWithSnapshot = store => {let prevState = _.cloneDeep(store.state)
store.subscribe((mutation, state) => {let nextState = _.cloneDeep(state)
// compare `prevState` and `nextState`...
// save state for next mutation
prevState = nextState
})
}
const store = new Vuex.Store({
...,
plugins: process.env.NODE_ENV !== 'production' ? [myPluginWithSnapshot] : [],})
Selector | Getter
Redux(reselect): https://redux.js.org/recipes/…
import {createSelector} from 'reselect'
const getTodos = state => state.todos
export const getDoneTodos = createSelector([getTodos],
todos.filter(t => t.completed),
)
...
import {connect} from 'react-redux'
import TodoList from '../components/TodoList'
import {getDoneTodos} from '../selectors'
const mapStateToProps = state => {
return {doneTodos: getDoneTodos(state)
}
}
const DoneTodoList = connect(mapStateToProps)(TodoList)
export default DoneTodoList
Vuex: https://vuex.vuejs.org/guide/…
const store = new Vuex.Store({state: { ...},
getters: {
doneTodos: state => {return state.todos.filter(t => t.completed)
}
}
})
...
import {mapGetters} from 'vuex'
export default {
computed: {...mapGetters(['doneTodos'])
}
}
DevTools
Redux
https://chrome.google.com/web…
Vuex
https://chrome.google.com/web…
起源:https://medium.com/js-dojo,作者:Oahehc (Andrew),翻译:公众号《前端全栈开发者》