美文网首页
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