vuex 应用

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

 

State

用一个对象就包含了全部的应用层级状态.每个应用将仅仅包含一个.

例如:

state: {
    count:0,
    list:[],
    inputValue:'',
    nextId:5,
    viewkey:'all'
  },

mutations

 更改 Vuex 的 store 中的state(状态)的唯一方法是提交 mutation。(tips:不能直接修改state) ,Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数;也可以接收传入的额外的参数(例如:step)。

mutations: {
    handleadd(state,step){
      state.count += step
    },
    handlesub(state,step){
      state.count -= step
    }
}

 mutation 处理函数不能直接调用 。“当触发一个类型为handleadd 的 mutation 时,调用此函数。”要唤醒一个 mutation 处理函数,例如:在子组件的 methods 中:(当然你也可以向 store.commit 传入额外的参数 例如 ’3‘)

methods: {
        addClick(){
            // commit 的作用就是触发调用 mutation 中的函数
            this.$store.commit('handleadd', 3)
        },
}

注:mutation 必须是同步函数 ,处理异步操作在 actions 中

actions

Action 提交的是 mutation,而不是直接变更状态。

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,例如:

// actions 中可以执行异步操作
actions: {
    add(context,step) {
      setTimeout( () => {
        context.commit("handleadd",step)
      },2000)
    },
    sub(context,step) {
      setTimeout( () => {
        context.commit('handlesub',step)
      },2000)
    },
}

Action 通过 store.dispatch 方法触发:

methods: {
    // 异步
    addClickN() {
    // dispatch 的作用就是触发调用 action 中的函数
    this.$store.dispatch('add',10)
     }
}

在 action 内部执行异步操作: 

// actions 中可以执行异步操作
actions: {
    // 例如获取数据
    getList(context) {
      axios.get('list.json').then( (data) => {
        context.commit('initList',data.data)
      })
    }
}

modules

每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = createStore({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象。 

getters

有时候我们需要从 store 中的 state 中派生出一些状态,Getter可以对Store中已有的数据加工处理之后形成新的数据,类似Vue的计算属性。Store中数据发生变化,Getter的数据也会跟着变化。

 例如:

getters:{
    showNumber (state) {
      return '当前最新的数量是:' + state.count + '。'
    },
}

案例:todolist

 本地数据源: list.json

[
  {
    "id": 0,
    "info": "Racing car sprays burning fuel into crowd.",
    "done": false
  },
  {
    "id": 1,
    "info": " Japanese princess to wed commoner.",
    "done": false
  },
  {
    "id": 2,
    "info": "Australian walks 100km after outback crash.",
    "done": false
  },
  {
    "id": 3,
    "info": "Man charged over missing wedding girl.",
    "done": false
  },
  {
    "id": 4,
    "info": "Los Angeles battles huge wildfires.",
    "done": false
  }
]

 store文件下>  index.js

import Vue from 'vue'
import Vuex from 'vuex'

import axios from 'axios'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    // 任务列表
    list:[],
    // 文本框内容
    inputValue:'',
    nextId:5,
    // 定义一个变量表示底部按钮状态:全部:all ; 未完成:undone ; 已完成:done
    viewkey:'all'
  },
  // mutations 中不能执行异步操作
  mutations: {
       initList(state,list){
      state.list = list
    },
    setinputval(state,val){
      state.inputValue = val
    },
    additem(state){
      const obj ={
        id:state.nextId,
        info:state.inputValue.trim(),
        done:false
      }
      state.list.push(obj)
      state.nextId++
      state.inputValue = ''
    },
    removeitem(state,id){
      const i = state.list.findIndex(x => x.id === id)
      if(i !== -1){
        state.list.splice(i,1)
      }
    },
    // 改变某项任务的 done 的状态
    changestatus(state,param){
      const i = state.list.findIndex(x => x.id === param.id)
      if(i !== -1){
        state.list[i].done = param.status
      }
    },
    // 把已经完成的任务过滤掉,返回剩下未完成任务列表
    cleandone(state){
      state.list = state.list.filter(x => x.done === false)
    },
    // 改变底部按钮的状态值
    changeviewkey(state,key){
    state.viewkey = key
    }
  },

  // actions 中可以执行异步操作
  actions: {
    getList(context) {
      axios.get('../list.json').then( (data) => {
        console.log(data.data)
        context.commit('initList',data.data)
      })
    }
  },
  modules: {
  },
  /*
  Getter可以对Store中已有的数据加工处理之后形成新的数据,类似Vue的计算属性。
  Store中数据发生变化,Getter的数据也会跟着变化。
  */
  getters:{
    showNumber (state) {
      return '当前最新的数量是:' + state.count + '。'
    },
    // 计算属性统计剩余条数
    undone(state){
      return state.list.filter(x => x.done === false).length
    },
    // 列表切换
    infolist(state){
      if(state.viewkey ==='all'){
        return state.list
      }
      if(state.viewkey === 'undone'){
        return state.list.filter(x => !x.done)
      }
      if(state.viewkey === 'done'){
        return state.list.filter(x => x.done)
      }
      return state.list
    }
  }
})

example.vue

<template>
  <div id="app">
    <a-input placeholder="请输入任务" class="my_ipt" 
    :value="inputValue" @change="handleinutchange" />
    <a-button type="primary" @click="additemtolist">添加事项</a-button>

    <a-list bordered :dataSource="infolist" class="dt_list">
      <a-list-item slot="renderItem" slot-scope="item">
        <!-- 复选框 -->
        <!-- item.done 为 true 时,checkedbox 为选中状态 item.done 为 false 时,checkedbox 为未选中状态 -->
        <a-checkbox :checked = "item.done" @change="(e) => {checkchange(e,item.id)}">{{ item.info }}</a-checkbox>
        <!-- 删除链接 -->
        <a slot="actions" @click="removeitemid(item.id)">删除</a>
      </a-list-item>

      <!-- footer区域 -->
      <div class="footer" slot="footer">
        <span>{{undone}}条剩余</span>
        <a-button-group>
          <a-button :type=" viewkey === 'all' ? 'primary' : 'default' "  @click="changelist('all')">全部</a-button>
          <a-button :type="viewkey === 'undone' ? 'primary' : 'default' " @click="changelist('undone')">未完成</a-button>
          <a-button :type="viewkey === 'done' ? 'primary' : 'default'  " @click="changelist('done')">已完成</a-button>
        </a-button-group>
        <a @click="clean">清除已完成</a>
      </div>
    </a-list>
  </div>
</template>
<script>
import {mapState,mapGetters} from 'vuex'
export default {
  name: "app",
  data() {
    return {}
  },
  created () {
      this.$store.dispatch("getList")
  },
  computed: {
      ...mapState(['inputValue','viewkey']),
      ...mapGetters(['undone','infolist'])
  },
  methods: {
      // 监听文本框输入变化
      handleinutchange(e){
        //   console.log(e.target.value)
          this.$store.commit('setinputval',e.target.value)
      },
      additemtolist(){
          if(this.inputValue.trim().length <= 0){
              return this.$message.warning('文本框内容不能为空')
          }

          this.$store.commit('additem')
      },
      removeitemid(id){
          console.log(id)
          this.$store.commit('removeitem',id)
      },
      checkchange(e,id){
          console.log(e.target.checked,id)
          const param = {
              id:id,
              status:e.target.checked
          }
          this.$store.commit('changestatus',param)
      },
     clean(){
         this.$store.commit('cleandone')
     } ,
     changelist(key){
         console.log(key)
         this.$store.commit('changeviewkey',key)
     }
    }
};
</script>
<style scoped>
#app {
  padding: 10px;
}
.my_ipt {
  width: 500px;
  margin-right: 10px;
}
.dt_list {
  width: 500px;
  margin-top: 10px;
}
.footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
</style>

需要用到的外部组件 ant-design-vue 这个需要安装。然后导入

import Antd from '../node_modules/ant-design-vue'

import '../node_modules/ant-design-vue/dist/antd.css'

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值