使用Vuex心得

之前一直都是看别人写的vuex感觉还挺好理解的,今天自己根据需求写了下vuex,一下子不知道怎么写了,

想要用好vuex还是先要知道原理:

参考好博客写的非常到位:https://www.cnblogs.com/DM428/p/7293867.html

基本组成:

       注意到这个store对象包含三个子对象:

     state、mutations、actions

      其中state用于存储数据,类似vue实例的data属性。

       mutations用于递交更改,对state对象中的属性数据进行更改。

      actions用于进行递交异步更改,通过调用mutations实现对数据的更改。

actions与mutations的区别:

      其中actions区别于mutations的地方在于mutations只能进行同步更改,而actions中的更改可以是异步执行。所以基本上所有用户执行的直接数据更改都是触发mutations属性

      函数执行,而需要与后端进行数据交互的数据更改通常是通过actions属性函数去执行。

定义actions与mutations属性函数的注意事项:

      其中定义mutations属性函数时必须传递的第一个参数是state,因为要对state进行更改,第二个参数代表传入的新参数。mutations属性函数只接受两个参数,如果要同时更改多个属性值,可以通过对象传入。

        在actions属性函数中可以通过context.commit()方法触发mutations属性函数。定义actions属性函数时,必须传递的第一个参数是context,用于触发mutations函数。

触发actions与mutations属性函数的方法:

    在子组件中通过this.$store.commit()方法触发mutations属性函数。在注册store的Vue实例中(第三步中将会讲到)可以通过store.commit()触发。

    commit函数第一个参数是mutations的属性函数名,第二个参数是传入的新值。

    actions属性函数中可以进行异步操作,比如通过ajax或者Vue.Resource()进行数据获取,获取数据后再通过context.commit()触发更改。

     触发actions属性函数使用this.$store.dispatch()或者store.dispatch() (在注册store的Vue实例中)函数。dispatch函数传递的一个参数是actions属性函数名称。如果希望在

    Vue实例创建完成还未挂载时就从后端获取数据,则可以在created钩子函数中调用actions属性函数。

在组件中访问数据中心state的注意事项:

    在Vue实例中可以通过this.$store.state对象获取state中的数据。如果希望在state中的数据发生更改之后,组件会自动更新,则应该使用组件的computed属性定义数据,而

    不是通过data属性定义。如果使用data定义组件数据,则state中的数据发生更改之后组件不会发生变化。

练习:vuex+父子组件间通信

项目目录:

页面组件:AppFilm.vue

<template>
  <div class="app-film">
    <AppFilmNav></AppFilmNav>
    <AppFilmBox></AppFilmBox> 
  </div>
</template>
<script>
import AppFilmNav from '@/components/AppFilmNav'
import AppFilmBox from '@/components/AppFilmBox'
export default {
  name: 'app-film',
  components:{AppFilmNav,AppFilmBox},
  data () {
    return {
    }
  },
  computed:{
    
 }
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.app-film{
  height: 0.5rem;
}
</style>

AppFilmBox:

<template>
  <div class="app-film-box">
    <AppFilmItem  :film="film" v-for="(film,index) in films" :key="index"></AppFilmItem>   /// :film 绑定数据传递给子组件
    <!--{{ infor }}-->
   </div>
</template>
<script>
import axios from 'axios'
import AppFilmItem from './AppFilmItem'
export default {
  // props:['infor'],
  name: 'app-film-box',
  components:{AppFilmItem},
  data () {
    return {
      // films:[]
    }
  },
  // 必须通过computed属性使用state数据!否则state属性中的数据发生更改时不会反映在组件上! computed: { films(){
return this.$store.state.film } }, methods: { getfilms(){ let that = this; this.$store.dispatch('Toggle',this.$store.state.posturl); } }, created(){ this.getfilms() } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style> .app-film-box{ padding:0 15px; } </style>

appFilmItem.vue

<template>
  <div class="app-film-item">
    <img  :src="film.poster" alt="">
    <div class="info">
        <h5>{{film.name}}</h5>
        <p class="for">{{film.intro}}</p>
        <p class="for1">{{film.cinemaCount}}家影院上映<i>{{film.watchCount}}人购票</i></p>
    </div>
    <div class="other">
        <div class="range">8.5</div>
        <i class="fa fa-angle-right"></i>
    </div>
         
  </div>
</template>
<script>
export default {
  name:'app-film-item',
  props:['film'], // 从父组件那里接受数据 film
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss">
body{
  background-color:#f9f9f9;
}
.app-film-item{
  // padding-left: 20px;
  // margin-top: -0.3rem;
  display: flex;
  align-items: center;
  padding-bottom: 28px;
  border-bottom: 1px solid #ccc;
  padding-top: 25px;
  img{
    width:0.6rem;
  }
  .info{
    padding-left: 15px;
    display: inline-block;
    width: 75%;
    h5{
      font-size: 16px;
      line-height: 32px;
      color: #000;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .for{
      height: 24px;
      line-height: 24px;
      color: #8e8e8e;
      font-size: 14px;
      overflow: hidden;
      text-overflow: ellipsis;
      width: 100%;
      display: inline-block;
    }
    .for1{
      line-height: 24px;
      color: #8e8e8e;
      font-size: 12px;
      i{
        margin-left: 15px;
      }
    }
      
  }
}
.other{
  display: flex;
  justify-content: space-between;
  margin-right: 0.2rem;
  margin-bottom:0.5rem;
  .range{
    font-size: 16px;
    line-height: 32px;
    color: #fc7103;
  }
  i{
    padding-left: 5px;
    line-height: 29px;
    color: #c6c6c6;
  }
}
</style>

AppFilmNav.vue

<template>
  <div class="app-film-nav">
    <div  class="now_playing" @touchend.stop.prevent="toggle(0)" :class="{active:active==0}">
        正在热映
    </div>
    <div  class="coming_soon" @touchend.stop.prevent="toggle(1)" :class="{active:active==1}">
        即将上映
    </div>
  </div>
</template>
<script>
export default {
  name:'app-film-nav',
  data () {
    return {
      active:0
    }
  },
  methods: {
    toggle (i) {
      this.active = i;
      this.$store.state.posturl = this.$store.state.urls[i].url;
      this.$store.dispatch('Toggle',this.$store.state.posturl);
    }
  }
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss" scoped>
.app-film-nav{
  height: 47px;
  margin: 0.5rem 15px 5px 15px;
  border-bottom: solid #fe6e00 1px;
  // padding-left: 15px;
  // padding-right:15px;
  .now_playing{
    float: left;
    width: 50%;
    height: 100%;
    text-align: center;
    font-size: 16px;
    line-height: 46px;
    // color: #6a6a6a;
    cursor: pointer;
  }
  .coming_soon{
    float: left;
    width: 50%;
    height: 100%;
    text-align: center;
    font-size: 16px;
    line-height: 46px;
    color: #6a6a6a;
    cursor: pointer;
  }
  .active{
    color: #fe6e00;
    border-bottom: solid;
  }
}
</style>

vuex写在main.js里

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex)
Vue.config.productionTip = false

const store = new Vuex.Store({
  state:{
    urls:[                      
      {title:'正在热映',url:'/static/mock/now-playing.json'},
      {title:'即将上映',url:'/static/mock/coming-soon.json'}
    ],
    posturl:'/static/mock/now-playing.json',
    film:''
  },
  mutations:{
    SET_FILM: (state, film) => {
      state.film = film
    }
  },
  actions: {
    Toggle: ({commit},url) => {
      return new Promise((resolve, reject) => {
        axios.get(url).then((res) => {     
          const data = res.data.data
          commit('SET_FILM', data)
          resolve()
        }).catch((err) => {
          reject(err)
        })
      })
    }
  }
})

/* eslint-disable no-new */
new Vue({
  el: '#app',
  store, // 根组件通过store选项将store实例注入所有地子组件
  created (){
    store.dispatch('Toggle',store.state.posturl);
  },
  router,
  components: { App },
  template: '<App/>'
})

// 上面的代码能够让子组件通过this.$store访问到store实例。

页面效果:

这里用Vuex来切换get请求的地址

猜你喜欢

转载自www.cnblogs.com/mmzuo-798/p/9450990.html
今日推荐