vuex入门最详细整理


Posted in Javascript onMarch 04, 2020

如果你在使用 vue.js , 那么我想你可能会对 vue 组件之间的通信感到崩溃 。

我在使用基于 vue.js 2.0 的UI框架 ElementUI 开发网站的时候 , 就遇到了这种问题 : 一个页面有很多表单 , 我试图将表单写成一个单文件组件 , 但是表单 ( 子组件 ) 里的数据和页面 ( 父组件 ) 按钮交互的时候 , 它们之间的通讯很麻烦 :

<!--父组件中引入子组件-->
<template>
 <div>
  <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" @click="show = true">点击</a>
  <t-dialog :show.sync="show"></t-dialog>
 </div>
</template>

<script>
import dialog from './components/dialog.vue'
export default {
 data(){
  return {
   show:false
  }
 },
 components:{
  "t-dialog":dialog
 }
}
</script>


<!--子组件-->
<template>
 <el-dialog :visible.sync="currentShow"></el-dialog>
</template>

<script>
export default {
 props:['show'],
 computed:{
   currentShow:{
     get(){
       return this.show
     },
     set(val){
       this.$emit("update:show",val)
     }
   }
 }
}
</script>

之所以这么麻烦 , 是因为父组件可以通过 props 给子组件传递参数 , 但子组件内却不能直接修改父组件传过来的参数。

这时候 , 使用 vuex 就可以比较方便的解决这种问题了 :

<!--父组件中引入子组件-->
<template>
 <div>
  <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" @click="$store.state.show = true">点击</a>
  <t-dialog></t-dialog>
 </div>
</template>

<script>
import dialog from './components/dialog.vue'
export default {
 components:{
  "t-dialog":dialog
 }
}
</script>


<!--子组件-->
<template>
 <el-dialog :visible.sync="$store.state.show"></el-dialog>
</template>

<script>
export default {}
</script>

是不是方便了许多 , 这就是 vuex 最简单的应用 , 不要被网上其他教程吓到 , vuex 原来可以这么简单 !

安装、使用 vuex

首先我们在 vue.js 2.0 开发环境中安装 vuex :

npm install vuex --save

然后 , 在 main.js 中加入 :

import vuex from 'vuex'
Vue.use(vuex);
var store = new vuex.Store({//store对象
  state:{
    show:false
  }
})

再然后 , 在实例化 Vue对象时加入 store 对象 :

new Vue({
 el: '#app',
 router,
 store,//使用store
 template: '<App/>',
 components: { App }
})

完成到这一步 , 上述例子中的 $store.state.show 就可以使用了。

modules

前面为了方便 , 我们把 store 对象写在了 main.js 里面 , 但实际上为了便于日后的维护 , 我们分开写更好 , 我们在 src 目录下 , 新建一个 store 文件夹 , 然后在里面新建一个 index.js :

import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);

export default new vuex.Store({
  state:{
    show:false
  }
})

那么相应的 , 在 main.js 里的代码应该改成 :

//vuex
import store from './store'

new Vue({
 el: '#app',
 router,
 store,//使用store
 template: '<App/>',
 components: { App }
})

这样就把 store 分离出去了 , 那么还有一个问题是 : 这里 $store.state.show 无论哪个组件都可以使用 , 那组件多了之后 , 状态也多了 , 这么多状态都堆在 store 文件夹下的 index.js 不好维护怎么办 ?

我们可以使用 vuex 的 modules , 把 store 文件夹下的 index.js 改成 :

import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);

import dialog_store from '../components/dialog_store.js';//引入某个store对象

export default new vuex.Store({
  modules: {
    dialog: dialog_store
  }
})

这里我们引用了一个 dialog_store.js , 在这个 js 文件里我们就可以单独写 dialog 组件的状态了 :

export default {
  state:{
    show:false
  }
}

做出这样的修改之后 , 我们将之前我们使用的 $store.state.show 统统改为 $store.state.dialog.show 即可。

如果还有其他的组件需要使用 vuex , 就新建一个对应的状态文件 , 然后将他们加入 store 文件夹下的 index.js 文件中的 modules 中。

modules: {
  dialog: dialog_store,
  other: other,//其他组件
}

mutations

前面我们提到的对话框例子 , 我们对vuex 的依赖仅仅只有一个 $store.state.dialog.show 一个状态 , 但是如果我们要进行一个操作 , 需要依赖很多很多个状态 , 那管理起来又麻烦了 !

mutations 登场 , 问题迎刃而解 :

export default {
  state:{//state
    show:false
  },
  mutations:{
    switch_dialog(state){//这里的state对应着上面这个state
      state.show = state.show?false:true;
      //你还可以在这里执行其他的操作改变state
    }
  }
}

使用 mutations 后 , 原先我们的父组件可以改为 :

<template>
 <div id="app">
  <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" @click="$store.commit('switch_dialog')">点击</a>
  <t-dialog></t-dialog>
 </div>
</template>

<script>
import dialog from './components/dialog.vue'
export default {
 components:{
  "t-dialog":dialog
 }
}
</script>

使用 $store.commit('switch_dialog') 来触发 mutations 中的 switch_dialog 方法。

这里需要注意的是:

1、mutations 中的方法是不分组件的 , 假如你在 dialog_stroe.js 文件中的定义了

switch_dialog 方法 , 在其他文件中的一个 switch_dialog 方法 , 那么

$store.commit('switch_dialog') 会执行所有的 switch_dialog 方法。

2、mutations里的操作必须是同步的。

你一定好奇 , 如果在 mutations 里执行异步操作会发生什么事情 , 实际上并不会发生什么奇怪的事情 , 只是官方推荐 , 不要在 mutationss 里执行异步操作而已。

actions

多个 state 的操作 , 使用 mutations 会来触发会比较好维护 , 那么需要执行多个 mutations 就需要用 action 了:

export default {
  state:{//state
    show:false
  },
  mutations:{
    switch_dialog(state){//这里的state对应着上面这个state
      state.show = state.show?false:true;
      //你还可以在这里执行其他的操作改变state
    }
  },
  actions:{
    switch_dialog(context){//这里的context和我们使用的$store拥有相同的对象和方法
      context.commit('switch_dialog');
      //你还可以在这里触发其他的mutations方法
    },
  }
}

那么 , 在之前的父组件中 , 我们需要做修改 , 来触发 action 里的 switch_dialog 方法:

<template>
 <div id="app">
  <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" @click="$store.dispatch('switch_dialog')">点击</a>
  <t-dialog></t-dialog>
 </div>
</template>

<script>
import dialog from './components/dialog.vue'
export default {
 components:{
  "t-dialog":dialog
 }
}
</script>

使用 $store.dispatch('switch_dialog') 来触发 action 中的 switch_dialog 方法。

官方推荐 , 将异步操作放在 action 中。

getters

getters 和 vue 中的 computed 类似 , 都是用来计算 state 然后生成新的数据 ( 状态 ) 的。

还是前面的例子 , 假如我们需要一个与状态 show 刚好相反的状态 , 使用 vue 中的 computed 可以这样算出来 :

computed(){
  not_show(){
    return !this.$store.state.dialog.show;
  }
}

那么 , 如果很多很多个组件中都需要用到这个与 show 刚好相反的状态 , 那么我们需要写很多很多个 not_show , 使用 getters 就可以解决这种问题 :

export default {
  state:{//state
    show:false
  },
  getters:{
    not_show(state){//这里的state对应着上面这个state
      return !state.show;
    }
  },
  mutations:{
    switch_dialog(state){//这里的state对应着上面这个state
      state.show = state.show?false:true;
      //你还可以在这里执行其他的操作改变state
    }
  },
  actions:{
    switch_dialog(context){//这里的context和我们使用的$store拥有相同的对象和方法
      context.commit('switch_dialog');
      //你还可以在这里触发其他的mutations方法
    },
  }
}

我们在组件中使用 $store.state.dialog.show 来获得状态 show , 类似的 , 我们可以使用 $store.getters.not_show 来获得状态 not_show 。

注意 : $store.getters.not_show 的值是不能直接修改的 , 需要对应的 state 发生变化才能修改。

mapState、mapGetters、mapActions

很多时候 , $store.state.dialog.show 、$store.dispatch('switch_dialog') 这种写法又长又臭 , 很不方便 , 我们没使用 vuex 的时候 , 获取一个状态只需要 this.show , 执行一个方法只需要 this.switch_dialog 就行了 , 使用 vuex 使写法变复杂了 ?

使用 mapState、mapGetters、mapActions 就不会这么复杂了。

以 mapState 为例 :

<template>
 <el-dialog :visible.sync="show"></el-dialog>
</template>

<script>
import {mapState} from 'vuex';
export default {
 computed:{

  //这里的三点叫做 : 扩展运算符
  ...mapState({
   show:state=>state.dialog.show
  }),
 }
}
</script>

相当于 :

<template>
 <el-dialog :visible.sync="show"></el-dialog>
</template>

<script>
import {mapState} from 'vuex';
export default {
 computed:{
  show(){
    return this.$store.state.dialog.show;
  }
 }
}
</script>

mapGetters、mapActions 和 mapState 类似 , mapGetters 一般也写在 computed 中 , mapActions 一般写在 methods 中。

弄懂上面这些 , 你可以去看vuex文档了 , 应该能看懂了。

以上就是vuex入门最详细整理的详细内容,更多关于vuex入门知识点的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
Jquery知识点二 jquery下对数组的操作
Jan 15 Javascript
提高javascript效率 一次判断,而不要次次判断
Mar 30 Javascript
JS/FLASH实现复制代码到剪贴板(兼容所有浏览器)
May 27 Javascript
JavaScript表单验证的两种实现方法
Feb 11 Javascript
vue2.0嵌套路由实现豆瓣电影分页功能(附demo)
Mar 13 Javascript
JavaScript实现的可变动态数字键盘控件方式实例代码
Jul 15 Javascript
vue学习之mintui picker选择器实现省市二级联动示例
Oct 12 Javascript
浅谈Vue3 Composition API如何替换Vue Mixins
Apr 29 Javascript
Node.js中出现未捕获异常的处理方法
Jun 29 Javascript
Vue(定时器)解决mounted不能获取到data中的数据问题
Jul 30 Javascript
vue 解决无法对未定义的值,空值或基元值设置反应属性报错问题
Jul 31 Javascript
vue 子组件watch监听不到prop的解决
Aug 09 Javascript
JavaScript 严格模式(use strict)用法实例分析
Mar 04 #Javascript
vue 自定义组件的写法与用法详解
Mar 04 #Javascript
js找出5个数中最大的一个数和倒数第二大的数实现方法示例小结
Mar 04 #Javascript
vue请求数据的三种方式
Mar 04 #Javascript
使用Vue 自定义文件选择器组件的实例代码
Mar 04 #Javascript
JS中==、===你分清楚了吗
Mar 04 #Javascript
js数组相减简单示例【删除a数组所有与b数组相同元素】
Mar 04 #Javascript
You might like
利用php+mysql来做一个功能强大的在线计算器
2010/10/12 PHP
php连接函数implode与分割explode的深入解析
2013/06/26 PHP
php float不四舍五入截取浮点型字符串方法总结
2013/10/28 PHP
php遍历类中包含的所有元素的方法
2015/05/12 PHP
利用PHP访问带有密码的Redis方法示例
2017/02/09 PHP
PHP魔术方法之__call与__callStatic使用方法
2017/07/23 PHP
php+mysql开发的最简单在线题库(在线做题系统)完整案例
2019/03/30 PHP
JavaScript使用prototype定义对象类型
2007/02/07 Javascript
JQuery跨Iframe选择实现代码
2010/08/19 Javascript
iframe父页面获取子页面参数的方法
2014/02/21 Javascript
基于jQuery实现仿淘宝套餐选择插件
2015/03/04 Javascript
jQuery使用prepend()方法在元素前添加内容用法实例
2015/03/26 Javascript
JavaScript中使用Math.PI圆周率属性的方法
2015/06/14 Javascript
微信小程序 wxapp内容组件 text详细介绍
2016/10/31 Javascript
微信小程序项目总结之点赞 删除列表 分享功能
2018/06/25 Javascript
对angularJs中controller控制器scope父子集作用域的实例讲解
2018/10/08 Javascript
Vue 全家桶实现移动端酷狗音乐功能
2018/11/16 Javascript
微信小程序canvas.drawImage完全显示图片问题的解决
2018/11/30 Javascript
利用Node.js如何实现文件循环覆写
2019/04/05 Javascript
layui异步加载table表中某一列数据的例子
2019/09/16 Javascript
js实现多图和单图上传显示
2019/12/18 Javascript
微信小程序自定义modal弹窗组件的方法详解
2020/12/20 Javascript
django初始化数据库的实例
2018/05/27 Python
通过python扫描二维码/条形码并打印数据
2019/11/14 Python
HTML5 Canvas实现放大镜效果示例
2020/03/25 HTML / CSS
软件测试常见笔试题
2012/02/04 面试题
预备党员的自我评价
2014/03/12 职场文书
交通安全寄语大全
2014/04/08 职场文书
感恩老师的演讲稿
2014/05/06 职场文书
小学生学习雷锋倡议书
2014/05/15 职场文书
银行求职自荐书
2014/06/25 职场文书
个人催款函范文
2015/06/24 职场文书
2015年学校教研室主任工作总结
2015/07/20 职场文书
新手入门Mysql--概念
2021/06/18 MySQL
MySql按时,天,周,月进行数据统计
2022/08/14 MySQL
MySQL 原理与优化之Update 优化
2022/08/14 MySQL