nuxt踩坑之Vuex状态树的模块方式使用详解


Posted in Javascript onSeptember 06, 2019

初次看到这个模块方式,感觉很是新奇,之前的vuex状态树使用方法用的也有些腻了,就想来实践一发新的东西

废话不多说,直接进入正题

Vuex状态树-模块方式官方文档解读

状态树还可以拆分成为模块,store 目录下的每个 .js 文件会被转换成为状态树指定命名的子模块

  1. 这句话啊,看了半天,我都没绕出来。之前一直用的是store目录下文件为:index.js、state.js、mutations.js、actions.js。后三个是index.js的子模块,你说这每个js文件都是一个模块?懵逼一分钟
  2. 继续往下:使用状态树模块化的方式,store/index.js 不需要返回 Vuex.Store 实例,而应该直接将 state、mutations 和 actions 暴露出来。 到这里我虽然还懵逼着,但是转念一想,nuxt还有这操作,都不用我们自己辛辛苦苦写export default store = () => new Vuex.Store({}) 了,倒也真的省事儿呢
  3. 还是继续看例子吧,官方给的这个,看了一遍没看懂(笨小孩的世界真滴难),你这index.js不是Vuex默认的store文件么,再来一todos.js,同样暴露出去的对象,不应该是index.js同级的么
  4. 重点来了,看不会不要紧,照猫画虎我还是会滴~

照猫画虎

// store/index.js
export const state = () => ({
 num: 0
})
 
export const mutations = {
 increment (state) {
  state.num ++
 },
 decrement (state) {
  state.num --
 }
}
 
 
// store/plus.js
export const state = () => ({
 plusNum: 1
})
 
export const mutations = {
 plus (state) {
  state.plusNum ++
 }
}
 
// store/minus.js
export const state = () => ({
 minusNum: 10
})
 
export const mutations = {
 minus (state) {
  state.minusNum --
 }
}
 
// pages/store.vue
<template>
 <section class="container">
  <table>
    <tr>
      <td colspan=4>vuex状态树使用</td>
    </tr>
    <tr>
      <td>页内数据</td>
      <td>index.js</td>
      <td>plus.js</td>
      <td>minus.js</td>
    </tr>
    <tr>
      <td>{{ count }}</td>
      <td>{{ $store.state.num }}</td>
      <td>{{ $store.state.plus.plusNum }}</td>
      <td>{{ $store.state.minus.minusNum }}</td>
    </tr>
    <tr>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
    </tr>
  </table>
 </section>
</template>

跑一下,唷!报错了,我说同学们啊,我写的真的没有错!!!

好吧,报错内容:[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.

意思是我客户端和vue SSR生成的DOM不一样,客户端不也是SSR生成的,这是个问题,有知道的大佬,希望可以告诉我。

不过这个问题我倒是解决了,虽然不知道问什么-_-!,把那一大堆的tr标签都放到tbody里面就OK了

跑起来,没问题,按示例的写法,这样成功拿到了state的数据

接着试试mutation的方法

<tr class="mutation-fun">
  <td @click="count ++">count ++</td>
  <td @click="$store.commit('increment')">increment</td>
  <td @click="$store.commit('plus')">plus</td>
  <td @click="$store.commit('minus')">minus</td>
</tr>

报错:[vuex] unknown mutation type: plus

修改下:

<tr class="mutation-fun">
  <td @click="count ++">count ++</td>
  <td @click="$store.commit('increment')">increment</td>
  <td @click="$store.commit('plus/plus')">plus/plus</td>
  <td @click="$store.commit('minus/minus')">minus/minus</td>
</tr>

搞定~

自己先小结下这个模块怎么用的吧

nuxt很贴心的帮我们省去了返回Vuex实例的代码,我们可以不用去写了
只有store文件夹下的index.js是一级的vuex状态,其他的js文件都是二级的状态树。(能不能有三级的我不知道,不过感觉没必要,哈哈哈!!)

每个状态树文件都可以包含state,mutation,action

使用二级状态树的state用: $store.state.文件名.变量名

使用二级状态树的mutation用: $store.commit(‘文件名/变量名')

使用二级状态树的action用: $store.dispatch(‘文件名/变量名')

官方示例没有提到的

二级状态树能调用一级状态树的state和mutation以及action吗?

我们来给plus.js增加一个修改index.js中的state的方法plusIndex

export const state = () => ({
 plusNum: 1
})
 
export const mutations = {
 plus (state) {
  state.plusNum ++
 },
 plusIndex (state) {
  state.num ++
  console.log('点击递增index的num')
 }
}

去试着调用了一下,文本打印出来了,也没有报错,但是完全获取不到index中的num哇~~

这次聪明点儿,我直接把state打印出来:

export const state = () => ({
 plusNum: 1
})
 
export const mutations = {
 plus (state) {
  state.plusNum ++
 },
 plusIndex (state) {
  console.log('state: ', state)
  state.num ++
 }
}

跑一下试试: 结果有点儿让人想哭:state: {num: NaN, plusNum: 1}。再看看页面上index.js对应的num依然是0,这就说明我们这里的num不是index.js里的num,而是下面state ‘.'(点)出来的num,并且没有给初始值就执行了一次 ++ ,所以值为NaN

到这里,我已经大概猜测到了这里的弯弯绕是怎么回事儿了 ?> 模块儿的作用域是本文件内。但编程不是靠猜的,要用实践证明的才是对的,下面在深究这个问题

反过来,一级状态树能调用二级状态树的state和mutation以及action吗?

这里的情况跟上面一样,既然我们的这个store是模块方式生成的,那就要遵循模块化的规范,变量作用域只能在文件内

通过模块化编程规范来获取一级状态树的state

先把index.js引过来,因为不放心引用过来的还是不是原来那个index.js,所以把它打印出来看看

const indexVuex = require('./index.js')
console.log('indexVuex: ', indexVuex)

这下不就炸了嘛,我引过来的居然是一个空的vuex状态树!!!内容长这样子

{
  mutation: {},
  modules: {
    plus: {
      mutation: {},
      namespaced: true
    },
    minus: {
      mutation: {},
      namespaced: true
    }
  },
  namespaced: true
}

好吧,我这个用模块化的方式来使用其他文件内的变量的想法也是泡汤了

最后的让步,我在组件中调用状态树时再去用二级状态树的方法修改一级状态树的state,先试试:

// plus.js
export const state = () => ({
 plusNum: 1
})
 
export const mutations = {
 plus (state) {
  state.plusNum ++
 },
 plusIndex (state, meio) {
  meio ++
  console.log('meio: ', meio)
 }
}
 
// 调用:
<td @click="$store.commit('plus/plusIndex', $store.state.num)">递增index的num</td>

点击后,依然没能修改index.js中的num,查看打印结果中一直都是1,也就是说我们传进去的是基本数据类型的0~~

那修改一下,我们传进去一个引用数据类型的看看可以不

// plus.js
export const state = () => ({
 plusNum: 1
})
 
export const mutations = {
 plus (state) {
  state.plusNum ++
 },
 plusIndex (state, meio) {
  meio.num ++
  console.log('meio: ', meio.num)
 }
}
 
// 调用:
<td @click="$store.commit('plus/plusIndex', $store.state)">递增index的num</td>

功夫不负有心人,终于是成功了,虽然这样很麻烦,但也起到了效果

这里经验证:反过来一级状态树调用二级状态树也是一样的,代码就不贴了

小结一下

  1. vuex状态树的模块写法,不同的文件之间不能直接引用
  2. vuex状态树使用模块加载引用,得到的是一组命名空间,而不是最终生成的Vuex模块文件
  3. 要通过b文件修改其他文件的state需要在store外部去修改

最后,小小的STAR下

情境(situation):粗略的看完一遍NUXT的官方文档,回头把不太清楚的东西再整理一下,这儿就卡在Vuex状态树的的模块写法上

任务(task):通过各种方法弄明白NUXT的Vuex状态树的模块写法是怎么实现的

行动(action):第一步,参照官方示例先让自己的状态树能运行起来;第二步,与普通写法的状态树写法比较并举一反三,看看模块写法和普通写法的状态树在使用上有什么区别和需要注意的

结果(result):第一,学会了vuex状态树的模块写法和用法;第二,通过探索store目录下的不同文件之间是否可以互相引用以及模块引用来熟悉模块方式的写法和普通方式的区别,也找到了模块写法中修改其他模块的state的方法;第三,模块写法的优点:写法简单,结构清晰明了,符合现在模块化开发;同文件(模块)内部类似普通写法,可按业务模块划分Vuex模块,提高开发效率;还有一点儿,我觉得这样写省事儿,也好看-,-| 妈妈再也不用担心我所有的Vuex都放同一个文件中,要用时还得找半天了~~

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
在网页中控制wmplayer播放器
Jul 01 Javascript
List all the Databases on a SQL Server
Jun 21 Javascript
window.open被浏览器拦截后的自定义提示效果代码
Nov 19 Javascript
javascript控制Div层透明属性由浅变深由深变浅逐渐显示
Nov 12 Javascript
从零学JS之你需要了解的几本书
May 19 Javascript
js实现的星星评分功能函数
Dec 09 Javascript
AngularJs bootstrap搭载前台框架——准备工作
Sep 01 Javascript
移动端触摸滑动插件swiper使用方法详解
Aug 11 Javascript
AngularJS遍历获取数组元素的方法示例
Nov 11 Javascript
vue form 表单提交后刷新页面的方法
Sep 04 Javascript
vue中实现Monaco Editor自定义提示功能
Jul 05 Javascript
vue中destroyed方法的使用说明
Jul 21 Javascript
Nuxt使用Vuex的方法示例
Sep 06 #Javascript
vue中input的v-model清空操作
Sep 06 #Javascript
nuxt框架中对vuex进行模块化设置的实现方法
Sep 06 #Javascript
layui 表格操作列按钮动态显示的实现方法
Sep 06 #Javascript
基于Vue和Element-Ui搭建项目的方法
Sep 06 #Javascript
微信小程序 搜索框组件代码实例
Sep 06 #Javascript
layui加载表格,绑定新增,编辑删除,查看按钮事件的例子
Sep 06 #Javascript
You might like
上海无线电三厂简史修改版
2021/03/01 无线电
用PHP读注册表
2006/10/09 PHP
PHP中cookies使用指南
2007/03/16 PHP
php文件夹的创建与删除方法
2015/01/24 PHP
laravel多条件查询方法(and,or嵌套查询)
2019/10/09 PHP
基于ThinkPHP删除目录及目录文件函数
2020/10/28 PHP
基于jquery的合并table相同单元格的插件(精简版)
2011/04/05 Javascript
40个有创意的jQuery图片和内容滑动及弹出插件收藏集之二
2011/12/31 Javascript
jquery中交替点击事件toggle方法的使用示例
2013/12/08 Javascript
js 去除字符串第一位逗号的方法
2014/06/07 Javascript
node.js中的querystring.parse方法使用说明
2014/12/10 Javascript
node.js中的fs.readdir方法使用说明
2014/12/17 Javascript
js正则表达式匹配数字字母下划线等
2015/04/14 Javascript
jstree的简单实例
2016/12/01 Javascript
详解react-router如何实现按需加载
2017/06/15 Javascript
记录一篇关于redux-saga的基本使用过程
2018/08/18 Javascript
vue vue-Router默认hash模式修改为history需要做的修改详解
2018/09/13 Javascript
纯javascript前端实现base64图片下载(兼容IE10+)
2018/09/14 Javascript
2019 年编写现代 JavaScript 代码的5个小技巧(小结)
2019/01/15 Javascript
uni app仿微信顶部导航条功能
2019/09/17 Javascript
详解微信小程序入门从这里出发(登录注册、开发工具、文件及结构介绍)
2020/07/21 Javascript
js实现验证码干扰(动态)
2021/02/23 Javascript
Python读取stdin方法实例
2019/05/24 Python
使用python进行广告点击率的预测的实现
2019/07/04 Python
python:按行读入,排序然后输出的方法
2019/07/20 Python
Django url 路由匹配过程详解
2021/01/22 Python
米兰必去买手店排行榜首位:Antonioli
2016/09/11 全球购物
Omio荷兰:预订火车、巴士和机票
2018/11/04 全球购物
匈牙利超级网上商店和优惠:Alza.hu
2019/12/17 全球购物
本科毕业生专业自荐书范文
2014/02/05 职场文书
企业管理毕业生求职信
2014/03/11 职场文书
初中学生评语大全
2014/04/24 职场文书
市委常委会班子党的群众路线教育实践活动整改方案
2014/10/25 职场文书
毕业生入职感言
2015/07/31 职场文书
一篇文章搞懂python混乱的切换操作与优雅的推导式
2021/08/23 Python
JavaScript 数组去重详解
2021/09/15 Javascript