vuex 有大的更新 vue2创建项目的时候 勾选上了vue默认版本 是"vue":“^3.4.0”
vue3 里面 得使用 4开头的版本 “vue”:“^4.0.0”
- 第一步: 创建一个store/index.js
npm i vuex (或者创建vue项目的时候 勾选项 勾上 vuex)
import Vue from "vue";
import Vuex from "vuex"
Vue.use(Vuex)
export default new Vuex.Store({
state:{
// state 放需要管理的数据
singerList:[
{id:1,name:"周杰伦"},
{id:2,name:"薛之谦"},
{id:3,name:"陈奕迅"},
{id:4,name:"孙燕姿"}
]
},
// 一般放函数
actions:{},
mutations:{}
})
然后呢 得在main.js里
new Vue({
store,
render: h => h(App),
}).$mount('#app')
走通一条线
PageA 中使用singerList这条数据
<template>
<div id="pagear">
<h3>歌手列表</h3>
<ul>
<li v-for="item in singerList" :key="item.id">
<p>{{ item.name }}</p>
</li>
</ul>
</div>
</template>
<script>
export default{
name:"PageA",
data(){
return{
singerList:[],
}
},
methods:{
},
mounted(){
console.log(this)
this.singerList = this.$store.state.singerList
},
}
</script>
<template>
<div id="pagear">
<h3>歌手列表</h3>
<ul>
<li v-for="item in singerList" :key="item.id">
<p>{{ item.name }}</p>
</li>
</ul>
</div>
</template>
<script>
export default{
name:"PageA",
methods:{
},
// 或者不在data数据中定义数组,直接用计算属性来接收
computed:{
singerList(){
return this.$store.state.singerList
}
},
mounted(){
console.log(this)
this.singerList = this.$store.state.singerList
},
}
</script>
获取state数据的方式2 mapState
<template>
<div id="pagear">
<h3>歌手列表</h3>
<ul>
<li v-for="item in singerList" :key="item.id">
<p>{{ item.name }}</p>
</li>
</ul>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default{
name:"PageA",
computed:{
如果我们要从state中 取十条数据
如果没有 mapSate 那我们需要写 类似于 以下爱的十条 计算属性
// singerList(){
// return this.$store.state.singerList
// }
// arr(){
// return this.$store.state.arr
// }
// 相当于上面的操作 相当于 拥有了singerList或者arr计算属性
...mapState(["singerList","arr"]) 用在 computed内
},
使用了 mapState 只需要在数组中 添加数组项即可
}
</script>
如果我们不希望 同名 想要在组件内 自己定义数据名
不要用数组写法 用对象写法
...mapState({ list 是组件内的计算属性 singerList 是 state中的数据
list:"singerList"
})
等价于下面的写法
list(){
return this.$store.state.singerList
}
mutations的知识点
actions:{},
mutations:{
// 真正去修改 state内数据的函数 一些多余的逻辑处理(校验 判断 请求数据 这些都不放在 mutation内)
ADDFN(state,value){
state.singerList.push(value)
}
}
触发AddFN函数的方式1
methods:{
addFn(){
// this.$state.singerList.push({})
// commit 调用mutations内的 ADDFN函数 后面传参
this.$store.commit("ADDFN",{
id:8,
name:this.selectStr
})
}
}
InputAdd
<template>
<div class="inputadd">
<select v-model="selectStr">
<option value="李荣浩">李荣浩</option>
<option value="林依晨">林依晨</option>
<option value="陈奕迅">陈奕迅</option>
<option value="毛不易">毛不易</option>
<option value="邓紫棋">邓紫棋</option>
</select>
<button @click="addFn">添加一条</button>
</div>
</template>
<script>
export default{
name:"InputAdd",
data(){
return{
selectStr:"李荣浩"
}
},
methods:{
addFn(){
// this.$state.singerList.push({})
// commit 调用mutations内的 ADDFN函数 后面传参
this.$store.commit("ADDFN",{
id:8,
name:this.selectStr
})
}
}
}
</script>
触发mutations内函数的方式2
把ADDFN从mutations内导入到methods中 在组件内使用函数 只需要 this.函数名
methods:{
...mapMutations(["ADDFN"]),
addFn(){
this.ADDFN({id:8,name:this.selectStr})
}
}
数组写法:
相当于 在组件内 用ADDFN变量名接收 mutations内的ADDFN函数
...mapMutations(["ADDFN"]),
对象写法: 在组件内 用ADDfn变量名 接收 mutations的ADDFN函数
...mapMutations({
ADDfn:"ADDFN"
}),
InputAdd.vue
<template>
<div class="inputadd">
<select v-model="selectStr">
<option value="李荣浩">李荣浩</option>
<option value="林依晨">林依晨</option>
<option value="陈奕迅">陈奕迅</option>
<option value="毛不易">毛不易</option>
<option value="邓紫棋">邓紫棋</option>
</select>
<button @click="addFn">添加一条</button>
</div>
</template>
<script>
import {mapMutations} from "vuex"
export default{
name:"InputAdd",
data(){
return{
selectStr:"李荣浩"
}
},
methods:{
// addFn(){
// // this.$state.singerList.push({})
// // commit 调用mutations内的 ADDFN函数 后面传参
// this.$store.commit("ADDFN",{
// id:8,
// name:this.selectStr
// })
// }
// 把ADDFN从mutations内导入到methods中 在组件内使用函数 只需要 this.函数名
...mapMutations(["ADDFN"]),
addFn(){
this.ADDFN({id:8,name:this.selectStr})
}
}
}
</script>
actions
actions:{
addAction(context,value){
// 如果添加项 数组已经有了 那就 什么操作都不做
// context 是 简单版的$store
// console.log(context,value)
console.log(value)
// 如果return 内 返回true(value在数组项中存在) index 返回对应的索引值
// 返回都是false value在数组内不存在 返回 index = -1
const index = context.state.singerList.findIndex((item =>{
return item.name === value.name
}))
if(index>-1) return
// 调用mutations内的函数
context.commit("ADDFN",value)
}
},
actions触发方式1
methods:{
addFn(){
// dispach函数触发 actions内的函数执行
console.log(this.$store)
this.$store.dispatch("addAction",{id:8,name:this.selectStr})
}
actions触发方式2
数组写法
...mapActions(["addAction"]),
addFn(){
this.addAction({id:8,name:this.selectStr})
}
对象写法
...mapActions({
inputAddFn:"addAction"
}),
addFn(){
this.inputAddFn({id:8,name:this.selectStr})
}
index.js
import Vue from "vue";
import Vuex from "vuex"
Vue.use(Vuex)
console.log(Vuex)
export default new Vuex.Store({
state:{
// state 放需要管理的数据
singerList:[
{id:1,name:"周杰伦"},
{id:2,name:"薛之谦"},
{id:3,name:"陈奕迅"},
{id:4,name:"孙燕姿"}
],
arr:[
1,2,3
]
},
// 一般放函数
actions:{
addAction(context,value){
// 如果添加项 数组已经有了 那就 什么操作都不做
// context 是 简单版的$store
// console.log(context,value)
console.log(value)
// 如果return 内 返回true(value在数组项中存在) index 返回对应的索引值
// 返回都是false value在数组内不存在 返回 index = -1
const index = context.state.singerList.findIndex((item =>{
return item.name === value.name
}))
if(index>-1) return
// 调用mutations内的函数
context.commit("ADDFN",value)
}
},
mutations:{
// 真正去修改 state内数据的函数 一些多余的逻辑处理(校验 判断 请求数据 这些都不放在 mutation内)
ADDFN(state,value){
state.singerList.push(value)
}
}
})
InputAdd.vue
<template>
<div class="inputadd">
<select v-model="selectStr">
<option value="李荣浩">李荣浩</option>
<option value="林依晨">林依晨</option>
<option value="陈奕迅">陈奕迅</option>
<option value="毛不易">毛不易</option>
<option value="邓紫棋">邓紫棋</option>
</select>
<button @click="addFn">添加一条</button>
</div>
</template>
<script>
import {mapActions} from "vuex"
export default{
name:"InputAdd",
data(){
return{
selectStr:"李荣浩"
}
},
methods:{
// addFn(){
// // dispach函数触发 actions内的函数执行
// console.log(this.$store)
// this.$store.dispatch("addAction",{id:8,name:this.selectStr})
// }
...mapActions(["addAction"]),
addFn(){
this.addAction({id:8,name:this.selectStr})
}
}
}
</script>
补充一下 context参数内 dispach用于触发actions内其他的函数
actions内的逻辑处理比较复杂 需要抽分出几个函数
删除一条的方法
- 方法一
<template>
<div class="controlBtn">
<button @click="deleteOne">删除一条</button>
</div>
</template>
<script>
export default{
name:"ControlBtn",
methods:{
deleteOne(){
this.$store.state.singerList.pop()
}
}
}
</script>
- 方法二
index.js
import Vue from "vue";
import Vuex from "vuex"
Vue.use(Vuex)
console.log(Vuex)
export default new Vuex.Store({
state:{
// state 放需要管理的数据
singerList:[
{id:1,name:"周杰伦"},
{id:2,name:"薛之谦"},
{id:3,name:"陈奕迅"},
{id:4,name:"孙燕姿"}
],
arr:[
1,2,3
]
},
// 一般放函数
actions:{
addAction(context,value){
// 如果添加项 数组已经有了 那就 什么操作都不做
// context 是 简单版的$store
// console.log(context,value)
console.log(value)
// 如果return 内 返回true(value在数组项中存在) index 返回对应的索引值
// 返回都是false value在数组内不存在 返回 index = -1
const index = context.state.singerList.findIndex((item =>{
return item.name === value.name
}))
if(index>-1) return
// 调用mutations内的函数
context.commit("ADDFN",value)
},
},
mutations:{
// 真正去修改 state内数据的函数 一些多余的逻辑处理(校验 判断 请求数据 这些都不放在 mutation内)
ADDFN(state,value){
state.singerList.push(value)
},
DELETEONE(state){
state.singerList.pop()
}
}
})
ContolBtn.vue
``js
<template>
<div class="controlBtn">
<button @click="deleteOne">删除一条</button>
</div>
</template>
<script>
export default{
name:"ControlBtn",
methods:{
deleteOne(){
// this.$store.state.singerList.pop()
this.$store.commit("DELETEONE")
}
}
}
</script>
方法三:
index.js
import Vue from "vue";
import Vuex from "vuex"
Vue.use(Vuex)
console.log(Vuex)
export default new Vuex.Store({
state:{
// state 放需要管理的数据
singerList:[
{id:1,name:"周杰伦"},
{id:2,name:"薛之谦"},
{id:3,name:"陈奕迅"},
{id:4,name:"孙燕姿"}
],
arr:[
1,2,3
]
},
// 一般放函数
actions:{
addAction(context,value){
// 如果添加项 数组已经有了 那就 什么操作都不做
// context 是 简单版的$store
// console.log(context,value)
console.log(value)
// 如果return 内 返回true(value在数组项中存在) index 返回对应的索引值
// 返回都是false value在数组内不存在 返回 index = -1
const index = context.state.singerList.findIndex((item =>{
return item.name === value.name
}))
if(index>-1) return
// 调用mutations内的函数
context.commit("ADDFN",value)
},
deleteAction(context){
if(context.state.singerList.length <= 1) return
context.dispatch("moreAction")
},
moreAction(context){
console.log("在这里处理了一些其他的事情");
context.commit("DELETEONE")
}
},
mutations:{
// 真正去修改 state内数据的函数 一些多余的逻辑处理(校验 判断 请求数据 这些都不放在 mutation内)
ADDFN(state,value){
state.singerList.push(value)
},
DELETEONE(state){
state.singerList.pop()
}
}
})
ControlBtn.vue
<template>
<div class="controlBtn">
<button @click="deleteOne">删除一条</button>
</div>
</template>
<script>
export default{
name:"ControlBtn",
methods:{
deleteOne(){
// this.$store.state.singerList.pop()
// this.$store.commit("DELETEONE")
this.$store.dispatch("deleteAction")
}
}
}
</script>
getter
当频繁要去获取state数据的内容,可以把当前的数据 处理为getter,去加工 state 内的数据 (不是去修改) 只是去获取(更加便捷)
需求:想要获取singerList的第一项
-
{{ $store.state.singerList[0].name }}
<template>
<div class="controlBtn">
<button @click="deleteOne">删除一条</button>
<p>{{ $store.state.singerList[0].name }}</p>
</div>
</template>
<script>
export default{
name:"ControlBtn",
methods:{
deleteOne(){
// this.$store.state.singerList.pop()
// this.$store.commit("DELETEONE")
this.$store.dispatch("deleteAction")
}
}
}
</script>
<p>{{ $store.getters.singerListFirstName }}</p>
getters:{
singerListFirstName(state){
return state.singerList[0].name
}
}
import Vue from "vue";
import Vuex from "vuex"
Vue.use(Vuex)
console.log(Vuex)
export default new Vuex.Store({
state:{
// state 放需要管理的数据
singerList:[
{id:1,name:"周杰伦"},
{id:2,name:"薛之谦"},
{id:3,name:"陈奕迅"},
{id:4,name:"孙燕姿"}
],
arr:[
1,2,3
]
},
// 一般放函数
actions:{
addAction(context,value){
// 如果添加项 数组已经有了 那就 什么操作都不做
// context 是 简单版的$store
// console.log(context,value)
console.log(value)
// 如果return 内 返回true(value在数组项中存在) index 返回对应的索引值
// 返回都是false value在数组内不存在 返回 index = -1
const index = context.state.singerList.findIndex((item =>{
return item.name === value.name
}))
if(index>-1) return
// 调用mutations内的函数
context.commit("ADDFN",value)
},
deleteAction(context){
if(context.state.singerList.length <= 1) return
context.dispatch("moreAction")
},
moreAction(context){
console.log("在这里处理了一些其他的事情");
context.commit("DELETEONE")
},
},
mutations:{
// 真正去修改 state内数据的函数 一些多余的逻辑处理(校验 判断 请求数据 这些都不放在 mutation内)
ADDFN(state,value){
state.singerList.push(value)
},
DELETEONE(state){
state.singerList.pop()
}
},
getters:{
singerListFirstName(state){
return state.singerList[0].name
}
}
})
其他获取方式
import {mapActions} from "vuex"
conputed:{
...mapGetters(["singerListFirstName"]),
},
从这里开始报错…
新增一条songList 数据 新增多条数据导致 {} 内 actions mutations内的函数 变的 不好维护
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
//state 放需要管理的数据
singerList: [
{ id: 1, name: "薛之谦" },
{ id: 2, name: "周杰伦" },
{ id: 3, name: "陈奕迅" },
{ id: 4, name: "孙燕姿" },
],
songList: [
{ name: "动物世界" },
{ name: "布拉格广场" },
{ name: "隐形的翅膀" },
],
},
actions: {
addAction(context, value) {
const index = context.state.singerList.findIndex((item) => {
return item.name === value.name
})
if (index > -1) return
// 调用 mutations内的函数
context.commit('ADDFN', value)
},
deleteAction(context) {
if (context.state.singerList.length <= 1) return
context.dispatch('moreAction')
},
moreAction(context) {
console.log('在这里处理了一些其他的事情');
context.commit('DELETEONE')
},
// 操作songList
addSongAction(context, value) {
const index = context.state.songList.findIndex((item) => {
return item.name === value.name
})
if (index > -1) return
// 调用 mutations内的函数
context.commit('ADDSONG', value)
},
},
mutations: {
//操作singerList
ADDFN(state, value) {
state.singerList.push(value)
},
// 操作songList
ADDSONG(state, value) {
state.songList.push(value)
},
DELETEONE(state, value) {
state.singerList.pop()
}
},
getters: {
singerListFirstName(state) {
return state.singerList[0].name
},
currentSong() {
return playList[index]
}
}
})
pageB
<template>
<div class="pageb">
<h3>歌曲列表</h3>
<ul>
<li v-for="item in songList">
<p>{{ item.name }}</p>
</li>
</ul>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "PageB",
computed: {
...mapState(["songList"]),
},
};
</script>
inputAdd
<template>
<div class="inputadd">
<select v-model="selectStr">
<option value="李荣浩">李荣浩</option>
<option value="林依晨">林依晨</option>
<option value="陈奕迅">陈奕迅</option>
<option value="毛不易">毛不易</option>
<option value="邓紫棋">邓紫棋</option>
</select>
<button @click="addFn">添加一条</button>
<hr />
<select v-model="selectV">
<option value="遇见">遇见</option>
<option value="一路生花">一路生花</option>
<option value="李白">李白</option>
<option value="偏爱">偏爱</option>
<option value="平凡之路">平凡之路</option>
</select>
<button @click="addSongItem">添加一条</button>
</div>
</template>
<script>
import { mapMutations, mapActions } from "vuex";
export default {
name: "InputAdd",
data() {
return {
selectStr: "李荣浩",
selectV: "遇见",
};
},
methods: {
addFn() {
this.addAction({ id: 8, name: this.selectStr });
},
addSongItem() {
//触发 actions内的
this.addSongAction({ name: this.selectV });
},
...mapActions(["addAction", "addSongAction"]),
},
};
</script>
modules 模块化处理
songlist.js
export default {
namespaced: true, //开启命名空间
state: {
songList: [
{ name: "动物世界" },
{ name: "布拉格广场" },
{ name: "隐形的翅膀" },
],
},
actions: {
// 操作songList
addSongAction(context, value) {
const index = context.state.songList.findIndex((item) => {
return item.name === value.name
})
if (index > -1) return
// 调用 mutations内的函数
context.commit('ADDSONG', value)
},
},
mutations: {
ADDSONG(state, value) {
state.songList.push(value)
},
}
}
singerlist.js
export default {
namespaced: true,
state: {
singerList: [
{ id: 1, name: "薛之谦" },
{ id: 2, name: "周杰伦" },
{ id: 3, name: "陈奕迅" },
{ id: 4, name: "孙燕姿" },
],
},
actions: {
addAction(context, value) {
const index = context.state.singerList.findIndex((item) => {
return item.name === value.name
})
if (index > -1) return
context.commit('ADDFN', value)
},
deleteAction(context) {
if (context.state.singerList.length <= 1) return
context.commit('DELETEONE')
},
},
mutations: {
//操作singerList
ADDFN(state, value) {
state.singerList.push(value)
},
DELETEONE(state, value) {
state.singerList.pop()
}
}
}
index.js
import Vue from 'vue'
import Vuex from 'vuex'
import singerListModule from './singerList'
import songListModule from './songList'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
singerListModule,
songListModule
}
})
state内数据的获取
state: Object
singerListModule: (…)
songListModule: (…)
console.log(this.$store.state.singerListModule.singerList);
用 mapState的方式
computed: {
...mapState("singerListModule", ["singerList"]),
},
getters内的数据的获取
普通获取
console.log(this.$store.getters["singerListModule/singerListFirstName"]);
mapGetters获取
...mapGetters("singerListModule", ["singerListFirstName"]),
actions内的数据的获取
普通调用
this.$store.dispatch("songListModule/addSongAction", {
name: this.selectV,
});
...mapActions("singerListModule", ["addAction"]),
...mapActions("songListModule", ["addSongAction"]),
mutations内的数据的获取
this.$store.commit('singerListModule/DELETEONE')
...mapMutations("singerListModule", ["DELETEONE"]),
动态组件
<template>
<div id="app">
<component :is="componentId"></component>
<button @click="bool = !bool">修改bool</button>
</div>
</template>
<script>
import Song from "@/components/song.vue";
import Singer from "@/components/singer.vue";
export default {
name: "App",
data() {
return {
bool: true,
};
},
computed: {
componentId() {
return this.bool ? "Singer" : "Song";
},
},
components: { Song, Singer },
};
</script>
缓存动态组件
<!-- 默认缓存所有的动态组件 -->
<keep-alive>
<component :is="componentId"></component>
</keep-alive>
只缓存 Song 组件
<keep-alive include="Song"> //值是 组件name
<component :is="componentId"></component>
</keep-alive>
<!-- 不缓存Song的组件 -->
<keep-alive exclude="Song">
<component :is="componentId"></component>
</keep-alive>