经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » HTML/CSS » HTML5 » 查看文章
vuex 源码解析(三) getter属性详解
来源:cnblogs  作者:大沙漠  时间:2019/9/10 10:53:38  对本文有异议

有时候我们需要从store中的state中派生出一些状态,例如:

  1. <div id="app">
  2. <p>{{reverseMessage}}</p>
  3. </div>
  4. <script>
  5. const store = new Vuex.Store({
  6. state:{reverseMessage:'Hello Vue!'}
  7. })
  8. new Vue({
  9. el:'#app',
  10. store,
  11. computed:{
  12. reverseMessage:function(){return this.$store.state.reverseMessage.split('').reverse().join('')}
  13. }
  14. })
  15. </script>

如果多个组件需要用到此属性,我们要么复制这个函数,或者抽取到一个共享函数然后在多处导入它---无论哪种方式都不是很理想

writer by:大沙漠 QQ:22969969

Vuex允许我们在store中定义"getter"(可以认为是store的计算属性),就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算

每个getter对应的匿名函数可以带四个参数,分别是当前模块的state、getter和根模块的state、getter,例如:

  1. <div id="app">
  2. <p>{{reverseMessage}}</p>
  3. </div>
  4. <script>
  5. const store = new Vuex.Store({
  6. state:{reverseMessage:'Hello Vue!'},
  7. getters:{
  8. reverseMessage:function(state){return state.reverseMessage.split('').reverse().join('');}
  9. }
  10. })
  11. new Vue({
  12. el:'#app',
  13. store,
  14. computed:{
  15. reverseMessage:function(){return this.$store.getters.reverseMessage}
  16. }
  17. })
  18. </script>

这样在vuex内部就把reverseMessage这个属性给实现了,还是很好用的,vuex官网里说我们可以把getter当作计算属性一样来使用,事实上vuex内部也是把getter定义为vue的computed计算属性来实现的。

 

源码分析


 在创建Vuex.Store()初始化时会执行installModule()安装根模块,和getter相关的如下:

  1. function installModule (store, rootState, path, module, hot) { //安装模块
  2. /**/
  3. module.forEachGetter(function (getter, key) { //遍历module模块的getters对象,如果找到了,则执行这个匿名函数 参数1:每个getter值 key:对应的键名
  4. var namespacedType = namespace + key; //拼凑命名空间+键名,例如:a/computedCount
  5. registerGetter(store, namespacedType, getter, local); //依次执行registerGetter
  6. });
  7. /**/
  8. }

 registerGetter用于注册每个getter,如下:

  1. function registerGetter (store, type, rawGetter, local) { //注册getter
  2. if (store._wrappedGetters[type]) { //如果store._wrappedGetters下已经有key了
  3. {
  4. console.error(("[vuex] duplicate getter key: " + type)); //则报错,即不允许重复
  5. }
  6. return
  7. }
  8. store._wrappedGetters[type] = function wrappedGetter (store) { //保存到store._wrappedGetters对应的type里
  9. return rawGetter( //执行store函数 四个参数分别为local state、local getters、root state、root getters
  10. local.state, // local state
  11. local.getters, // local getters
  12. store.state, // root state
  13. store.getters // root getters
  14. )
  15. };
  16. }

这样在 store._wrappedGetters中就存储了对应的getter了,是一个匿名函数,函数有一个参数是store,这个是vuex.store()的实例,一会创建vue实例时会传入的,这样在geter里就能访问到根模块的state和getters了

例子执行到这里对应的_wrappedGetters如下:

最后Vuex走到resetStoreVM()去创建一个Vue实例时,和getter有关的逻辑如下:

  1. function resetStoreVM (store, state, hot) { //重新存储数据
  2. var oldVm = store._vm;
  3. // bind store public getters
  4. store.getters = {};
  5. var wrappedGetters = store._wrappedGetters; //获取store的所有getter信息,也就是上面保存的数据,每个值是一个匿名函数
  6. var computed = {}; //用于存储最后的计算属性
  7. forEachValue(wrappedGetters, function (fn, key) { //遍历wrappedGetters
  8. // use computed to leverage its lazy-caching mechanism
  9. computed[key] = function () { return fn(store); }; //将computed[key]定义为一个函数表达式,内部返回fn()执行后的结果,传入store参数,这样在geter里就能访问到根模块的state和getters了
  10. Object.defineProperty(store.getters, key, { //设置store.getters的key的访问器属性,这样就可以通过store.getters.aaa访问到某个具体的值了
  11. get: function () { return store._vm[key]; },
  12. enumerable: true // for local getters
  13. });
  14. });
  15. /**/
  16. }

之后如果有修改了state里的信息,getter里的信息都会自动更新的,这个归功于Vue的响应式设计了。

 

原文链接:http://www.cnblogs.com/greatdesert/p/11429856.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号