SuperLucyFight / vuex-zh

0 stars 0 forks source link

vuex 翻译 #1

Open SuperLucyFight opened 8 years ago

SuperLucyFight commented 8 years ago

安装

直接下载 / CDN

源码:https://unpkg.com/vuex

Unpkg.com 提供基于npm的cdn链接。 上面的链接总是指向npm能安装的最新版本。你也可以使用一个特定版本或者标签,比如https://unpkg.com/vuex@2.0.0。

放vuex.js于 Vue.js之后,并且它会自动安装。

<script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script>

NPM安装

npm install vuex

当使用一个模块系统,你必须显式地安装vuex通过Vue.use()。

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

当使用全局脚本标签时,你不需要这样做。

Dev Build

如果你想使用最新的开发版本,你将不得不直接从github上克隆并且构建。

git clone https://github.com/vuejs/vuex.git node_modules/vuex
cd node_modules/vuex
npm install
npm run build
SuperLucyFight commented 8 years ago

Modules

由于使用一个单一的状态树,我们的应用程序的所有状态都包含在一个大的对象中。然而,随着我们的应用程序规模的增长,store可能会变得非常臃肿。

为了解决上述问题,vuex允许我们将我们的存储模块为 modules。每一个module 能包含它自己的 state、 mutations、 actions、 getters 甚至嵌套的modules —— 它的分形一路下来:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA's state
store.state.b // -> moduleB's state

Module Local State

在一个module的 mutations 和 getters内, 收到的第一个参数将是 the module's local state

const moduleA = {
  state: { count: 0 },
  mutations: {
    increment: (state) {
      // state is the local module state
      state.count++
    }
  },

  getters: {
    doubleCount (state) {
      return state.count * 2
    }
  }
}

同样,在module actions内, context.state将暴露 local state,并且 root state 将作为context.rootState被暴露。

const moduleA = {
  // ...
  actions: {
    incrementIfOdd ({ state, commit }) {
      if (state.count % 2 === 1) {
        commit('increment')
      }
    }
  }
}

同样,在 module getters,内, root state 将被暴露为第三个参数:

const moduleA = {
  // ...
  getters: {
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}

Namespacing

注意在modules 内的actions、mutations 和getters 仍然注册在全局命名空间下——这允许多个模块的相同mutation/action反应。你可以命名空间模块,资产自己来避免他们名字以前缀或后缀的冲突。也许你应该你正在写一个可重用的vuex模块将被用在未知的环境中。例如,我们要创建一个`todNote‘的module:

// types.js

//定义getters, actions 和 mutations 的名字作为常量
// 并且他们以module名字 `todos`作为前缀
export const DONE_COUNT = 'todos/DONE_COUNT'
export const FETCH_ALL = 'todos/FETCH_ALL'
export const TOGGLE_DONE = 'todos/TOGGLE_DONE'
// modules/todos.js
import * as types from '../types'

// 使用前缀名字定义getters, actions 和 mutations 
const todosModule = {
  state: { todos: [] },

  getters: {
    [types.DONE_COUNT] (state) {
      // ...
    }
  },

  actions: {
    [types.FETCH_ALL] (context, payload) {
      // ...
    }
  },

  mutations: {
    [types.TOGGLE_DONE] (state, payload) {
      // ...
    }
  }
}

Dynamic Module Registration(动态module注册)

在 store被创建之后,你可以通过 store.registerModule 方法注册一个 module :

store.registerModule('myModule', {
  // ...
})

module的 state 将被暴露作为 store.state.myModule

动态注册 module 使其他的Vue插件通过整个应用的store一个附加module 利用Vuex 管理state成为可能。例如, vuex-router-sync /使 vue-router 和vuex结为整体在一个动态的连接模块中通过管理项目的路由状态 。

你也可以用store.unregisterModule(moduleName)删除动态注册的模块。注意,您不能用此方法静态模块(在存储时的创建声明)。

SuperLucyFight commented 8 years ago

Plugins

接受插件选项,为每个变更公开钩子。一个vuex插件是一个简单的函数,接收store 作为唯一的参数:

const myPlugin = store => {
  // called when the store is initialized
  store.subscribe((mutation, state) => {
    // called after every mutation.
    // The mutation comes in the format of { type, payload }.
  })
}

并且像这样能被使用:

const store = new Vuex.Store({
  // ...
  plugins: [myPlugin]
})

Committing Mutations Inside Plugins

插件不允许直接变更状态 ——和你的components类似,他们仅仅能触发改变通过提交变更。

通过提交突变,一个插件可以用于将数据源同步到store。 举例, 同步一个WebSocket数据源到 store (这只是一个例子,现实中的createPlugin功能可以采取一些额外的选项对于较复杂的任务):

export default function createWebSocketPlugin (socket) {
  return store => {
    socket.on('data', data => {
      store.commit('receiveData', data)
    })
    store.subscribe(mutation => {
      if (mutation.type === 'UPDATE_DATA') {
        socket.emit('update', mutation.payload)
      }
    })
  }
}
const plugin = createWebSocketPlugin(socket)

const store = new Vuex.Store({
  state,
  mutations,
  plugins: [plugin]
})

Taking State Snapshots

有时插件可能想收到一个state的 "snapshots",并对突变后的状态与前突变状态进行了比较 。 要实现这一目标,您将需要在状态对象上执行一个深拷贝:

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
  })
}

插件仅在开发过程中使用状态快照。 使用WebPACK或者Browserify的时候,我们可以让我们的构建工具为我们处理:

const store = new Vuex.Store({
  // ...
  plugins: process.env.NODE_ENV !== 'production'
    ? [myPluginWithSnapshot]
    : []
})

该插件将被默认使用。 对于生产环境,你必须在最后的构建中用Webpack 的DefinePlugin 或者 Browserify 的 envify 来转换 process.env.NODE_ENV !== 'production' 的值为tfalse

Built-in Logger Plugin

如果你使用 vue-devtools 你也许不需要这个。

Vuex有一个 logger 插件对于常见的调试使用:

import createLogger from 'vuex/dist/logger'

const store = new Vuex.Store({
  plugins: [createLogger()]
})

createLogger 函数需要几个options:

const logger = createLogger({
  collapsed: false, // 自动扩展记录的突变
  transformer (state) {
    // 在记录它之前变换状态。
    //例如,只返回一个特定的子树
    return state.subTree
  },
  mutationTransformer (mutation) {
    // 变更的记录以这种格式 { type, payload }
    // 我们可以格式化它任何我们想要的方式
    return mutation.type
  }
})

日志文件也可以包括直接通过<script> 标签,并将全局地暴露 createVuexLogger 函数。

注意Logger插件产生状态的快照,所以只有在发展时用它。