【day 10】Vuex

vuex 有大的更新 vue2创建项目的时候 勾选上了vue默认版本 是"vue":“^3.4.0”
vue3 里面 得使用 4开头的版本 “vue”:“^4.0.0”

  1. 第一步: 创建一个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内的逻辑处理比较复杂 需要抽分出几个函数
删除一条的方法

  1. 方法一
<template>
    <div class="controlBtn">
        <button @click="deleteOne">删除一条</button>
    </div>
</template>
<script>
  export default{
    name:"ControlBtn",
    methods:{
      deleteOne(){
        this.$store.state.singerList.pop()
      }

    }


  }

</script>
  1. 方法二
    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的第一项

  1. {{ $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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值