<p><code></p> <p>一、 Getter</p> <p>我们先回忆一下上一篇的代码</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="computed:{ getName(){ return this.$store.state.name } }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs kotlin"><code>computed:{ getName(){ <span class="hljs-keyword">return</span> <span class="hljs-keyword"><a href="http://www.js-code.com/tag/this" title="浏览关于“this”的文章" target="_blank" class="tag_link">this</a></span>.$store.state.name } }</code></pre> <p>这里假设现在逻辑有变,我们最终期望得到的数据(getName),是基于 <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.$store.state.name 上经过复杂计算得来的,刚好这个getName要在好多个地方使用,那么我们就得复制好几份.</p> <p>vuex 给我们提供了 getter,请看代码 (文件位置 /src/store/index.js)</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ // 类似 vue 的 data state: { name: 'oldName' }, // 类似 vue 的 computed -----------------以下5行为新增 getters:{ getReverseName: state => {<br /> return state.name.split('').reverse().join('')<br /> }<br /> },<br /> // 类似 vue 里的 mothods(同步方法)<br /> mutations: {<br /> updateName (state) {<br /> state.name = 'newName'<br /> }<br /> }<br /> })" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-keyword">import</span> <a href="http://www.js-code.com/tag/vue" title="浏览关于“Vue”的文章" target="_blank" class="tag_link">Vue</a> <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span> <span class="hljs-keyword">import</span> Vuex <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex'</span> Vue.use(Vuex) <span class="hljs-keyword"><a href="http://www.js-code.com/tag/export" title="浏览关于“export”的文章" target="_blank" class="tag_link">export</a></span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">new</span> Vuex.Store({ <span class="hljs-comment">// 类似 vue 的 data</span> state: { name: <span class="hljs-string">'oldName'</span> }, <span class="hljs-comment">// 类似 vue 的 computed -----------------以下5行为新增</span> getters:{ getReverseName: <span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> { <span class="hljs-keyword">return</span> state.name.split(<span class="hljs-string">''</span>).reverse().join(<span class="hljs-string">''</span>) } }, <span class="hljs-comment">// 类似 vue 里的 mothods(同步方法)</span> mutations: { updateName (state) { state.name = <span class="hljs-string">'newName'</span> } } })</code></pre> <p>然后我们可以这样用 文件位置 /src/main.js</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="computed:{ getName(){ return this.$store.getters.getReverseName } }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs kotlin"><code>computed:{ getName(){ <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.$store.getters.getReverseName } }</code></pre> <p>事实上, getter 不止单单起到封装的作用,它还跟vue的computed属性一样,会缓存结果数据, 只有当依赖改变的时候,才要重新计算.</p> <p>二、 actions和$dispatch</p> <p>细心的你,一定发现我之前代码里 mutations 头上的注释了 类似 vue 里的 mothods(同步方法)</p> <p>为什么要在 methods 后面备注是同步方法呢? mutation只能是同步的函数,只能是同步的函数,只能是同步的函数!! 请看vuex的解释:</p> <div class="google-auto-placed ap_container" style="text-align: center; width: 100%; height: auto; clear: none;"><ins data-ad-format="auto" class="adsbygoogle adsbygoogle-noablate" data-ad-client="ca-pub-6330872677300335" data-adsbygoogle-status="done" style="display: block; margin: auto; background-color: transparent;"><ins id="aswift_4_expand" style="display: inline-table; border: none; height: 0px; margin: 0px; padding: 0px; position: relative; visibility: visible; width: 697px; background-color: transparent;"><ins id="aswift_4_anchor" style="display: block; border: none; height: 0px; margin: 0px; padding: 0px; position: relative; visibility: visible; width: 697px; background-color: transparent; overflow: hidden; opacity: 0;"><iframe width="697" height="175" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" onload="var i=this.id,s=window.google_iframe_oncopy,H=s&amp;&amp;s.handlers,h=H&amp;&amp;H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&amp;&amp;d&amp;&amp;(!d.body||!d.body.firstChild)){if(h.call){setTimeout(h,0)}else if(h.match){try{h=s.upd(h,i)}catch(e){}w.location.replace(h)}}" id="aswift_4" name="aswift_4" style="left:0;position:absolute;top:0;border:0px;width:697px;height:175px;"></iframe></ins></ins></ins></div> <p>现在想象,我们正在 debug 一个 app 并且观察 devtool 中的 mutation 日志。每一条 mutation 被记录, devtools 都需要捕捉到前一状态和后一状态的快照。然而,在上面的例子中 mutation 中的异步函数中的回调让这不 可能完成:因为当 mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调 用——实质上任何在回调函数中进行的状态的改变都是不可追踪的。<br /> 那么如果我们想触发一个异步的操作呢? 答案是: action + $dispatch, 我们继续修改store/index.js下面的代码</p> <p>文件位置 /src/store/index.js</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="import Vue from 'vue' import Vuex from 'vuex' export default new Vuex.Store({ // 类似 vue 的 data state: { name: 'oldName' }, // 类似 vue 的 computed getters:{ getReverseName: state => {<br /> return state.name.split('').reverse().join('')<br /> }<br /> },<br /> // 类似 vue 里的 mothods(同步方法)<br /> mutations: {<br /> updateName (state) {<br /> state.name = 'newName'<br /> }<br /> },<br /> // 类似 vue 里的 mothods(异步方法) -------- 以下7行为新增<br /> actions: {<br /> updateNameAsync ({ commit }) {<br /> setTimeout(() => {<br /> commit('updateName')<br /> }, 1000)<br /> }<br /> }<br /> })" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span> <span class="hljs-keyword">import</span> Vuex <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex'</span> <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">new</span> Vuex.Store({ <span class="hljs-comment">// 类似 vue 的 data</span> state: { name: <span class="hljs-string">'oldName'</span> }, <span class="hljs-comment">// 类似 vue 的 computed</span> getters:{ getReverseName: <span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> { <span class="hljs-keyword">return</span> state.name.split(<span class="hljs-string">''</span>).reverse().join(<span class="hljs-string">''</span>) } }, <span class="hljs-comment">// 类似 vue 里的 mothods(同步方法)</span> mutations: { updateName (state) { state.name = <span class="hljs-string">'newName'</span> } }, <span class="hljs-comment">// 类似 vue 里的 mothods(异步方法) -------- 以下7行为新增</span> actions: { updateNameAsync ({ commit }) { setTimeout(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> { commit(<span class="hljs-string">'updateName'</span>) }, <span class="hljs-number">1000</span>) } } })</code></pre> <p>然后我们可以再我们的vue页面里面这样使用</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="methods: { rename () { this.$store.dispatch('updateNameAsync') } }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs groovy"><code><span class="hljs-string">methods:</span> { rename () { <span class="hljs-keyword">this</span>.$store.dispatch(<span class="hljs-string">'updateNameAsync'</span>) } }</code></pre> <p>三、 Module 模块化</p> <p>当项目越来越大的时候,单个 store 文件,肯定不是我们想要的, 所以就有了模块化. 假设 src/store 目录下有这2个文件</p> <p>moduleA.js</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="export default { state: { ... }, getters: { ... }, mutations: { ... }, actions: { ... } }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs properties"><code><span class="hljs-attr">export</span> <span class="hljs-string">default {</span> <span class="hljs-attr">state</span>: <span class="hljs-string">{ ... },</span> <span class="hljs-attr">getters</span>: <span class="hljs-string">{ ... },</span> <span class="hljs-attr">mutations</span>: <span class="hljs-string">{ ... },</span> <span class="hljs-attr">actions</span>: <span class="hljs-string">{ ... }</span> <span class="hljs-attr">}</span></code></pre> <p>moduleB.js</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="export default { state: { ... }, getters: { ... }, mutations: { ... }, actions: { ... } } 那么我们可以把 index.js 改成这样 import moduleA from './moduleA' import moduleB from './moduleB' export default new Vuex.Store({ modules: { moduleA, moduleB } }) 这样我们就可以很轻松的把一个store拆分成多个. 四、 总结 •actions 的参数是 store 对象,而 getters 和 mutations 的参数是 state . •actions 和 mutations 还可以传第二个参数,具体看vuex官方文档 •getters/mutations/actions 都有对应的map,如: mapGetters , 具体看vuex官方文档 •模块内部如果怕有命名冲突的话,可以使用命名空间, 具体看vuex官方文档 •vuex 其实跟 vue 非常像,有data(state),methods(mutations,actions),computed(getters),还能模块化." title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> { state: { ... }, getters: { ... }, mutations: { ... }, actions: { ... } } 那么我们可以把 index.js 改成这样 <span class="hljs-keyword">import</span> moduleA <span class="hljs-keyword">from</span> <span class="hljs-string">'./moduleA'</span> <span class="hljs-keyword">import</span> moduleB <span class="hljs-keyword">from</span> <span class="hljs-string">'./moduleB'</span> <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">new</span> Vuex.Store({ modules: { moduleA, moduleB } }) 这样我们就可以很轻松的把一个store拆分成多个. 四、 总结 •actions 的参数是 store 对象,而 getters 和 mutations 的参数是 state . •actions 和 mutations 还可以传第二个参数,具体看vuex官方文档 •getters/mutations/actions 都有对应的map,如: mapGetters , 具体看vuex官方文档 •模块内部如果怕有命名冲突的话,可以使用命名空间, 具体看vuex官方文档 •vuex 其实跟 vue 非常像,有data(state),methods(mutations,actions),computed(getters),还能模块化.</code></pre> <p></code></p>

本文固定链接: http://www.js-code.com/vue-js/vue-js_26841.html