• vuex 基础知识 (跨组件传值)


    一、解释

    vuex 状态(数据)管理工具 。 vuex 可以把整个项目的数据集中的管理起来 方便组件与组件的使用 (组件想使用数据 那么不需要使用 复杂的传递方式了 直接就可以去vuex中进行数据 的获取)

    传统的vue 是单向数据流 如果是兄弟或者是跨层级的组件在进行传递的时候vue就非常的麻烦vuex就可以来进行上述传值 简化数据传递的复杂度。

    二、vuex创建流程

    ①第一种 创建项目时选中Vuex

     ② 第二种 指令下载

    npm install --save vuex

     在src文件夹下新建store文件夹并且新建index.js 

    1. import Vue from 'vue'
    2. import Vuex from 'vuex'
    3. Vue.use(Vuex)
    4. export default new Vuex.Store({
    5. })

    在main.js 中引用vuex文件 并且在vue实例上注册

    1. import Vue from 'vue'
    2. import App from './App.vue'
    3. import router from './router'
    4. import store from './store'//引用
    5. Vue.config.productionTip = false
    6. new Vue({
    7. router,
    8. store,//注册
    9. render: h => h(App)
    10. }).$mount('#app')

    三、vuex的5大属性

    1、state属性---数据源(创建数据的   类似于组件中的data)

    vuex的所有数据都在state中进行创建

    1. import Vue from 'vue'
    2. import Vuex from 'vuex'
    3. Vue.use(Vuex)
    4. export default new Vuex.Store({
    5. state: {
    6. text:"小王",
    7. age:18,
    8. arr:[111,222,333],
    9. obj:{
    10. love:"女"
    11. }
    12. },
    13. mutations: {
    14. },
    15. actions: {
    16. },
    17. modules: {
    18. }
    19. })

    ① 取值方式1 ----任意组件模板上直接使用 $store.state.xxx使用

    1. <template>
    2. <div>
    3. 拿text的值{{$store.state.text}}
    4. div>
    5. template>
    6. <script>
    7. export default {
    8. }
    9. script>
    10. <style>
    11. style>

    ②.取值方式2 ---使用计算属性来进行vuex的数据获取

    1. <template>
    2. <div>
    3. 拿age的值{{newage}}
    4. div>
    5. template>
    6. <script>
    7. export default {
    8. computed:{
    9. newage(){
    10. return this.$store.state.age
    11. }
    12. }
    13. }
    14. script>
    15. <style>
    16. style>

    2、mutations属性---vuex的数据修改

    vuex中state的数据不能直接修改 如果要触发mutations的修改动作 那么要使用commit这个方法来进行调用

    比如把小王修改为小黑

    第一步、通过事件触发commit来调用修改操作

    1. <template>
    2. <div>
    3. home页面{{$store.state.text}}
    4. <button @click="fun()">点我修改button>
    5. div>
    6. template>
    7. <script>
    8. export default {
    9. methods:{
    10. fun(){
    11. // 需要触发这个函数之后把vuex的text变量进行修改
    12. // this.$store.commit("你要调用的mutations的名字",传递的参数)
    13. //第一种写法:
    14. this.$store.commit("uptext",{newtext:"小黑"})
    15. //第二种写法:推荐写对象的形式
    16. this.$store.commit({
    17. type:"uptext",
    18. newtext:"小白"
    19. })
    20. }
    21. }
    22. }
    23. script>
    24. <style>
    25. style>

    第二步去store中编写对应的mutations修改动作

    1. import Vue from 'vue'
    2. import Vuex from 'vuex'
    3. Vue.use(Vuex)
    4. export default new Vuex.Store({
    5. state: {//创建数据的类似于组件中的data
    6. text:"小王",
    7. age:18,
    8. arr:[111,222,333],
    9. obj:{
    10. love:"女"
    11. }
    12. },
    13. mutations: {
    14. // 第一个形参state就是指向上面的state数据源
    15. // 第二个形参接收的就是commit方法中的第二个参数
    16. uptext(state,payload){
    17. state.text = payload.newtext
    18. }
    19. },
    20. actions: {
    21. },
    22. modules: {
    23. }
    24. })

    vuex数据修改后 刷新丢失

    在vuex中如果我们修改数据之后 页面在刷新一次 那么页面的数据你会回复成默认值

    1. created() {
    2. //在页面加载时读取sessionStorage里的状态信息
    3. if (sessionStorage.getItem("store")) {
    4. this.$store.replaceState(
    5. Object.assign(
    6. {},
    7. this.$store.state,
    8. JSON.parse(sessionStorage.getItem("store"))
    9. )
    10. );
    11. }
    12. //在页面刷新时将vuex里的信息保存到sessionStorage里
    13. window.addEventListener("beforeunload", () => {
    14. sessionStorage.setItem("store", JSON.stringify(this.$store.state));
    15. });
    16. },

    3、actions属性------触发异步操作

    actions中是一个个的方法 每一个方法就是一个异步的动作 (异步请求)

    actions调用的话 使用dispatch( ) 来进行调用

    1.页面通过dispatch来触发actions

    1. <template>
    2. <div>
    3. user页面{{$store.state.text}}
    4. <button @click="fun()">点我触发异步操作button>
    5. div>
    6. template>
    7. <script>
    8. export default {
    9. methods:{
    10. fun(){
    11. // 调用actions
    12. // this.$store.dispatch("你出发的actions的名字",{数据})
    13. //写法一:
    14. //this.$store.dispatch("demoLink",{url:"/data/data"})
    15. //写法二:推荐写为对象的形式
    16. this.$store.dispatch(
    17. {
    18. type:"getMenuList",
    19. url:"/data/list/menu"
    20. }
    21. )
    22. }
    23. }
    24. }
    25. script>

    2、actions创建对应的方法  

    1. import Vue from 'vue'
    2. import Vuex from 'vuex'
    3. // 引用数据请求
    4. import getlink from "@/apis/getapi.js"
    5. Vue.use(Vuex)
    6. export default new Vuex.Store({
    7. state: {//创建数据的类似于组件中的data
    8. text:"小王",
    9. age:18,
    10. arr:[111,222,333],
    11. obj:{
    12. love:"女"
    13. }
    14. },
    15. mutations: {
    16. uparr(state,payload){
    17. //把请求来的数据修改state
    18. state.arr=payload.arrdata
    19. }
    20. },
    21. actions: {
    22. // context形参 就是store对象
    23. // 第二个形参接收的就是dispatch
    24. demoLink(context,payload){
    25. console.log("context")
    26. //发送异步操作
    27. getlink(payload.url).then((res)=>{
    28. console.log(res.data.data)
    29. //把请求来的数据交给mutations来修改state
    30. context.commit("uparr",{arrdata:res.data.data})
    31. })
    32. }
    33. },
    34. modules: {
    35. }
    36. })

    3、在页面展示请求来的新的arr

    1. <template>
    2. <div>
    3. {{newarr}}
    4. div>
    5. template>
    6. <script>
    7. export default {
    8. computed:{
    9. newarr(){
    10. return this.$store.state.arr
    11. }
    12. },
    13. }
    14. script>
    15. <style>
    16. style>

    4、getters属性 -- 类似于计算属性

    getters 可以对一个数据在不同位置展示出不同的形态时候用

    getters 处理的数据 任何组件都能用

    vue的计算属性处理的数据 只能当前组件使用

    1. import Vue from 'vue'
    2. import Vuex from 'vuex'
    3. Vue.use(Vuex)
    4. export default new Vuex.Store({
    5. state: {//创建数据的类似于组件中的data
    6. demo:"abcde"
    7. },
    8. mutations: {
    9. },
    10. actions: {
    11. },
    12. modules: {
    13. },
    14. getters:{
    15. // 里面就一个形参 state代表的就是数据源
    16. newdemo(state){
    17. return state.demo.toUpperCase()
    18. }
    19. }
    20. })

    把demo的小写处理为大写后在页面去用(组件里使用getters时不加模块名)

    1. <template>
    2. <div>
    3. home页面
    4. <h1>{{$store.getters.newdemo}}h1>
    5. div>
    6. template>
    7. <script>
    8. export default {
    9. }
    10. script>
    11. <style>
    12. style>

    5、module 模块

    可以把上面写在一起的数据 修改 异步操作 计算属性 按照页面等进行分类管理

    第一步 home页面user页面分开管理

     第二步 在index.js把模块注入到vuex中

    1. import Vue from 'vue'
    2. import Vuex from 'vuex'
    3. // 引用模块
    4. import Home from "./modules/home.js"
    5. import User from "./modules/user.js"
    6. Vue.use(Vuex)
    7. export default new Vuex.Store({
    8. // 注入
    9. modules: {
    10. Home ,
    11. User
    12. }
    13. })

     第三步 使用数据 $store.state.模块名.xxx

    1. <template>
    2. <div>
    3. home页面
    4. <h1>{{$store.state.Home.text}}h1>
    5. div>
    6. template>
    7. <script>
    8. export default {
    9. }
    10. script>
    11. <style>
    12. style>

    问题:如果home和user两个模块里有相同action(mutation)的名字

     

    结果是两个都会调用,那么如何区分????

     添加 namespaced: true 的方式使其成为带命名空间的模块

    两个都要开启。开启后变为严格模式必须加模块名字

     

     getters重名区分的话    也要加模块名

    {{$store.getters["Home/newdemo"]}}

    {{$store.getters["User/newdemo"]}}

    问题:这样写太繁琐(冗余)

    辅助函数 http:// https://vuex.vuejs.org/zh/guide/state.html

    mapState, mapGetters (这两个在computed里映射

    mapMutations, mapActions(这两个在methods里映射

     假如index.js 里 (没分模块化)

    1. import axios from "axios";
    2. import Vue from "vue";
    3. import Vuex from 'vuex'
    4. import Home from "./home.js"
    5. import User from "./user.js"
    6. // 1.安装
    7. Vue.use(Vuex)
    8. // 2.创建对象
    9. export default new Vuex.Store({
    10. state: {
    11. demo:"abc",
    12. num:0,
    13. num1:"1",
    14. num2:"2",
    15. num3:"2",
    16. age:18,
    17. },
    18. mutations: {
    19. },
    20. actions: {
    21. },
    22. getters: {
    23. newDemo(state){
    24. return state.demo.toUpperCase()
    25. }
    26. },
    27. modules: {
    28. Home,
    29. User
    30. }
    31. })

     使用辅助函数

    1. <template>
    2. <div>
    3. demoVuex:
    4. <h3>{{num1}}h3>
    5. <h3>{{num2}}h3>
    6. <h3>{{num3}}h3>
    7. <h3>newDemo:{{newDemo}}h3>
    8. div>
    9. template>
    10. <script>
    11. import { mapState,mapGetters } from "vuex";
    12. export default {
    13. data(){
    14. return{
    15. }
    16. },
    17. methods:{
    18. },
    19. computed:{
    20. ...mapState(['num1','num2','num3']),
    21. ...mapGetters(["newDemo"])
    22. },
    23. //这种写法也可以但(不能再写其它计算属性)
    24. // computed:mapState({
    25. // num:state=> state.num
    26. // }),
    27. }
    28. script>

    区分模块化

    1. <template>
    2. <div>
    3. demoVuex
    4. <h4>{{newDemo}}h4>
    5. div>
    6. template>
    7. <script>
    8. import { mapState,mapGetters } from "vuex";
    9. export default {
    10. data(){
    11. return{
    12. }
    13. },
    14. methods:{
    15. },
    16. computed:{
    17. // 未加模块名
    18. ...mapState(['num1','num2','num3']),
    19. ...mapGetters(["newDemo"]),
    20. // 加了模块名
    21. // ...mapGetters(["模块名",[模块里的getters]])
    22. ...mapGetters(["Home",["newdemo"]])
    23. },
    24. }
    25. script>

    mapActions

    ① 不区分模块index.js

    1. actions: {
    2. getMenuList(){
    3. axios({
    4. url:'/data/list/menu'
    5. }).then(res=> {
    6. console.log('res',res);
    7. })
    8. }
    9. },

    使用时候

    1. <template>
    2. <div>
    3. <input type="button" value="按钮" @click="handleAxios()">
    4. div>
    5. template>
    6. <script>
    7. import { mapState,mapGetters,mapActions } from "vuex";
    8. export default {
    9. data(){
    10. return{
    11. }
    12. },
    13. methods:{
    14. // 把getMenuList映射到当前组件的methods中
    15. ...mapActions(["getMenuList"]),
    16. handleAxios(){
    17. this.getMenuList({id:123}) //类似this.$store.dispatch()
    18. },
    19. }
    20. }
    21. script>

    区分模块化 ...mapActions({"名字":"模块名/actions下的方法名"}),

    1. <template>
    2. <div>
    3. <input type="button" value="按钮" @click="handleAxios()">
    4. div>
    5. template>
    6. <script>
    7. import { mapState,mapGetters,mapActions } from "vuex";
    8. export default {
    9. data(){
    10. return{
    11. }
    12. },
    13. methods:{
    14. // 把getIndexAction映射到当前组件的methods中
    15. ...mapActions(["getIndexAction"]),
    16. // ...mapActions({"getMenuList":"Home/getMenuList"}),
    17. ...mapActions(['getMenuList', ['Home/getMenuList']]),
    18. handleAxios(){
    19. this.getIndexAction({id:123}) //类似this.$store.dispatch()
    20. this.getMenuList() //类似this.$store.dispatch()
    21. },
    22. }
    23. }
    24. script>

    mapMutations

    不区分模块index.js

    1. export default new Vuex.Store({
    2. state: {
    3. word:"hello word",
    4. },
    5. mutations: {
    6. upWord(state,payload) {
    7. state.word = payload.newWord
    8. }
    9. },
    10. })

    使用

    1. <template>
    2. <div>
    3. demoVuex:
    4. <h5>{{ $store.state.word }}h5>
    5. <button @click="changeWord()">点我修改button>
    6. div>
    7. template>
    8. <script>
    9. import { mapState, mapGetters, mapActions,mapMutations } from 'vuex'
    10. export default {
    11. data() {
    12. return {}
    13. },
    14. methods: {
    15. ...mapMutations(['upWord']),
    16. changeWord(){
    17. this.upWord({newWord:'hi'})
    18. }
    19. }
    20. }
    21. script>

    区分模块home.js

    1. export default {
    2. state:{
    3. homeText:'home的hello'
    4. },
    5. mutations:{
    6. homeText(state,payload) {
    7. state.homeText = payload.homeText
    8. }
    9. }
    10. }

    使用

    1. <template>
    2. <div>
    3. demoVuex:
    4. <h5>{{ $store.state.word }}h5>
    5. <h5>{{$store.state.home.homeText}}h5>
    6. <button @click="changeWord()">点我修改button>
    7. div>
    8. template>
    9. <script>
    10. import { mapState, mapGetters, mapActions,mapMutations } from 'vuex'
    11. export default {
    12. methods: {
    13. ...mapMutations(['homeText',['home/homeText']]),
    14. changeWord(){
    15. this.homeText({homeText:'heihei'})
    16. }
    17. }
    18. }
    19. script>

     dispatch触发actions通过commit调用mutations修改state

  • 相关阅读:
    MATLAB算法实战应用案例精讲-【优化算法】沙丁鱼优化算法(SOA)(附MATLAB代码实现)
    数据库中的数据
    Docker -- 01实践:使用Docker 快速安装Jenkins
    csdn 格式规范
    结构化数据和非结构化数据
    认识物联网
    Java获取dbcp连接池
    export default 导出的对象,不能解构问题,和module.exports的区别
    Linux之从进程角度来理解文件描述符
    SpringCloud - Spring Cloud Alibaba 之 Seata分布式事务服务详解;部署(十八)
  • 原文地址:https://blog.csdn.net/Tianxiaoxixi/article/details/126216431