当前位置: 首页 > article >正文

一篇文章学懂Vuex

一、基于VueCli自定义创建项目

233

344

二、Vuex 初始准备

建项目的时候把vuex勾选上就不用再yarn add vuex@3了

store/index.js

// 这里面存放的就是vuex相关的核心代码
import Vuex from 'vuex'
import Vue from 'vue'

// 插件安装
Vue.use(Vuex)

// 创建仓库(空仓库)
const store = new Vuex.Store()

// 到处给main.js使用
export default store

App.vue

  created () {
    // console.log(this.$router) // 没配
    console.log(this.$store) // 没配
  },

main.js

import Vue from 'vue'
import App from './App.vue'
import store from '@/store/index'
console.log(store.state.count)

Vue.config.productionTip = false

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

三、通过vuex仓库访问数据

(1)通过store直接访问

 新建仓库数据,这样别的模块、组件都可以访问到仓库中的数据。

// 创建仓库(空仓库)
const store = new Vuex.Store({
  // 通过state可以提供数据,所有组件共享的数据
  state: {
    title: '大标题',
    count: 100
  }
}
)

例如,App.vue中的模块中(指的是template中)

    <h1>根组件
      --{{ $store.state.title }}
      --{{ $store.state.count }}
    </h1>

App.vue中的组件中(指的是script中) 

  created () {
    console.log(this.$store.state.count) // 没配
  },

Son.vue(模块template中) 

    从vuex中获取的值: <label>{{ $store.state.count }}</label>

main.js(js中)

console.log(store.state.count)

总结:只需要在App.vue中写好仓库,后面可以直接通过底层的逻辑去调用,即:

模板中:{{$store.state.xxx }}
组件逻辑中:this.$store.state.xxx
JS模块中:store.state.xxx

Son1.vue

<template>
  <div class="box">
    <h2>Son1 子组件 {{ $store.state.title }}</h2>
    从vuex中获取的值: <label>{{ $store.state.count }}</label>
    <br>
    <button>值 + 1</button>
  </div>
</template>

<script>
export default {
  name: 'Son1Com'
}
</script>

<style lang="css" scoped>
.box{
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

(2)通过辅助函数(简化)

mapState是辅助函数,帮助我们把store中的数据自动映射到组件的计算属性中

 App.vue

//展示一下 不用

import { mapState } from 'vuex'
console.log(mapState(['count', 'title']))

在App.vue中这么写,就可以直接调用使用里面的值

<template>
  <div id="app">
    <h1>根组件
      --{{ title }}
      --{{ count }}
    </h1>
    <input type="text">
    <Son1></Son1>
    <hr>
    <Son2></Son2>
  </div>
</template>

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

Son2.vue,虽然写起来简单还是需要再写一遍解构函数,即  computed: {
    ...mapState(['count', 'title'])
  }

<template>
  <div class="box">
    <h2>Son2 子组件 {{ title }}</h2>
    从vuex中获取的值:<label>{{ count }}</label>
    <br />
    <button>值 - 1</button>
  </div>
</template>

<script>
import { mapState } from 'vuex'
export default {
  name: 'Son2Com',
  computed: {
    ...mapState(['count', 'title'])
  }
}
</script>

<style lang="css" scoped>
.box {
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

四、组件修改仓库中的数据(mutations)

(1)错误情况

<template>
  <div class="box">
    <h2>Son1 子组件 {{ $store.state.title }}</h2>
    从vuex中获取的值: <label>{{ $store.state.count }}</label>
    <br>
    <button @click="handleAdd">值 + 1</button>
  </div>
</template>

<script>
export default {
  name: 'Son1Com',
  methods: {
    handleAdd () {
      // 错误代码,不会报错,并且可以实现,但其实是错的 (但是vue不会监测 监测需要成本)
      // this.$store.state.count++
      // console.log(this.$store.state.count)

      // 应该通过mutation 核心概念 进行修改
    }
  }
}
</script>

<style lang="css" scoped>
.box{
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

(2)严格模式 strict:true

为了避免这种情况,方便初学者检查,我们采用严格模式。store/index.js中操作

// 这里面存放的就是vuex相关的核心代码
import Vuex from 'vuex'
import Vue from 'vue'

// 插件安装
Vue.use(Vuex)

// 创建仓库(空仓库)
const store = new Vuex.Store({
  // 严格模式(有利于初学者,检测不规范的代码 => 上线时需要关闭)
  // 其实还是可以修改,只是会提示报错
  strict: true,
  // 通过state可以提供数据,所有组件共享的数据
  state: {
    title: '大标题',
    count: 100
  }
}
)

// 到处给main.js使用
export default store

(3)修改数据-mutations

 store/index.js

// 这里面存放的就是vuex相关的核心代码
import Vuex from 'vuex'
import Vue from 'vue'

// 插件安装
Vue.use(Vuex)

// 创建仓库(空仓库)
const store = new Vuex.Store({
  // 严格模式(有利于初学者,检测不规范的代码 => 上线时需要关闭)
  // 其实还是可以修改,只是会提示报错
  strict: true,
  // 1.通过state可以提供数据,所有组件共享的数据
  state: {
    title: '大标题',
    count: 100
  },

  // 2.通过mutations可以提供修改数据的方法,mutation是一个对象
  mutations: {
    //   所有的mutation函数,第一个参数,都是state
    addCount (state) {
      //   修改数据
      state.count += 1
    },
    addFive (state) {
      //   修改数据
      state.count += 5
    },
    changeTitle (state) {
      state.title = '小标题'
    }
  }

}
)

// 到处给main.js使用
export default store

Son1.vue

<template>
  <div class="box">
    <h2>Son1 子组件 {{ $store.state.title }}</h2>
    从vuex中获取的值: <label>{{ $store.state.count }}</label>
    <br>
    <button @click="handleAdd">值 + 1</button>
    <button @click="addFive">值 + 5</button>
    <button @click="changeFn">改标题</button>

  </div>
</template>

<script>
export default {
  name: 'Son1Com',
  methods: {
    handleAdd () {
      // 错误代码,不会报错,并且可以实现,但其实是错的 (但是vue不会监测 监测需要成本)
      // this.$store.state.count++
      // console.log(this.$store.state.count)

      // 应该通过mutation 核心概念 进行修改数据
      // 需要提交调用mutation
      this.$store.commit('addCount')
    },
    addFive () {
      this.$store.commit('addFive')
    },
    changeFn () {
      this.$store.commit('changeTitle')
    }
  }
}
</script>

<style lang="css" scoped>
.box{
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

(4)mutations传参

index.js

  // 2.通过mutations可以提供修改数据的方法,mutation是一个对象
  mutations: {
    //   所有的mutation函数,第一个参数,都是state
    // addCount (state) {
    //   //   修改数据
    //   state.count += 1
    // },
    addCount (state, n) {
      //   修改数据
      state.count += n
    },

    changeTitle (state, newTitle) {
      state.title = newTitle
    }
  }

Son.vue

<template>
  <div class="box">
    <h2>Son1 子组件 {{ $store.state.title }}</h2>
    从vuex中获取的值: <label>{{ $store.state.count }}</label>
    <br>
    <button @click="handleAdd(1)">值 + 1</button>
    <button @click="handleAdd(5)">值 + 5</button>
    <button @click="handleAdd(10)">值 + 10</button>
    <button @click="changeFn">改标题</button>

  </div>
</template>

<script>
export default {
  name: 'Son1Com',
  methods: {
    handleAdd (n) {
      // 错误代码,不会报错,并且可以实现,但其实是错的 (但是vue不会监测 监测需要成本)
      // this.$store.state.count++
      // console.log(this.$store.state.count)

      // 应该通过mutation 核心概念 进行修改数据
      // 需要提交调用mutation
      // this.$store.commit('addCount')
      this.$store.commit('addCount', n)
      console.log(n)
    },
    changeFn (newTitle) {
      this.$store.commit('changeTitle', '黑马程序员')
    }
  }
}
</script>

<style lang="css" scoped>
.box{
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

(5)mutations传多参

只能传递有且仅有一个参数,如果是想传递多个参数,可以写成对象数组的形式。

Son1.vue

<template>
  <div class="box">
    <h2>Son1 子组件 {{ $store.state.title }}</h2>
    从vuex中获取的值: <label>{{ $store.state.count }}</label>
    <br>
    <button @click="handleAdd(1)">值 + 1</button>
    <button @click="handleAdd(5)">值 + 5</button>
    <button @click="handleAdd(10)">值 + 10</button>
    <button @click="changeFn">改标题</button>

  </div>
</template>

<script>
export default {
  name: 'Son1Com',
  methods: {
    handleAdd (n) {
      // 错误代码,不会报错,并且可以实现,但其实是错的 (但是vue不会监测 监测需要成本)
      // this.$store.state.count++
      // console.log(this.$store.state.count)

      // 应该通过mutation 核心概念 进行修改数据
      // 需要提交调用mutation
      // this.$store.commit('addCount')
      // this.$store.commit('addCount', n)
      // 只能传递有且仅有一个参数,如果是想传递多个参数,可以写成对象数组的形式。
      this.$store.commit('addCount', {
        count: n,
        msg: '哈哈'
      })

      console.log(n)
    },
    changeFn (newTitle) {
      this.$store.commit('changeTitle', '黑马程序员')
    }

  }
}
</script>

<style lang="css" scoped>
.box{
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

index.js

  // 2.通过mutations可以提供修改数据的方法,mutation是一个对象
  mutations: {
    addCount (state, obj) {
      //   修改数据
      state.count += obj.count
    }
}
)

 (6)实时输入,实时更新

不能用:value 因为不能直接改变仓库的值,但是:value是由:value和@input组成,所以可以分开用

App.vue

<template>
  <div id="app">
    <h1>根组件
      --{{ title }}
      --{{ count }}
    </h1>
    <input type="text" :value="count" @input="handleInput">
    <Son1></Son1>
    <hr>
    <Son2></Son2>
  </div>
</template>

<script>
import { mapState } from 'vuex'
import Son1 from './components/Son1.vue'
import Son2 from './components/Son2.vue'

// console.log(mapState(['count', 'title']))

export default {
  name: 'app',
  data: function () {
    return {

    }
  },
  created () {
    // console.log(this.$router) // 没配
    // console.log(this.$store) // 没配
    // console.log(this.$store.state.count) // 没配
  },
  computed: {
    ...mapState(['count', 'title'])
  },
  components: {
    Son1,
    Son2
  },
  methods: {
    handleInput (e) {
      // 1.实时获取输入框的值
      // e.target指得是输入框  +是转化成数字类型
      const num = +e.target.value

      // 2.提交mutation,调用mutation函数
      this.$store.commit('changeCount', num)
    }
  }
}
</script>

<style>
#app {
  width: 600px;
  margin: 20px auto;
  border: 3px solid #ccc;
  border-radius: 3px;
  padding: 10px;
}
</style>

index.js

    changeCount (state, newCount) {
      state.count = newCount
    }

五、mapMutations(辅助函数)

 Son2.vue

<template>
  <div class="box">
    <h2>Son2 子组件 {{ title }}</h2>
    从vuex中获取的值:<label>{{ count }}</label>
    <br />
    <button @click="handleSub(1)">值 - 1</button>
    <button @click="handleSub(5)">值 - 5</button>
    <button @click="handleSub(10)">值 - 10</button>
<!-- 上面可以直接用subCount()了,都没必要封装了 -->
    <button @click="subCount(10)">值 - 10</button>
    <button @click="changeTitle('改了标题')">改标题</button>

  </div>
</template>

<script>
import { mapMutations, mapState } from 'vuex'
export default {
  name: 'Son2Com',
  computed: {
    ...mapState(['count', 'title'])
  },
  methods: {
    ...mapMutations(['subCount', 'changeTitle']),
    handleSub (n) {
      // this.$store.commit('subCount', n)
      this.subCount(n)
    }
  }
}
</script>

<style lang="css" scoped>
.box {
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

六、actions和getters

(1)actions和dispatch

目标:明确actions的基本用法,处理异步操作。

需求:一秒钟之后,修改state的count成666。

说明:mutations必须是同步的(便于检测数据变化,记录调试)

 index.js

// 这里面存放的就是vuex相关的核心代码
import Vuex from 'vuex'
import Vue from 'vue'

// 插件安装
Vue.use(Vuex)

// 创建仓库(空仓库)
const store = new Vuex.Store({
  // 严格模式(有利于初学者,检测不规范的代码 => 上线时需要关闭)
  // 其实还是可以修改,只是会提示报错
  strict: true,
  // 1.通过state可以提供数据,所有组件共享的数据
  state: {
    title: '大标题',
    count: 100
  },

  // 3.actions处理异步
  //   注意:不能直接操作state,操作state,还是需要commit mutation
  actions: {
    // context上下文(此处未分模块,可以当作store仓库)
    // context.commit('mutation名字',额外参数)
    changeCountAction (context, num) {
      //   这里是setTimeout模拟异步,以后大部分场景是发请求
      setTimeout(() => {
        context.commit('changeCount', num)
      }, 1000)
    }
  }
}

)

// 到处给main.js使用
export default store

Son1.vue

<template>
  <div class="box">
    <h2>Son1 子组件 {{ $store.state.title }}</h2>
    从vuex中获取的值: <label>{{ $store.state.count }}</label>
    <br>
    <button @click="handleAdd(1)">值 + 1</button>
    <button @click="handleAdd(5)">值 + 5</button>
    <button @click="handleAdd(10)">值 + 10</button>
    <button @click="handleChange(66)">疫苗后改为66</button>
    <button @click="changeFn">改标题</button>

  </div>
</template>

<script>
export default {
  name: 'Son1Com',
  methods: {
    handleAdd (n) {
      // 错误代码,不会报错,并且可以实现,但其实是错的 (但是vue不会监测 监测需要成本)
      // this.$store.state.count++
      // console.log(this.$store.state.count)

      // 应该通过mutation 核心概念 进行修改数据
      // 需要提交调用mutation
      // this.$store.commit('addCount')
      // this.$store.commit('addCount', n)
      // 只能传递有且仅有一个参数,如果是想传递多个参数,可以写成对象数组的形式。
      this.$store.commit('addCount', {
        count: n,
        msg: '哈哈'
      })

      // console.log(n)
    },
    changeFn (newTitle) {
      this.$store.commit('changeTitle', '黑马程序员')
    },
    handleSub (n) {
      this.$store.commit('subCount', n)
    },
    handleChange () {
      // 调用action
      // this.$store.dispatch('action名字',额外参数)
      this.$store.dispatch('changeCountAction', '666')
    }

  }
}
</script>

<style lang="css" scoped>
.box{
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

(2)辅助函数-mapActions

目标:掌握辅助函数mapActions,映射方法,这样可以简化dispatch

Son2.vue

<template>
  <div class="box">
    <h2>Son2 子组件 {{ title }}</h2>
    从vuex中获取的值:<label>{{ count }}</label>
    <br />
    <button @click="handleSub(1)">值 - 1</button>
    <button @click="handleSub(5)">值 - 5</button>
    <button @click="subCount(10)">值 - 10</button>
<!-- 上面可以直接用subCount()了,都没必要封装了 -->
    <button @click="subCount(10)">值 - 10</button>
    <button @click="changeTitle('改了标题')">改标题</button>
    <button @click="changeCountAction(888)">一秒后改成888</button>

  </div>
</template>

<script>
import { mapActions, mapMutations, mapState } from 'vuex'
export default {
  name: 'Son2Com',
  computed: {
    ...mapState(['count', 'title'])
  },
  methods: {
    ...mapMutations(['subCount', 'changeTitle']),
    handleSub (n) {
      // this.$store.commit('subCount', n)
      this.subCount(n)
    },
    ...mapActions(['changeCountAction'])

  }
}
</script>

<style lang="css" scoped>
.box {
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

(3)getters

也就是对仓库中的数据(state)进行操作

index.js

// 这里面存放的就是vuex相关的核心代码
import Vuex from 'vuex'
import Vue from 'vue'

// 插件安装
Vue.use(Vuex)

// 创建仓库(空仓库)
const store = new Vuex.Store({
  // 严格模式(有利于初学者,检测不规范的代码 => 上线时需要关闭)
  // 其实还是可以修改,只是会提示报错
  strict: true,
  // 1.通过state可以提供数据,所有组件共享的数据
  state: {
    title: '大标题',
    count: 100,
    list: [1, 2, 3, 4, 5, 6, 7, 8, 9]
  },

  // 2.通过mutations可以提供修改数据的方法,mutation是一个对象
  mutations: {
    //   所有的mutation函数,第一个参数,都是state
    // addCount (state) {
    //   //   修改数据
    //   state.count += 1
    // },
    // addCount (state, n) {
    //   //   修改数据
    //   state.count += n
    // },
    addCount (state, obj) {
      //   修改数据
      state.count += obj.count
    },

    changeTitle (state, newTitle) {
      state.title = newTitle
    },
    subCount (state, n) {
      state.count -= n
    },
    changeCount (state, newCount) {
      state.count = newCount
    }
  },

  // 3.actions处理异步
  //   注意:不能直接操作state,操作state,还是需要commit mutation
  actions: {
    // context上下文(此处未分模块,可以当作store仓库)
    // context.commit('mutation名字',额外参数)
    changeCountAction (context, num) {
      //   这里是setTimeout模拟异步,以后大部分场景是发请求
      setTimeout(() => {
        context.commit('changeCount', num)
      }, 1000)
    }
  },

  // 4.getters类似于计算属性
  // 但是只有获取,没有修改,修改只能通过mutations
  getters: {
    // 注意点:
    // 1.形参第一个参数,就是state
    // 必须有返回值,返回值就是getters的值
    filterList (state) {
      return state.list.filter(item => item > 5)
    }
  }
}

)

// 到处给main.js使用
export default store

Son1.vue(纯原生)

<template>
  <div class="box">
    <h2>Son1 子组件 {{ $store.state.title }}</h2>
    从vuex中获取的值: <label>{{ $store.state.count }}</label>
    <br>
    <button @click="handleAdd(1)">值 + 1</button>
    <button @click="handleAdd(5)">值 + 5</button>
    <button @click="handleAdd(10)">值 + 10</button>
    <button @click="handleChange">一秒后改为666</button>
    <button @click="changeFn">改标题</button>
    <hr>
    <div>{{ $store.state.list }}</div>
    <div>{{ $store.getters.filterList }}</div>

  </div>
</template>

<script>
export default {
  name: 'Son1Com',
  methods: {
    handleAdd (n) {
      // 错误代码,不会报错,并且可以实现,但其实是错的 (但是vue不会监测 监测需要成本)
      // this.$store.state.count++
      // console.log(this.$store.state.count)

      // 应该通过mutation 核心概念 进行修改数据
      // 需要提交调用mutation
      // this.$store.commit('addCount')
      // this.$store.commit('addCount', n)
      // 只能传递有且仅有一个参数,如果是想传递多个参数,可以写成对象数组的形式。
      this.$store.commit('addCount', {
        count: n,
        msg: '哈哈'
      })

      // console.log(n)
    },
    changeFn (newTitle) {
      this.$store.commit('changeTitle', '黑马程序员')
    },
    handleChange () {
      // 调用action
      // this.$store.dispatch('action名字',额外参数)
      this.$store.dispatch('changeCountAction', 666)
    }

  }
}
</script>

<style lang="css" scoped>
.box{
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

(4)辅助函数-mapGetters 

Son2.vue(辅助函数)

<template>
  <div class="box">
    <h2>Son2 子组件 {{ title }}</h2>
    从vuex中获取的值:<label>{{ count }}</label>
    <br />
    <button @click="handleSub(1)">值 - 1</button>
    <button @click="handleSub(5)">值 - 5</button>
    <button @click="subCount(10)">值 - 10</button>
<!-- 上面可以直接用subCount()了,都没必要封装了 -->
    <button @click="subCount(10)">值 - 10</button>
    <button @click="changeTitle('改了标题')">改标题</button>
    <button @click="changeCountAction(888)">一秒后改成888</button>
<hr>
<div>{{ filterList }}</div>
  </div>
</template>

<script>
import { mapActions, mapGetters, mapMutations, mapState } from 'vuex'
export default {
  name: 'Son2Com',
  computed: {
    // mapState和mapGetters都是映射属性
    ...mapState(['count', 'title']),
    ...mapGetters(['filterList'])
  },
  methods: {
    handleSub (n) {
      // this.$store.commit('subCount', n)
      this.subCount(n)
    },
    // mapMutations和mapActions都是映射方法
    ...mapMutations(['subCount', 'changeTitle']),
    ...mapActions(['changeCountAction'])

  }
}
</script>

<style lang="css" scoped>
.box {
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

七、模块创建


http://www.kler.cn/a/560858.html

相关文章:

  • ESP32系列芯片模组方案,设备物联网无线通信,智能化交互响应控制
  • ubuntu磁盘挂载
  • Websock Demo(二) Java后端代码
  • SQL:DQL数据查询语言以及系统函数(oracle)
  • 力扣-贪心-452 用最小数量的箭引爆气球
  • vue 手写分页
  • 除了Axios,如何用fetch处理403错误?
  • Linux故障排查和性能优化面试题及参考答案
  • MybatisPlus-插件功能-分页插件基本用法
  • 2024前端性能优化终极指南:从加载到渲染的完整解决方案
  • 谷歌浏览器(Google Chrome)扩展程序的安装路径(插件的安装路径)
  • 如何在VMware虚拟机的window10系统中安装网易mumu模拟器
  • angular表格排序分页
  • java 入门面试题
  • 对鸿蒙 中 对象的理解
  • SQL注入实战指南:sqli-labs全关卡通关详解与技巧总结
  • [java基础-JVM篇]1_JVM自动内存管理
  • js中的await与async的使用
  • 永洪科技旗下BI产品,成功入选“金融信创优秀解决方案“
  • redis添加密码