zoukankan      html  css  js  c++  java
  • 使用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请求的地址

  • 相关阅读:
    WPF MarkupExtension
    WPF Binding小数,文本框不能输入小数点的问题
    WPF UnhandledException阻止程序奔溃
    .Net Core的总结
    C#单元测试
    Csla One or more properties are not registered for this type
    unomp 矿池运行问题随记
    矿池负载运行监测记录
    MySql 数据库移植记录
    后台服务运行后无故停止运行,原因不明
  • 原文地址:https://www.cnblogs.com/mmzuo-798/p/9450990.html
Copyright © 2011-2022 走看看