Vuex从入门到实战(二)

4.基于vuex的案例——todos任务记录工具

4.1我们重新初始化一个vue-cli项目,配置时别忘了选中Vuex配置。

4.2我们还要安装几个依赖:axios和ant-design-vue(ant-designUI组件库,也可以不使用或者使用其他擅长的组件库)

npm install axios ant-design-vue -S

4.3在mian.js中引入ant-design和ant-design的样式文件

import Vue from 'vue'
import App from './App.vue'
import store from './store'
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css'

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

new Vue({
  store,
  render: h => h(App)
}).$mount('#app')

4.4实现基本布局






4.5在public路径下新增一个list.json文件进行数据存储,并且将我们在App.vue中list里面的数据放到这里。

[
  {
    "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 
  }
]

我们的目的是通过请求这个json文件,来控制我们这个任务列表的内容。

4.6通过axios请求获取到list.json中的数据

在store路径下的index.js文件中引入axios,并且进行异步请求,我们需要将请求到的数据挂载到state中的list数组中,但是由于挂载数据只能在mutation中进行,所以我们要在mutation中声明一个方法,将获取到的数据挂载到list中。在actions中的getList方法获取到数据后,调用mutation中的initList方法,将数据传递给list。

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    list: []
  },
  mutations: {
    initList (state, list) {
      state.list = list
    }
  },
  actions: {
    getList (context) {
      axios.get('/list.json').then(({ data }) => {
        context.commit('initList', data)
      })
    }
  },
  modules: {
  }
})

4.7在App.vue引入state中的list变量,我们通过引入mapState,在computed属性中展开获取。

import { mapState } from 'vuex'

computed: {
    ...mapState(['list'])
},

4.8输入值的双向绑定

在state中定义一个inputValue属性,默认值为空,存放文本框输入的信息。

并且在App.vue中获取到这个属性后,绑定在标签上。并且给文本框绑定一个change方法,监听input组件值的变化,将这个值传递给state中的inputValue。

在motation中定义一个接收inputValue的方法:

    setInputValue (state, value) {
      state.inputValue = value
    }

在App.vue中定义handlInputChange方法:

  methods: {
    handlInputChange (e) {
      this.$store.commit('setInputValue', e.target.value)
    }
  }

4.9 给各个组件绑定事件

4.9.1给添加事项按钮绑定点击事件

在vuex中的state数据中定义nextId属性,用于存放下一项数据的id(添加项的id)

在vuex中定义addItem方法,将id,info(输入内容,trim去除空格),done(是否完成的标识,默认为false未完成)添加到一个对象内;将这个对象push到state属性的list中,并且将nextId数值加一,并且清空inputValue(清空输入框)。

    addItem (state) {
      const obj = {
        id: state.nextId,
        info: state.inputValue.trim(),
        done: false
      }
      state.list.push(obj)
      state.nextId++
      state.inputValue = ''
    },

在App.vue中定义一个向列表中新增item项的方法,并且将这个方法绑定给“添加事项”按钮,方法首先判断输入内容是否为空,如果为空则进行提示,不为空则调用vuex中的addItem方法:

    addItemToList () {
      if (this.inputValue.trim().length <= 0) {
        return this.$notification.open({
          message: '文本框内容不能为空!',
          type: 'warning'
        })
      }
      this.$store.commit('addItem')
    },

4.9.2给删除按钮绑定点击事件

在vuex中定义removeItem方法,根据调用该方法时传入的id查找到对应id的索引值,然后使用splice方法将该索引的项删除。

    removeItem (state, id) {
      // 1.根据id查找对应项索引
      const index = state.list.findIndex(i => i.id === id)
      // 2.根据索引删除对应项
      if (index !== -1) {
        state.list.splice(index, 1)
      }
    },

在App.vue中定义一个向列表中删除item项的方法,并且将这个方法绑定给“删除”按钮,并且将checkbox的id传递给方法,removeItemById方法调用removeIitem方法,将id传入,删除选中项。

    removeItemById (id) {
      this.$store.commit('removeItem', id)
    },

4.9.3给checkbox绑定点击事件

checkbox的点击事件是改变list中选中项的done属性,和删除一样,传入id值后查找索引,如果索引值存在,则改变该项的done属性。

    changeDone (state, id) {
      const index = state.list.findIndex(i => i.id === id)
      if (index !== -1) {
        state.list[index].done = !state.list[index].done
      }
    },

在App.vue中定义changeDoneById方法,并且将这个方法绑定给checkbox,并且将checkbox的id传递给方法,changeDoneById方法调用changeDone方法,将id传入,改变选中项状态。

    changeDoneById (id) {
      this.$store.commit('changeDone', id)
    },

4.9.4给状态选择按钮绑定点击事件

项目底部的状态选择框在点击后需要切换样式,并且获取对应的item项,我们献给这些按钮绑定事件和样式。绑定事件时,将对应的状态传给方法,绑定type时进行判断,如果为当前选中的type,则以primary样式展示,否则以默认样式展示:

        
          全部
          未完成
          已完成
        

上面我们用了viewKey判断样式,所以我们需要在vuex的state中定义viewKey,并且定义ChangeList点击事件:

  state: {
    viewKey: 'undone'
  },  
  changeViewKey (state, key) {
      state.viewKey = key
    }
  },

并且在getters中判断viewKey,如果viewKey为all,返回list;如果viewKey为undone,返回done为false的list;如果viewKey为done,返回done值为true的list:

   infoList (state) {
      if (state.viewKey === 'all') {
        return state.list
      } else if (state.viewKey === 'undone') {
        return state.list.filter(x => x.done === false)
      } else if (state.viewKey === 'done') {
        return state.list.filter(x => x.done === true)
      } else {
        return state.list
      }
    }

同样,在App.vue中定义ChangeList方法,调用changeViewKey方法,并且返回key值即可

    ChangeList (key) {
      this.$store.commit('changeViewKey', key)
    }

4.9.5给清除已完成按钮绑定点击事件

清除已完成是将done属性为done的项删除,我们在vuex中定义cleanDone方法,将过滤后的list赋值给原来的list即可:

    cleanDone (state) {
      state.list = state.list.filter(x => x.done === false)
    },

在App.vue中定义clean方法调用该cleanDone方法,并且绑定给清除已完成按钮:

    clean () {
      this.$store.commit('cleanDone')
    },

-------------------------------------------------至此,vuex内容完结,附源代码---------------------------------------

github地址:https://github.com/weizhuren/VuexDemo.git

App.vue






vuex(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: {
    list: [],
    inputValue: '',
    // 下一个id
    nextId: 5,
    viewKey: 'undone'
  },
  mutations: {
    initList (state, list) {
      state.list = list
    },
    setInputValue (state, value) {
      state.inputValue = value
    },
    // 添加项目列表
    addItem (state) {
      const obj = {
        id: state.nextId,
        info: state.inputValue.trim(),
        done: false
      }
      state.list.push(obj)
      state.nextId++
      state.inputValue = ''
    },
    // 根据id删除对应任务事项
    removeItem (state, id) {
      // 1.根据id查找对应项索引
      const index = state.list.findIndex(i => i.id === id)
      // 2.根据索引删除对应项
      if (index !== -1) {
        state.list.splice(index, 1)
      }
    },
    changeDone (state, id) {
      const index = state.list.findIndex(i => i.id === id)
      if (index !== -1) {
        state.list[index].done = !state.list[index].done
      }
    },
    // 清除已完成的任务
    cleanDone (state) {
      state.list = state.list.filter(x => x.done === false)
    },
    // 修改页面上展示列表数据
    changeViewKey (state, key) {
      state.viewKey = key
    }
  },
  actions: {
    getList (context) {
      axios.get('/list.json').then(({ data }) => {
        context.commit('initList', data)
      })
    }
  },
  getters: {
    // 统计未完成的任务条数
    unDoneLength (state) {
      return state.list.filter(x => x.done === false).length
    },
    infoList (state) {
      if (state.viewKey === 'all') {
        return state.list
      } else if (state.viewKey === 'undone') {
        return state.list.filter(x => x.done === false)
      } else if (state.viewKey === 'done') {
        return state.list.filter(x => x.done === true)
      } else {
        return state.list
      }
    }
  }
})

 

你可能感兴趣的:(vue)