使用mpvue开发小程序教程(六)

作者: 一斤代码 | 来源:发表于2018-07-31 15:06 被阅读237次

    在上一章节中,我们列举了在Vue中能用但在mpvue中不能用或需要特别注意的特性,在实际开发前了解一下还是很有必要的,可以避免浪费找错误的时间。

    如果你使用过原生的小程序框架,你一定经历过或思考过怎么解决以下的问题:

    • 怎么存放可全局访问的变量?
    • 页面跳转的时候,怎么传递参数到下一个页面比较好?
    • 页面返回上一页的时候,怎么传递当前页的数据到上一页?
    • 多个页面间需要同步数据,怎么做比较好?

    网上一搜,解决的方法通常也是五花八门的,什么通过app上的globalData啊、通过存取storage啊、通过一个单独的模块(module)啊、通过Page路由栈啊、通过引入自定义事件啊、通过引入redux啊,等等等等......

    在原生小程序框架里,确实没有提供什么太统一的方式来指导开发者解决这个问题,大家只能各自用着暂时能解决当前问题的方案。

    不过,既然我们用了Vue/mpvue,遇到这种情况,自然而然的就会想到一个方案,那就是Vuex。Vuex 是一个专为 Vue 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

    通过使用Vuex,我们可以在mpvue里很方便的对需要在app、页面、组件之间共享的数据进行很好的统一管理,可以更方便有效的在各个代码部分对这些共享数据进行访问,同时可以使得你的代码条理变得更加清晰。

    我们知道,Vuex一般有2种用法,当创建好store后:

    • 第一种用法是将store绑定到需要访问store内容的Vue实例上,然后通过该Vue实例下组件的this.$store来引用;或通过mapState等一系列映射函数将store中的state、getters、mutations、actions等映射成组件的计算属性或methods方法来使用;

    • 第二种用法是直接在组件中通过import导入store所在的模块文件,然后调用该store上的相关方法和属性,比如commit()dispatch()等方法来操作store中的内容。

    经过我的实测,上面的这两种方式在mpvue中也都是可用的。但是,由于mpvue不像Vue Web单页应用那种单Vue实例的结构,而是采用了多Vue实例的结构(app和各个页面都会由单独的Vue实例来管理),所以我个人推荐采用上面所说的第二种用法,这种方式会更加灵活和简单一些。

    让我们开始写代码,先在src目录下新建一个stores目录,接着在stores目录下新建一个名为global-store.js的文件:

    import Vue from 'vue'
    import Vuex from 'vuex';
    
    Vue.use(Vuex);
    
    export default new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        increment: (state) => {
          state.count += 1
        },
        decrement: (state) => {
          state.count -= 1
        }
      }
    });
    

    在这个代码中,我们新建了一个Store实例,管理了一个名为count的数字类型的状态,并定义了2个mutations去操作(增减)这个状态值。

    接着,我们要在2个页面中访问这个store。让我们在src/pages目录下编写2个页面:index和test1。

    这是pages/index/index.vue的代码内容:

    <template>
      <div class="container">
        <div>计数结果:{{count}}</div>
        <a href="/pages/test1/main" class="navlink">进入计数器页面</a>
      </div>
    </template>
    
    <script>
    import globalStore from "../../stores/global-store";
    
    export default {
      computed: {
        count() {
          return globalStore.state.count;
        }
      }
    };
    </script>
    
    <style scoped>
    .navlink {
      text-decoration: underline;
    }
    </style>
    

    这是pages/test1/index.vue的代码内容:

    <template>
      <div class="container btns">
        <button class="calbtn" @click="hanleDecrement">-</button>
        <span class="calnum">{{count}}</span>
        <button class="calbtn" @click="hanleIncrement">+</button>
      </div>
    </template>
    
    <script>
    import globalStore from "../../stores/global-store";
    
    export default {
      computed: {
        count() {
          return globalStore.state.count;
        }
      },
    
      methods: {
        hanleIncrement() {
          globalStore.commit("increment");
        },
    
        hanleDecrement() {
          globalStore.commit("decrement");
        }
      }
    };
    </script>
    
    <style scoped>
    .btns {
      display: flex;
      align-items: center;
    }
    .calnum {
      color: red;
      font-size: 32px;
    }
    </style>
    

    这样,我们就有了2个使用了我们定义的global-store的页面,这些页面都会从store中获取count状态值并显示;在test1页面中,还会调用incrementdecrement两个mutations去更新count值。

    运行小程序,可以看到初始进入index页面时是这样的,页面上显示的计数结果是0:

    index页面

    然后点击“进入计数器页面”进到test1页面,并在这个页面上点击加减按钮操作一下,当中显示的count数会发生改变:

    test1页面

    最后,点击左上角返回按钮返回index页面,你将发现这个页面上的即使结果也已经发生了改变,自动同步成前面操作后的结果了:

    返回index页面

    小结

    通过这个例子,是不是感觉到使用Vuex做页面间的传值和数据同步特别简单?另外,你也可以在src/stores目录下按需创建多个store模块,独立管理不同业务范围的数据,并按需导入页面组件使用。

    Vuex是开发中一件非常得力的工具,希望你能尽快掌握它。更多的用法可以参考官方文档

    相关文章

      网友评论

      • 9a1c0597a748:我们现在也在开发小程序,想请教大佬,网上大多数都是第一种方法,但是我比较认同您说的第二种情况,但是我在实际项目中的vuex中需要有好几个模块的js文件,每个js文件都是一个完整的state、mutations、actions、getters的结构,如何实现在任何一个组件中应用任何一个js文件呢?
        一斤代码:web单页应用中比较适合使用第一种方式,mpvue第二种更适合。

        你说的在任何一个组件中引用任何一个vuex的js文件,很简单啊,在要用的组件中直接import要的js就行了啊:

        import globalStore from "../../stores/global-store";
        import store1 from "../../stores/store1";
        import store2 from "../../stores/store2";

        然后在你的组件中就可以:

        globalStore.commit('......')

        store1.commit('......')
        store2.commit('......')

        store1.dispatch('......')
        store2.dispatch('......')

        理解了不?
      • d6f1ce838b5b:大佬,有没有tab标签的代码例子呢?初学者 想写个tab标签切换的
        一斤代码:@友善的糖果 这是vue动态组件功能,具体看官方文档吧:https://cn.vuejs.org/v2/guide/components-dynamic-async.html#ad
        d6f1ce838b5b:@一斤代码 我照着vue的例子写了下 不知道<component :is="currentTab"></component>这个怎么用 解释一下用法呗 简单的就好
        一斤代码:建议你用Vant Weapp、iView Weapp之类的组件库,里面有现成的tab组件
      • 工程设计:太厉害了
      • 尹大橙:hello, 一斤代码,你的文章很不错,我补充些内容后,想转到我博客去了,会附带此文出处,不知是否可以哈
        尹大橙:@一斤代码 谢谢哈
      • 嗯2018:哈哈哈 终于追上大神的脚步了, :smirk:
      • MrCrazy_514f:作为一名初涉小程序的vue开发者,这一系列文章真的大大鼓舞了信心,棒!
      • JsLin_:请问下 微信小程序底部导航 怎么实现 小红点 角标效果
        JsLin_:@一斤代码 谢谢
        一斤代码:可以使用wx.showTabBarRedDot
      • a401be6ff60e:写的太好了 让我避免了很多坑 棒
      • bommer洪:通俗易懂,非常棒
        一斤代码:@155e7f9f5552 https://github.com/zarknight,不过公开的项目里没有mpvue相关的东西
        155e7f9f5552:您好,你有公用的GitHub地址吗?可以看看学习一下

      本文标题:使用mpvue开发小程序教程(六)

      本文链接:https://www.haomeiwen.com/subject/unmzmftx.html