[手把手式教程,适合新手入门Vuex]-Vuex入门实践(上)

做者:小土豆biubiubiujavascript

博客园:www.cnblogs.com/HouJiao/css

掘金:juejin.im/user/58c61b…html

简书:www.jianshu.com/u/cb1c3884e…前端

微信公众号:土豆妈的碎碎念(扫码关注,一块儿吸猫,一块儿听故事,一块儿学习前端技术) vue

欢迎你们扫描微信二维码进入群聊讨论(若二维码失效可添加微信JEmbrace拉你进群)

码字不易,点赞鼓励哟~java

前言

Vuex被称为是专为Vue应用程序开发的的状态管理模式。它的做用使用一句话描述就是:让组件之间能够共享数据webpack

话很少少,先抛开概念,咱们写一个简单的示例感觉一波。web

Vuex入门实践将分为三篇,本篇是第一篇。vuex

项目环境搭建

项目开发环境搭建请移步做者的另一篇文章 新手入门vue-教你使用vue-cli搭建项目开发环境vue-cli

本次的项目目录以下:

安装Vuex

使用Vuex前须要先进行安装,安装命令:npm install vuex --save--dev

建立和访问共享数据

使用Vuex建立全局共享数据

首先咱们先须要在E:\MyStudy\test\VueDemo\src\目录下新建一个目录vuex和文件store.js

接着在store.js中使用Vuex建立一个全局的共享数据。

// E:\MyStudy\test\VueDemo\src\vuex\store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    // 在state中建立一个全局共享的数据 counter
    state: {
        counter: 0
    }
})
复制代码

能够看到使用Vuex建立一个共享数据的语法也比较简单,即在new Vuex.Store中定义state对象,在state对象中就能够建立全局的共享数据,本次咱们建立了一个counter数据。

入口文件中配置Vuex

共享数据前面咱们已经建立好了,接着须要在入口文件main.js中配置Vuex,配置的步骤以下:

1.引入咱们编写的关于Vuex的代码模块store.js

2.在根实例上配置Vuex
复制代码
// E:\MyStudy\test\VueDemo\src\main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router/router'
//1.引入vuex
import store from './vuex/store'
Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  components: { App },
  template: '<App/>',
  router: router,
  // 2.根实例上配置vuex
  store: store
})
复制代码

组件中获取共享数据

前面咱们已经完成了两件事:使用Vuex建立共享数据counter和配置Vuex

接着咱们就须要在组件中访问这个共享数据counter

咱们先新建一个Index.vue组件,在该组件中编写访问counter的代码。

<!-- E:\MyStudy\test\VueDemo\src\components\Index.vue -->
<template>
    <div>  
        <h1>这里是Index.vue组件</h1>
        <h1>Index组件获取共享数据:{{ $store.state.counter }}</h1>
    </div>
</template>
<script> export default { name: 'Index' } </script>
复制代码

访问共享数据counter的代码为:

<h1>Index组件获取共享数据:{{ $store.state.counter }}</h1>
复制代码

接着在App.vue中编写一样的代码访问这个counter,而且在App.vue组件中将Index.vue组件引入并展现。

<!-- E:\MyStudy\test\VueDemo\src\App.vue -->
<template>
  <div id="app">
    <img src="./assets/logo.png">
    <!-- 获取共享数据 -->
    <h1>这里是App组件</h1>
    <h1> App组件获取共享数据 : {{ $store.state.counter }} </h1>
    <hr/>
    <Index></Index>
  </div>
</template>

<script> import Index from './components/Index' export default { name: 'App', components: { Index } } </script>

<style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
复制代码

浏览器查看结果

咱们分别在App.vue组件和Index.vue组件中访问了共享数据counter,如今咱们启动项目在浏览器中看下结果。

能够看到, App组件和 Index组件都可以访问到 counter的值。

到此,咱们简单的建立一个共享数据而且在组件中成功的访问到了这个共享数据,这里咱们对Vuex的使用步骤作一个小总结:

1.安装vuex:npm install vuex
2.全局配置vuex:建立vuex实例,调用store方法配置在state中建立共享数据。
3.组件中使用$store.state.counter能够访问到共享数据
复制代码

修改共享数据

定义修改共享数据的状态

Vuex中,假如须要改变共享数据,必须在Vuex实例对象的Store方法中约定这个变化。

咱们在store.js中对counter作两个约束:递增递减

// E:\MyStudy\test\VueDemo\src\vuex\store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    // 在state中建立一个全局共享的数据 counter
    state: {
        counter: 0
    },
    mutations: {
        // 递增
        increase(state) {
            state.counter++ 
        },
        // 递减
        decrement(state) {
            state.counter--
        }
    }
})

复制代码

mutations中的increase方法就是约定共享数据counter每次递增1decrement方法约定共享数据counter每次递减1

组件中触发状态变化

约束共享数据的变化已经完成了,接着就开始触发这个变化从而使共享数据发生变化。

咱们在App.vue组件中触发counter递减,在Index.vue中触发counter递增

<!-- E:\MyStudy\test\VueDemo\src\App.vue -->
<template>
  <div id="app">
    <img src="./assets/logo.png">
    <!-- 获取共享数据 -->
    <h1>这里是App组件</h1>
    <h1> App组件获取共享数据 : {{ $store.state.counter }} </h1>
    <button v-on:click="$store.commit('decrement')">点击触发共享数据counter递减1</button>
    <hr/>
    <Index></Index>
  </div>
</template>

<script> import Index from './components/Index' export default { name: 'App', components: { Index } } </script>

<style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
复制代码
<!-- E:\MyStudy\test\VueDemo\src\components\Index.vue -->
<template>
    <div>  
        <h1>这里是Index.vue组件</h1>
        <h1>Index组件获取共享数据:{{ $store.state.counter }}</h1>
        <button v-on:click="$store.commit('increase')">点击该组件触发共享数据counter递增1</button>
    </div>
</template>
<script> export default { name: 'Index' } </script>
复制代码

能够看到在组件中触发共享数据counter递增和递减的逻辑分别为:$store.commit('increase')$store.commit('decrement')

即便用$store.commit方法并传递对应的函数名称

浏览器查看结果

能够看到,点击App组件中的按钮,成功的将counter1,且Index组件中的数据也自动更新;点击Index组件中的按钮,成功的将counter1App组件中的数据也自动更新。

异步修改数据

假设咱们前面的递增递减的需求变成:点击按钮后,过3秒再去修改counter的值。那么这个时候应该怎么实现呢?

咱们直接上代码。

// E:\MyStudy\test\VueDemo\src\vuex\store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    // 在state中建立一个全局共享的数据 counter
    state: {
        counter: 0
    },
    mutations: {
        // 递增
        increase(state) {
           state.counter++    
        },
        // 递减
        decrement(state) {
           state.counter--   
        }
    },
    actions: {
        increaseAction(context){
            setTimeout(function(){
                context.commit('increase')
            }, 3000); 
        },
        decrementAction(context){
            setTimeout(function(){
                context.commit('decrement')
            }, 3000); 
        }
    }
})
复制代码

store.js中,咱们把异步修改数据的逻辑定义在actions中,而且经过提交mutations改变共享数据的状态。

那在组件中须要使用$store.dispatch对应去触发共享数据的改变。

下面咱们看一下组件中如何使用$store.dispatch

<!-- E:\MyStudy\test\VueDemo\src\App.vue&emsp; -->
<template>
  <div id="app">
    <img src="./assets/logo.png">
    <!-- 获取共享数据 -->
    <h1>这里是App组件</h1>
    <h1> App组件获取共享数据 : {{ $store.state.counter }} </h1>
    <button v-on:click="$store.dispatch('decrement')">点击等待3秒触发共享数据counter递减1</button>
    <hr/>
    <Index></Index>
  </div>
</template>

<script> import Index from './components/Index' export default { name: 'App', components: { Index } } </script>

<style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
复制代码
<!-- E:\MyStudy\test\VueDemo\src\components\Index.vue -->
<template>
    <div>  
        <h1>这里是Index.vue组件</h1>
        <h1>Index组件获取共享数据:{{ $store.state.counter }}</h1>
              <button v-on:click="$store.dispatch('increase')">点击等待3秒触发共享数据counter递增1</button>
    </div>
</template>
<script> export default { name: 'Index' } </script>
复制代码

最后,咱们在浏览器看下效果。

能够看到,setTimeout这个异步逻辑成功执行。

这里有点不同的

关于上面想要实现的异步递增和递减,咱们的第一反应可能就是在mutations中的递增递减函数添setTimeout延迟执行函数,咱们来实践一下。

App.vueIndex.vue不作任何修改,仍是前面的内容,只修改store.js

// E:\MyStudy\test\VueDemo\src\vuex\store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    // 在state中建立一个全局共享的数据 counter
    state: {
        counter: 0
    },
    mutations: {
        // 递增
        increase(state) {
            // 添加定时器执行
            setTimeout(function(){
                state.counter++
            },3000);
             
        },
        // 递减
        decrement(state) {
            //添加定时器
            setTimeout(function(){
                state.counter--
            },3000);
            
        }
    }
})
复制代码

浏览器看下结果:

能够看到效果和actions同样!!!

没办法,我这人就是想多造做造做给你们看点不同的东西。

那对于mutations官网确实有明确的说明,mutations必须是同步函数。

当我仔细读了红色框里面的内容后,我大概理解了官方文档的为何说 mutations必须是同步函数了。

缘由一:若是是异步函数,在触发mutations的时候,浏览器的调试功能看不到数据的变化;

缘由二:mutations中异步函数中的数据变化没法追踪。
复制代码

到这里呢,咱们就不继续往下探究了,由于基础的尚未总结完,基础总结完后在探究这个问题。

共享数据的计算属性

vue组件中的计算属性想必你们都知道,那么Vuex中共享数据的计算属性的用途和原理也是同vue组件中的计算属性。

咱们假设vue组件中须要对共享数据作一些其余的转换:将某个字符串进行翻转,而且转为大写。(这个场景项目中几乎不会用到,仅仅为了演示而编造的)。当多个组件都须要对某个共享数据作这样的转化时,想必写起来也会比较繁琐,所以Vuex共享数据的计算属性就帮了咱们解决这个问题。下面咱们使用Vuex的共享数据的计算属性来实现这个需求。

// E:\MyStudy\test\VueDemo\src\vuex\store.js
// 在该文件中已经将前面定义的counter删除,从新定义了一个共享数据str
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    // 在state中建立一个全局共享的数据 str
    state: {
        str: 'hello'
    },
    getters: {
        reverseAndToUpper(state){
            return state.str.split("").reverse().join("");
        }
    }
})
复制代码

关于共享数据的计算属性的访问,咱们只在App组件中添加访问代码。

<!-- E:\MyStudy\test\VueDemo\src\App.vue -->
<!-- 在App组件中,将Index组件的引入代码已经删除 -->
<template>
  <div id="app">
    <img src="./assets/logo.png">
    <!-- 获取共享数据 -->
    <h1>这里是App组件</h1>
    <h1> App组件获取共享数据 : {{ $store.getters.reverseAndToUpper }} </h1>
  </div>
</template>

<script> import Index from './components/Index' export default { name: 'App', components: { Index } } </script>

<style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
复制代码

浏览器查看一下结果:

能够看到,在App组件中已经成功的访问到了str的计算属性。

总结

前面咱们一共实践了Vuex的这些内容:

1.在state中定义共享属性,在组件中可以使用$store.state.属性名访问共享属性。

2.在mutations可中定义修改共享数据的方法,在组件中可以使用$store.commit('方法名')同步修改共享属性。

3.在actions中可定义异步修改共享数据的方法,在组件中可以使用$store.dispatch('方法名')异步修改共享属性。

4.在getters中可定义共享数据的计算属性,在组件中可以使用$store.getters.计算属性名访问共享数据的计算属性。
复制代码

那最后我在将文章最开始的图拿过来。

根据咱们前面实践的内容,你们能看懂这个状态变化吗?

做者:小土豆biubiubiu

博客园:www.cnblogs.com/HouJiao/

掘金:juejin.im/user/58c61b…

简书:www.jianshu.com/u/cb1c3884e…

微信公众号:土豆妈的碎碎念(扫码关注,一块儿吸猫,一块儿听故事,一块儿学习前端技术)

欢迎你们扫描微信二维码进入群聊讨论(若二维码失效可添加微信JEmbrace拉你进群)

码字不易,点赞鼓励哟~

相关文章
相关标签/搜索