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 相关文章推荐
Javascript 面向对象之重载
May 04 Javascript
js事件(Event)知识整理
Oct 11 Javascript
基于jquery实现的图片在各种分辨率下未知的容器内上下左右居中
May 11 Javascript
JavaScript判断IE版本型号
Jul 27 Javascript
JavaScript对象参数的引用传递
Jan 14 Javascript
scroll事件实现监控滚动条并分页显示(zepto.js)
Dec 18 Javascript
JavaScript提高加载和执行效率的方法
Feb 03 Javascript
vue基于Element构建自定义树的示例代码
Sep 19 Javascript
微信小程序日期选择器实例代码
Jul 18 Javascript
vue 中滚动条始终定位在底部的方法
Sep 03 Javascript
vue mounted 调用两次的完美解决办法
Oct 29 Javascript
解决vue请求接口第一次成功,第二次失败问题
Sep 08 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
php执行sql语句的写法
2009/03/10 PHP
php程序内部post数据的方法
2015/03/31 PHP
使用xampp搭建运行php虚拟主机的详细步骤
2015/10/21 PHP
JavaScript实现url地址自动检测并添加URL链接示例代码
2013/11/12 Javascript
什么是cookie?js手动创建和存储cookie
2014/05/27 Javascript
一个css与js结合的下拉菜单支持主流浏览器
2014/10/08 Javascript
jQuery选择器源码解读(六):Sizzle选择器匹配逻辑分析
2015/03/31 Javascript
javascript实现的固定位置悬浮窗口实例
2015/04/30 Javascript
使用基于Node.js的构建工具Grunt来发布ASP.NET MVC项目
2016/02/15 Javascript
基于javascript html5实现多文件上传
2016/03/03 Javascript
在Node.js中使用Javascript Generators详解
2016/05/05 Javascript
详解微信小程序开发之下拉刷新 上拉加载
2016/11/24 Javascript
Bootstrap源码解读媒体对象、列表组和面板(10)
2016/12/26 Javascript
jQuery Validate表单验证插件的基本使用方法及功能拓展
2017/01/04 Javascript
jQuery实现图片上传预览效果功能完整实例【测试可用】
2018/05/28 jQuery
详解Vue中数组和对象更改后视图不刷新的问题
2018/09/21 Javascript
Vue核心概念Action的总结
2019/01/18 Javascript
在vue项目中使用Jquery-contextmenu插件的步骤讲解
2019/01/27 jQuery
JavaScript中的ES6 Proxy的具体使用
2019/06/16 Javascript
vue动态配置模板 'component is'代码
2019/07/04 Javascript
vue 验证码界面实现点击后标灰并设置div按钮不可点击状态
2019/10/28 Javascript
node.js express捕获全局异常的三种方法实例分析
2019/12/27 Javascript
[00:43]TI7不朽珍藏III——幽鬼不朽展示
2017/07/15 DOTA
python的常见命令注入威胁
2013/02/18 Python
Python基于分析Ajax请求实现抓取今日头条街拍图集功能示例
2018/07/19 Python
详解python:time模块用法
2019/03/25 Python
python实现计数排序与桶排序实例代码
2019/03/28 Python
canvas中普通动效与粒子动效的实现代码示例
2019/01/03 HTML / CSS
英国在线女鞋目的地:SIMMI
2018/12/27 全球购物
Onzie官网:美国时尚瑜伽品牌
2019/08/21 全球购物
学习雷锋标语
2014/06/25 职场文书
过程装备与控制工程专业求职信
2014/07/02 职场文书
超市工作总结范文2014
2014/12/19 职场文书
怎样写工作总结啊!
2019/06/18 职场文书
HTML+CSS+JS实现图片的瀑布流布局的示例代码
2021/04/22 HTML / CSS
python可视化大屏库big_screen示例详解
2021/11/23 Python