美文网首页
10.VueX和Vue devtools

10.VueX和Vue devtools

作者: 小二的学习日记 | 来源:发表于2020-07-07 17:22 被阅读0次

    在事件总线的例子中,我们实现了进入detail页面不显示下面的tabbar,在离开detail页面中,显示tabbar这样的效果。我们使用的是事件总线的事件订阅机制。
    在这个例子中,我们用VueX状态管理来更好的实现一下这样的功能。
    1.编写VueX状态管理文件

    //===>src/store/index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        //自定义的共享状态
        isTabbarShow: true
      },
      mutations: {
        HideMaizuoTabbar(state, data) {
          state.isTabbarShow = data
        }
      },
      actions: {
      },
      modules: {
      }
    })
    

    2.来看一下src/main.js
    在这个文件中,store是之前为我们定义好的。程序加载之后,store就在全局挂载了,所以我们就可以直接去使用它

    //===>src/main.js
    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    
    Vue.config.productionTip = false
    
    new Vue({
      router,
      store,
      render: h => h(App)
    }).$mount('#app')
    

    3.重写Detail的beforeMount()和beforeDestroy()方法,修改状态。

    ...
    beforeMount() {
        // bus.$emit("maizuo", false);
        this.$store.commit("HideMaizuoTabbar", false);
      }
    ...
     beforeDestroy() {
        // bus.$emit("maizuo", true);
        this.$store.commit("HideMaizuoTabbar", true);
      }
    ...
    

    为了更好的观察store的变化,保护状态不被随便改动。我们不能直接修改store中的state。所以,我们要使用mutations帮我们修改。
    在第三步我们修改beforeMount()方法的时候,我们使用了this.$store.commit("HideMaizuoTabbar", false);这样的方法,HideMaizuoTabbar会找到我们在第一步mutations中定义好的同名方法,然后通过参数去修改state中的isTabbarShow

    devtools

    使用mutations修改数据的好处是,我们可以在devtools插件中观察到state的数据变化。


    image.png

    异步

    我们想实现,在正在热映和即将上映之间切换的时候,如果有缓存数据,就直接用缓存数据,这该怎么弄呢?

    image.png
    实现原理:
    判断store中有没有nowplaying数据。没有->ajax(action->mutation->state);有->直接从store取数据,渲染页面
    1.首先编写Comingsoon.vue
    //===>src/views/Film/Comingsoon.vue
    <template>
      <div>
        <ul>
          <li v-for="data in $store.state.comingList" :key="data.filmId">
            <img :src="data.poster" />
            <h3>{{data.name}}</h3>
            <p>观众评分{{data.grade}}</p>
            <p>主演:{{data.actors |actorfilter}}</p>
          </li>
        </ul>
      </div>
    </template>
    <script>
    export default {
      mounted() {
        if (this.$store.state.comingList.length === 0) {
          this.$store.dispatch("getComingListAction");
        } else {
          console.log("使用缓存数据");
        }
      }
    };
    </script>
    <style lang="scss" scoped>
    ul {
      li {
        padding: 10px;
        overflow: hidden;
        img {
          float: left;
          width: 100px;
        }
      }
    }
    </style>
    

    2.修改store文件

    //===>src/store/index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    import axios from 'axios'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        //自定义的共享状态
        isTabbarShow: true,
        comingList: []
      },
      mutations: {
        HideMaizuoTabbar(state, data) {
          state.isTabbarShow = data
        },
        commingListMutation(state, data) {
          state.comingList = data;
        }
      },
      actions: {
        // 异步处理
        getComingListAction(store) {
          axios({
            url: 'https://m.maizuo.com/gateway?cityId=120100&pageNum=1&pageSize=10&type=2&k=8283002',
            headers: {
              'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.0.4","e":"159065562332628866547713"}',
              'X-Host': 'mall.film-ticket.film.list'
            }
          }).then(res => {
            console.log(res.data);
            store.commit('commingListMutation', res.data.data.films)
          })
        }
      },
      modules: {
      }
    })
    
    第二次点击的确使用缓存加载的

    我们点击进入Comingsoon组件,在mounted()生命周期函数中,判断store中的comingList有没有数据。有数据就直接用,没有数据的话,我们通过this.$store.dispatch("getComingListAction");来分发名字为getComingListAction的action。这个时候,会执行第二步中actions的定义的同名方法,异步调接口获取数据。获取到数据之后,我们再用mutations来更新数据。这个时候,第一步的$store.state.comingList就改变了。

    mapState

    mapState可以很方便的获取store中state里面的属性值,配合computed()计算属性使用,具体用法是:

    回忆一下之前的这个属性
    1.修改App.vue
    //===>src/App.vue
    <template>
      <div>
        <tabbar v-show="isTabbarShow" />
        ...
      </div>
    </template>
    
    <script>
    ...
    import { mapState } from "vuex";
    export default {
    ...
      computed: {
        ...mapState(["isTabbarShow"])
      }
    };
    </script>
    
    <style lang="scss">
    ...
    </style>
    

    此时,效果会和之前的一样。

    getters

    我们要实现,从接口获取到了很多条数据,但只想显示三条。这个功能使用store该怎么做呢?
    1.在store文件中添加getters方法

    //===>src/store/index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    import axios from 'axios'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        //自定义的共享状态
        isTabbarShow: true,
        comingList: []
      },
      getters: {
        comingListGetter(state) {
          return state.comingList.filter((item, index) => index < 3)
        }
      },
      mutations: {
        HideMaizuoTabbar(state, data) {
          state.isTabbarShow = data
        },
        commingListMutation(state, data) {
          state.comingList = data;
        }
      },
      actions: {
        // 异步处理
        getComingListAction(store) {
          axios({
            url: 'https://m.maizuo.com/gateway?cityId=120100&pageNum=1&pageSize=10&type=2&k=8283002',
            headers: {
              'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.0.4","e":"159065562332628866547713"}',
              'X-Host': 'mall.film-ticket.film.list'
            }
          }).then(res => {
            console.log(res.data);
            store.commit('commingListMutation', res.data.data.films)
          })
        }
      },
      modules: {
      }
    })
    

    2.在需要接受数据的地方,使用store中提供的getters方法

    <template>
      <div>
        <ul>
          <li v-for="data in $store.getters.comingListGetter" :key="data.filmId">
            ...
          </li>
        </ul>
      </div>
    </template>
    <script>
    ...
    </script>
    <style lang="scss" scoped>
    ...
    </style>
    

    效果就不展示了,因为疫情期间电影数据列表的内容不足三条。

    mutation常量风格

    1.新建mutation常量

    //===>src/type/index.js
    export const HIDE_TABBAR_MUTATION = 'hide'
    export const SHOW_TABBAR_MUTATION = 'show'
    

    2.在store中引入常量

    //===>src/store/index.js
    ...
    import { HIDE_TABBAR_MUTATION, SHOW_TABBAR_MUTATION } from '@/type'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
       ...
      },
      getters: {
        ...
      },
      mutations: {
        // HideMaizuoTabbar(state, data) {
        //   state.isTabbarShow = data
        // },
        [HIDE_TABBAR_MUTATION](state, data) {
          state.isTabbarShow = data
        },
        commingListMutation(state, data) {
          state.comingList = data;
        }
      },
      actions: {
       ...
      },
      modules: {
      }
    })
    

    3.修改Detail页面,时期使用常量风格的mutation

    //===>src/views/Film/Detail.vue
    <template>
     ...
    </template>
    <script>
    ...
    import { HIDE_TABBAR_MUTATION, SHOW_TABBAR_MUTATION } from '@/type'
    
    export default {
     ...
      beforeMount() {
        // bus.$emit("maizuo", false);
        this.$store.commit(HIDE_TABBAR_MUTATION, false);
      },
     ...
      beforeDestroy() {
        // bus.$emit("maizuo", true);
        this.$store.commit(HIDE_TABBAR_MUTATION, true);
      },
     ...
    };
    </script>
    <style lang="scss" scoped>
    ...
    </style>
    

    VueX总结

    (1)应用层级的状态应该集中到单个store对象中。
    (2)提交mutation是更改状态的唯一方法,并且这个过程是同步的。
    (3)异步逻辑都应该封装到action里面。

    相关文章

      网友评论

          本文标题:10.VueX和Vue devtools

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