zoukankan      html  css  js  c++  java
  • vuex

    • Vuex 概述 
    • Vuex 的基本使用 
    • Vuex 的核心概念 
    • 基于 Vuex 的案例 

    1. Vuex 概述

    ① 组件之间共享数据的方式

    父向子传值: v-bind 属性绑定

    子向父传值: v-on 事件绑定

    兄弟组件之间共享数据: EventBus

    • $on 接收数据的那个组件
    • $emit 发送数据的那个组件

    上面这三种共享数据的方式只适合在小范围内进行数据的共享,如果我们需要频繁的、大范围的实现数据的共享,这三种方案就有点力不从心了

    ② Vuex 是什么

    Vuex 是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享。 

    vuex本质就是实现数据共享的:

    ③ 使用 Vuex 统一管理状态的好处 

    • 能够在 vuex 中集中管理共享的数据,易于开发和后期维护
    • 能够高效地实现组件之间的数据共享,提高开发效率
    • 存储在 vuex 中的数据都是响应式的,能够实时保持数据与页面的同步

    ④ 什么样的数据适合存储到 Vuex 中

    一般情况下,只有组件之间共享的数据,才有必要存储到 vuex 中;对于组件中的私有数据,依旧存储在组件自身的 data 中即可。


    2. Vuex 的基本使用

    ① 安装 vuex 依赖包

    npm install vuex --save

    ② 导入 vuex 包

    import Vuex from 'vuex'
    Vue.use(Vuex)

    ③ 创建 store 对象

    const store = new Vuex.Store({
        // state 中存放的就是全局共享的数据
        state: { count: 0 }
    })

    ④ 将 store 对象挂载到 vue 实例中

    new Vue({
        el: '#app',
        render: h => h(app),
        router,
        // 将创建的共享数据对象,挂载到 Vue 实例中
        // 所有的组件,就可以直接从 store 中获取全局的数据了
        store
    })

    3. Vuex 的核心概念

    Vuex 中的主要核心概念如下:

    • State
    • Mutation
    • Action
    • Getter

    ① State 

    State 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 State 中进行存储。

    // 创建store数据源,提供唯一公共数据
    const store = new Vuex.Store({
        state: { count: 0 }
    })

    组件访问 State 中数据的第一种方式

    this.$store.state.全局数据名称

    在template区域,this是可以省略的:

    组件访问 State 中数据的第二种方式

    // 1. 从 vuex 中按需导入 mapState 函数
    import { mapState } from 'vuex'

    通过刚才导入的 mapState 函数,将当前组件需要的全局数据,映射为当前组件的 computed 计算属性:

    // 2. 将全局数据,映射为当前组件的计算属性
    computed: {
        ...mapState(['count'])
    }

    实现+1的效果:

    虽然能够实现所需的功能,但是这种做法是完全不对的。因为我们在当前组件中直接修改了$store全局数据,但是在vuex中不允许组件直接修改store里面的数据,所以上面的代码是完全不合法的。

    那在vuex中是推荐哪种方式来修改store里面的公有数据呢?

    如果我们使用在组件中直接修改store数据的方式,随着我们的项目越写越大,如果我们想看一下到底是哪个组件修改了store里面的数据,我们得挨个去组件里面找,不利于后期的维护。但是如果我们使用mutations来集中式修改state中的数据,可以方便后期的维护。

    ② Mutation

    Mutation 用于变更 Store中 的数据。

    只能通过 mutation 变更 Store 数据,不可以直接操作 Store 中的数据。

    通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化。

    // 定义 Mutation
    const store = new Vuex.Store({
        state: {
            count: 0
        },
        mutations: {
            add(state) {
                // 变更状态
                state.count++
            }
        }
    })
    // 触发mutation
    methods: {
        handle1() {
            // 触发 mutations 的第一种方式
            this.$store.commit('add')
        }
    }

    可以在触发 mutations 时传递参数:

    // 定义Mutation
    const store = new Vuex.Store({
        state: {
            count: 0
        },
        mutations: {
            addN(state, step) {
                // 变更状态
                state.count += step
            }
        }
    })
    // 触发mutation
    methods: {
        handle2() {
            // 在调用 commit 函数,
            // 触发 mutations 时携带参数
            this.$store.commit('addN', 3)
        }
    }

    commit的作用就是调用某个mutation函数

    this.$store.commit() 是触发 mutations 的第一种方式,触发 mutations 的第二种方式

    // 1. 从 vuex 中按需导入 mapMutations 函数
    import { mapMutations } from 'vuex'

    通过刚才导入的 mapMutations 函数,将需要的 mutations 函数,映射为当前组件的 methods 方法:

    // 2. 将指定的 mutations 函数,映射为当前组件的 methods 函数
    methods: {
        ...mapMutations(['add', 'addN'])
    }

    实现一个功能:点击按钮后延迟一秒再显示count的值

    按我们正常的思维会在mutation对应的方法中添加一个定时器,但是出现一个问题:

    页面显示的效果中是没有什么问题的,但是可以看到vue调试器中的count状态值却并没有发生变化。

    这是因为在mutations函数中,不能写异步的代码,而定时器就是异步的方法!

    那如何执行异步操作呢?

    ③ Action

    Action 用于处理异步任务。

    如果通过异步操作变更数据,必须通过 Action,而不能使用 Mutation,但是在 Action 中还是要通过触发Mutation 的方式间接变更数据。 

    // 定义 Action
    const store = new Vuex.Store({
        // ...省略其他代码
        mutations: {
            add(state) {
                state.count++
            }
        },
        actions: {
            addAsync(context) {
                setTimeout(() => {
                    context.commit('add')
                }, 1000)
            }
        }
    })
    // 触发 Action
    methods: {
        handle() {
            // 触发 actions 的第一种方式
            this.$store.dispatch('addAsync')
        }
    }

    dispatch函数专门用来触发action。

    只有mutation中定义的函数,才有权利修改state中的数据

    触发 actions 异步任务时携带参数:

    // 定义 Action
    const store = new Vuex.Store({
        // ...省略其他代码
        mutations: {
            addN(state, step) {
                state.count += step
            }
        },
        actions: {
            addNAsync(context, step) {
                setTimeout(() => {
                    context.commit('addN', step)
                }, 1000)
            }
        }
    })
    // 触发 Action
    methods: {
        handle() {
            // 在调用 dispatch 函数,
            // 触发 actions 时携带参数
            this.$store.dispatch('addNAsync', 5)
        }
    }

    this.$store.dispatch() 是触发 actions 的第一种方式,触发 actions 的第二种方式

    // 1. 从 vuex 中按需导入 mapActions 函数
    import { mapActions } from 'vuex'

    通过刚才导入的 mapActions 函数,将需要的 actions 函数,映射为当前组件的 methods 方法:

    // 2. 将指定的 actions 函数,映射为当前组件的 methods 函数
    methods: {
        ...mapActions(['addASync', 'addNASync'])
    }

    ④ Getter

    Getter 用于对 Store 中的数据进行加工处理形成新的数据。

    注意:Getter不会修改store里面的源数据,它只是起到包装数据的作用

    • Getter 可以对 Store 中已有的数据加工处理之后形成新的数据,类似 Vue 的计算属性。
    • Store 中数据发生变化, Getter 的数据也会跟着变化。
    // 定义 Getter
    const store = new Vuex.Store({
        state: {
            count: 0
        },
        getters: {
            showNum: state => {
                return '当前最新的数量是【'+ state.count +'】 '
            }
        }
    })

    使用 getters 的第一种方式

    this.$store.getters.名称

    使用 getters 的第二种方式

    import { mapGetters } from 'vuex'
    computed: {
        ...mapGetters(['showNum'])
    }

    4. 基于 Vuex 的案例

    使用vuex做一个TodoList的小案例: 

    ① 初始化项目

    • 通过 vue ui 命令打开可视化面板,创建新项目 vuex-demo2
    • 安装 vuex 依赖包 npm install vuex axios ant-design-vue –S
    • 实现 Todos 基本布局(基于已有样式模板)

    ② 完成具体功能

    • 动态加载任务列表数据
    • 实现文本框与store数据的双向同步
    • 完成添加任务事项的操作
    • 完成删除任务事项的操作
    • 动态绑定复选框的选中状态
    • 修改任务事项的完成状态
    • 统计未完成的任务的条数
    • 清除已完成的任务事项
    • 实现任务列表数据的动态切换

    创建一个新项目:

    开启Babel,vuex,linter/fomatter,use config files:

    需要安装的依赖:axios、ant-design-vue。

    1)实现数据动态渲染到页面上

    通过axios请求list.json文件里面的数据,如何发请求来获取数据呢?

    在store.js中导入axios,注意,axios请求是异步操作,所以必须在action中发送请求

    在App.vue组件中调用该函数:

    如何将数据渲染到页面上呢?需要将请求获取到的数据挂载到state里面来进行存储

    2)实现文本框中的内容的双向同步

    首先在store文件中的state中定义一个全局数据inputValue,需要将App.vue组件中的文本框的value属性动态绑定到该数据上
    只需要将该属性映射到计算属性中去,并为文本框监听一个change事件,拿到文本框最新的值,然后再同步到state中去

    3)点击添加事项的功能

    为添加事项按钮添加一个点击事件

    this.$message.warning是由ant-design的UI组件库提供的 

    4)实现删除事件的功能

    为每一个删除按钮添加一个点击事件,在调用该事件函数同时并把这条数据的id传递过去

    5)实现复选框状态的绑定

    6)修改任务完成状态的功能

    点击任务事项对应的复选框,能够拿到该复选框最新的状态,然后再根据这一项的id复制到对应的list数组中

    监听复选框状态改变的change事件

    7)统计未完成的任务条数

    需要用到vuex中的getters

    8)清除已完成任务的功能

    为该按钮添加一个点击事件

    9)实现列表底部三个按钮(全部、未完成、已完成)的高亮状态的切换

    点击不同的按钮能够切换不同按钮的高亮效果

    10)实现列表数据的按需切换

    基于vuex实现TodoList功能的代码地址:vuex_todolist

  • 相关阅读:
    jQuery 源码解析(二十四) DOM操作模块 包裹元素 详解
    jQuery 源码解析(二十三) DOM操作模块 替换元素 详解
    jQuery 源码解析(二十二) DOM操作模块 复制元素 详解
    jQuery 源码分析(二十一) DOM操作模块 删除元素 详解
    jQuery 源码分析(二十) DOM操作模块 插入元素 详解
    jQuery 源码分析(十九) DOM遍历模块详解
    python 简单工厂模式
    python 爬虫-协程 采集博客园
    vue 自定义image组件
    微信小程序 image组件坑
  • 原文地址:https://www.cnblogs.com/zcy9838/p/13493895.html
Copyright © 2011-2022 走看看