美文网首页
Vue 高级-Vuex

Vue 高级-Vuex

作者: 倪灏 | 来源:发表于2020-07-14 10:01 被阅读0次

    介绍

    vuex是一种状态管理模式,它保存着组件的公用的状态,并且以相应的规则保证状态变化。

    vuex的核心就是一个store,它相当于是一个容器,里面包含有state,action,mutation,getter,modules。

    • state:用于数据的存储,是store中的唯一数据源

    • getters:如vue中的计算属性一样,基于state数据的二次包装,常用于数据的筛选和多个数据的相关性计算

    • mutation:类似函数,改变state数据的唯一途径,且不能用于处理异步事件

    • action:类似于mutation,用于提交mutation来改变状态,而不直接变更状态,可以包含任意异步操作

    • modules:类似于命名空间,用于项目中将各个模块的状态分开定义和操作,便于维护

    特点

    • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

    • 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

    • vuex是单一状态树

    vuex的流程

    image.png

    vuex的整体流程是:

    1. 在组件内部,通过dispatch来分发action。

    2. 再通过action来第调用mutation

    3. 进而触发mutation内部的commit来修改state

    4. 最后state改变,导致页面重新render。

    使用

    vuex的使用场景

    • 大型应用中,用于全局共享的data,例如全局消息提醒、控件权限控制等等。

    • vuex可配合sessionStorage做用户基本信息的持久化存储。

    • 多级组件的数据需要共享或多个页面之间的数据存在因果关系时,可以使用vuex。

    在state中定义了count、userInfo、students三个属性,state里面的数据状态可以在全局中被访问,在任意组件中通过this.$store.state.attrName访问,在demo.vue的computed属性里面,我们获取了以上三个属性

    getter中可以自定义一些函数对state属性里面的数据进行过滤,并且在任意组件中可以通过this.$store.gettter.functionName的方式获取

    mutaions用来更新state里面的状态,我们可以定义一些方法对数据进行操作,在里面的方法中至少有state和value两个参数,state就是上面所说的state对象(属性),value就是从组件传递来的值。可以看到,在demo.vue中点击加号按钮或者减号按钮,通过this.$store.commit('getUserInfo',count的方式向vuex提交了一个事件,在store.js中mutaions里面的updateCount将提交过值接收并进行处理,state里面的count状态被更新,这是demo组件的computed属性中的number被执行,然后紧接着dom被更新。

    actions也是对state状态进行更新,但是是间接的,一些异步的操作先交给actions里面的函数执行,拿到结果后在交给mutaions中相应的处理函数处理,接下来的操作就跟上面讲的一样。 点击获取用户信息按钮,通过this.$store.dispatch('getUserInfo',this)向vuex提交了一个事件,store.js中actions的getUserInfo函数处理了这个事件,向本地一个user.json文件发了一个异步请求,难道结果后将返回的用户信息交给了mutaions的getUserInfo函数处理,state的userInfo属性被改变,userInfo的变化导致demo.vue中computed属性的userInfo被执行,接着dom更新,用户信息被显示。

    代码如下:

    // store/store.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)
    
    export default new Vuex.Store({
        state:{
            count:0,
            userInfo:{},
            students:[]
        },
        getters:{
          
        },
        mutations:{
            updateCount(state,count){
                state.count = count
            },
            getUserInfo(state,userInfo){
                state.userInfo = userInfo
            },
            getStudents(state,students){
                state.students = students
            }
        },
        actions:{
            updateCountAsync({commit,state},count){
                setTimeout(function() {
                    console.log('count:'+count)
                    commit('updateCount',count)
                }, 1000);
            },
            getUserInfo({commit,state},_this){
                let _vm = _this
                console.log(_vm)
                _vm.$http.get('http://localhost:8080/static/data/user.json').then(res=>{
                    console.log(res)
                    commit('getUserInfo',res.data)
                })
            },
            getStudents({commit,state},_this){
                let _vm = _this
                _vm.$http.get('/api/students').then(res=>{
                    console.log(res)
                    commit('getStudents',res.data.data.students)
                })
            }
        }
    })
    
    // demo.vue
    <template>
      <div class="hello">
        <h1>{{ msg }}</h1>
          
        <div class="number-box" style="margin:20px 0;">
          <button @click="plus">加 一</button>
          <input type="text" v-model="number" style="padding-left:20px;">
          <button @click="minus">减 一</button>
        </div>
    
        <button @click="getUserInfo">获取用户信息</button>
        <div class="user-info" v-if="userInfo">
          <span class="name" >{{userInfo.name}}</span>
          <span class="gender" >{{userInfo.gender}}</span>
          <span class="age">{{userInfo.age}}</span>
        </div>
        
        <button @click="getStudentList">获取成绩榜单</button>
        <div v-if="students.length>0">
          <h4 >成绩榜单</h4>
          <ul>
            <li v-for="item in students" :key="item.id">
              <span>{{item.name}}</span>
              <span>{{item.score}}</span>
            </li>
          </ul>
        </div>
      </div>
    </template>
    
    <style>
    
    </style>
    
    <script>
    export default {
      name: 'HelloWorld',
      data () {
        return {
          msg: 'Welcome to Your Vue.js App'
        }
      },
      mounted() {
        
      },
      computed:{
        number(){
          return this.$store.state.count
        },
        userInfo(){
          return this.$store.state.userInfo
        },
        students(){
          return this.$store.state.students
        }
      },
      methods:{
        plus(){
          // this.number++
          let count = Number(this.number)+1
          console.log('plus:'+count)
          this.$store.dispatch('updateCountAsync',count)
        },
        minus(){
          // this.number--
          let count = Number(this.number)-1
          console.log('minus:'+count)
          this.$store.dispatch('updateCountAsync',count)
        },
        getUserInfo(){
          this.$store.dispatch('getUserInfo',this)
        },
        getStudentList(){
          this.$store.dispatch('getStudents',this)
        }
      }
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    h1, h2 {
      font-weight: normal;
    }
    ul {
      list-style-type: none;
      padding: 0;
    }
    li {
      display: inline-block;
      margin: 0 10px;
    }
    a {
      color: #42b983;
    }
    .user-info{
      margin-top:20px;
      margin-bottom:20px;
    }
    .name{
      color:blue;margin-right:20px
    }
    .gender{
      color:red;margin-right:20px
    }
    .age{
      color:blue;margin-right:20px
    }
    </style>
    

    相关文章

      网友评论

          本文标题:Vue 高级-Vuex

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