Vuex(vue) / Flux (angular) /Redux(react)

vuex 是什么?

  • 状态管理工具

  • 状态即数据, 状态管理就是管理组件中的data数据

  • Vuex 中的状态管理工具,采用了 集中式 方式统一管理项目中组件之间需要通讯的数据

  • [看图]

如何使用

  • 最佳实践 : 只将组件之间共享的数据放在 vuex 中, 而不是将所有的数据都放在 vuex 中 ,
  • 也就是说:如果数据只是在组件内部使用的,这个数据应该放在组件中,而不要放在 vuex
  • vuex 中的数据也是响应式的,也就是说:如果一个组件中修改了 vuex 中的数据,另外一个使用的 vuex 数据的组件,就会自动更新 ( vuex 和 localstorage的区别)

什么时候用 ?

  • 官网

  • 说明: 项目体量很小,不需要使用 vuex, 如果项目中组件通讯不复杂,也不需要使用 vuex

  • 只有写项目的时候,发现组件通讯多,组件之间的关系复杂,项目已经无法继续开发了,此时,就应该使用 vuex

Vuex的基本使用

1. vuex的基本使用

  • 引入文件
<script src="vue.js"></script>
<script src="./vuex.js"></script>
  • 使用 vuex 插件
// 和 router 一样 在工程化项目中  需要使用 use 安装一下
Vue.use(vuex)
  • 创建 store
const store = new Vuex.Store()
  • 关联 vm 和 store
const vm = new Vue({store,       // 关联 storeel: '#app',})

2. state

vuex通过state来提供数据 类似于组件的data

  • 创建store的时候,可以指定state
 const store = new Vuex.Store({//1. state 是 vuex 用于提供数据的地方, 类似于组件的data , state中存放的是组件共享的数据//2. 在所有的组件, 都可以通过 this.$store.state 就能够访问vuex中state的数据//3. 只要vuex中state的数据发生了变化, 就会更新所有的组件 state: {name: 'hello',money: 1000,},})
  • 可以在任意组件的模板中,访问到vuex中state的数据
<p>{{ $store.state.name }}</p>
<p>{{ $store.state.money }}</p>
  • 事件中
created() {console.log(this.$store.state.name)console.log(this.$store.state.money)},

3. mutation

####3.1 演示报错

  • 演示1 - 添加严格模式
const store = new Vuex.Store({strict: true,         # 添加严格模式state: {name: 'hello',money: 1000,},
})
  • 演示2 : 修改
<p @click="changeName">{{ $store.state.name }}</p>
changeName() {this.$store.state.name = '马哥'console.log(this.$store.state.name)
},
# 报错 :    [vuex] do not mutate vuex store state outside mutation handlers."
# 说明 : vuex中的数据不能直接修改, 需要在 mutation 里面才可以修改

3.2 mutation使用

  • 创建store的时候,需要提供mutations
const store = new Vuex.Store({state:{},mutations :{}  # 添加
})
  • mutation中所有的方法第一个参数都是state, 可以修改state里面的数据
// vuex 的 store
mutations : {// 修改 namechangeName(state) {state.name = '马哥'console.log(state.name)},// 修改 moneychangeMoney(state) {state.money++console.log(state.money)},
}
  • 组件中不能直接修改state,但是可以提交mutation,类似于子组件触发事件
// 在点击的事件中 触发事件 =>提交 mutation// 点击事件
<p @click="changeName">{{ $store.state.name }}</p>
<p @click="changeMoney">{{ $store.state.money }}</p>
// vm 实例中methods: {changeName(state) {this.$store.commit('changeName')},changeMoney(state) {this.$store.commit('changeMoney')},},

4. vuex 传参

  • 传参
// 提交
this.$store.commit('changeName', {name: '6哥',})
  • 接收
// vuex 的 mutations   接收 参数
changeName(state, payload) {state.name = payload.name},

Todos 改造

Todos码云地址:https://gitee.com/wang_yu5201314/tudos_potato_silk_case

1. 初始化项目

  • 创建项目
vue create vuex-todos
  • 组件化开发

    1. 把结构和样式都拷贝过来并且引入
    2. 组件分为三个组件 : TodoHeader TodoList TodosFooter
// App.vue
import TodoHeader from "./components/TodoHeader.vue";
import TodoList from "./components/TodoList.vue";
import TodoFooter from "./components/TodoFooter.vue";export default {components: {TodoHeader,TodoList,TodoFooter}
};// 结构
<section class="todoapp"><!-- 头部 --><todo-header></todo-header><!-- 主体 --><todo-list></todo-list><!-- 底部 --><todo-footer></todo-footer></section>

2. 配置 vuex

  • 安装 vuex :
npm i vuex
  • 创建 store/index.js
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)    // 安装const state = {list: [{ id: 1, name: '吃饭', done: true },{ id: 2, name: '睡觉', done: true },{ id: 3, name: '打豆', done: false },],
}const store = new Vuex.Store({state,
})export default store

Todos 步骤

##1. 列表展示

<li :class="{completed : item.done}" v-for="item in $store.state.list" :key="item.id"><div class="view"><input class="toggle" type="checkbox" checked v-model="item.done" /><label>{{ item.name }}</label><button class="destroy"></button></div><input class="edit" value="Create a TodoMVC template" /></li>

##2. 删除任务

// vue 注册点击删除事件
del(id) {this.$store.commit("del", { id });
}// vuex  store
// mutations
const mutations = {del(state, playload) {let { id } = playloadstate.list = state.list.filter(v => v.id !== id)},
}

##3. 添加任务

// vue<inputv-model="todoName"                        # ++@keyup.enter="addTodo"                    # ++class="new-todo"placeholder="What needs to be done?"autofocus/>data() {return {todoName: ""                              # ++};},methods: {addTodo() {this.$store.commit("add", {name: this.todoName});this.todoName = "";}}// vuex
const mutations = {// 添加add(state, playload) {state.list.unshift({id: Date.now(),name: playload.name,done: false,})},
}

##4. 修改任务

  • 显示编辑框
//1. 准备 editId
data() {return {editId: -1};},
//2. 判断
<li  :class="{completed : item.done ,editing : item.id === editId }">
//3. 双击显示showEdit(id) {this.editId = id;}
  • 回车 - 修改数据
// vue
<input class="edit" :value="item.name" @keyup.enter="hideEdit(item.id,$event)" />hideEdit(id, e) {this.$store.commit("updateName", {id,name: e.target.value});this.editId = -1;} // vuex
const mutations = {// 修改nameupdateName(state, playload) {let { id, name } = playloadlet todo = state.list.find(v => v.id === id)todo.name = name},
}

5. 修改状态

// vue<inputclass="toggle"type="checkbox":checked="item.done"@change="iptChange(item.id,$event)"/>
iptChange(id, e) {console.log(e.target.checked);this.$store.commit("iptChange", {id,checked: e.target.checked});}// vuex// 更新状态iptChange(state, playload) {let { id, checked } = playloadlet todo = state.list.find(v => v.id === id)todo.done = checked                                  # todo.done},

##6. 计算属性(三个)

// 计算属性
const getters = {// 底部的显示与隐藏isFooterShow(state) {return state.list.length > 0},// 剩余未完成数itemLeftCount(state) {return state.list.filter(v => !v.done).length},// 是否显示清除已完成isClearCompletedShow(state) {let b = state.list.some(v => v.done)console.log(b)return state.list.some(v => v.done)},
}

##7. 清除已经完成的任务

// vue<!-- 清除已完成 --><buttonclass="clear-completed"@click="$store.commit('clear')"v-show="$store.getters.isClearCompletedShow">Clear completed</button>// vuexclear(state) {state.list = state.list.filter(v => !v.done)},

Action 的使用

  • 官网介绍
  • Action 类似于 mutation,不同在于:
    • Action 可以包含任意异步操作。
    • Action 提交的是 mutation,而不是直接变更状态。
  • mutaions 里不只能使用同步,不能出现异步 (演示删除任务 里使用setTimeout 会报错)
  • 演示1: actions 可以包含任意异步操作。 代码1
  • 演示2: actions 不能直接变更状态 , 代码2 会报错
  • 演示3 : actions 提交的是 mutation
// vuethis.$store.dispatch("addAsync", {name: this.todoName});// vuex -  actions
const actions = {// 添加 - 异步// store == contextaddAsync(context, playload) {setTimeout(() => {context.commit('add', playload)}, 3000)},
}// 添加add(state, playload) {state.list.unshift({id: Date.now(),name: playload.name,done: false,})},

几个辅助函数

1. mapState

当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。

我们可以使用 mapState 辅助函数 将 store 中的 state 映射到局部计算属性

  • 引入 mapState
import { mapState } from "vuex";
  • 数组形式
// 如果本来就是有 计算属性 computed ,就不能全部使用 mapState 了
// 使用对象展开运算符将 state 混入 computed 对象中
computed: {// ....  之前 vue 里面的getTotal(){}// 维护 vuex...mapState(['list'])},let arr1 = [1,2,3]
let arr = [a,...arr1]let obj1 = { list : [] }
let obj = { name : '马哥', ...obj1 }
  • **对象形式 **- 取个名字
computed: {// ....  之前 vue 里面的// 维护 vuex...mapState({l :'list'})},

2. mapGetters

mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性

使用展开运算符将 getter 混入 computed 对象中

  • 引入
import { mapGetters } from "vuex";
  • 数组形式
computed: {// .... 之前 vue 的//  维护  vuex// 将  this.isFooterShow  映射为 this.$store.getters.isFooterShow...mapGetters(["isFooterShow", "itemLeftCount", "isClearCompletedShow"])}
// 使用
v-show="isFooterShow"
<strong>{{ itemLeftCount }}</strong> item left
  • 对象形式

如果你想将一个 getter 属性另取一个名字,使用对象形式

computed: {// .... 之前 vue 的//  维护  vuex...mapGetters(["isFooterShow", "itemLeftCount"]),...mapGetters({// 把 `this.isShow` 映射为 `this.$store.getters.isClearCompletedShow`isShow: "isClearCompletedShow"       //  ==> 起名字 })
}// 使用
<button  v-show="isShow">Clear completed</button>

2. mapMutations

使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store

  • 引入
import { mapState, mapMutations } from "vuex";
  • 数组形式
methods: {// 讲 this.del() 映射为  this.$store.commit('del')...mapMutations(['del','showEdit','hideEdit','iptChange'])
}del(id) {// this.$store.commit("del", { id });this.del({id})    // 会造成死循环  => 改名字 },
  • 对象形式 :

如果你想将一个 methods 方法另取一个名字,使用对象形式

 methods: {// 将 this.del() 映射为  this.$store.commit('del')...mapMutations(["showEdit", "hideEdit", "iptChange"]),//  可以全部取名字 也可以改一个名字  // 将 this.d() 映射为  this.$store.commit('d')  ...mapMutations({d: "del"}),del(id) {// this.$store.commit("del", { id });this.d({ id });}}

3. mapActions

使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用

  • 引入
import { mapActions } from "vuex";
  • 数组形式
  methods: {// 将 this.addAsync() 映射为 this.$store.dispatch('addAsync')...mapActions(["addAsync"]),addTodo() {this.addAsync({name: this.todoName});this.todoName = "";}}
  • 对象形式
 methods: {// // 将 this.a() 映射为 this.$store.dispatch('addAsync')...mapActions({a: "addAsync"}),addTodo() {this.a({name: this.todoName});this.todoName = "";}}

头条-vuex-动态设置keep-alive

  1. 设置 keep-alive的include属性改字符串为数组形式
// App.vue
// 之前   name 组件名
<keep-alive include='home' ></keep-alive>// 改之后
<keep-alive :include="['home']" ></keep-alive>// 动态绑定
<keep-alive :include="cachelist" ></keep-alive>// 数据
data(){return {cachelist : ['home']}
}
  1. cachelist 放到 vuex

配置 vuex

const store = new Vuex.Store({state: {cachelist: ['home'],},
})
  • 使用
// App.vue
computed: {...mapState(['cachelist'],
},<keep-alive :include="cachelist"><router-view></router-view>
</keep-alive>
  1. 需求 :
缓存首页的思路:1. 只要进入到首页,就应该把首页给缓存起来。2. 离开首页的时候,需要判断了, 如果进入的是详情页,home组件依旧要被缓存。3. 离开首页的时候, 如果进入的不是详情页,home组件就不应该被缓存。
  1. 添加两个 mutations的方法
  mutations: {cache(state, playload) {// 如果缓存列表里面没有 name 就添加进去if (!state.cachelist.includes(playload.name)) {state.cachelist.push(playload.name)}},uncache(state, playload) {// 如果缓存列表里面 有 name , 就删除if (state.cachelist.includes(playload.name)) {state.cachelist = state.cachelist.filter(v => v !== playload.name)   # 易错点}},},
  1. 组件内导航守卫 - beforeRouteEnter - 进入之前
// Home.vue
import store from 'store'// 路由跳转之前
beforeRouteEnter (to, from, next) {// this.$store.commit('cache')   this 无法访问 因为还没有进入// 进入 home 把 home 添加到缓存列表store.commit('cache',{name :'home'})next()
}
  1. 组件内导航守卫 - beforeRouteLeave - 离开之前
// Home.vue
// 离开 home 之前beforeRouteLeave(to, from, next) {if (to.name === 'tabedit') {// 移除store.commit('uncache', {name: 'home',})}next()},

Vuex说明及Todos项目改造相关推荐

  1. vue项目改造nuxt(SEO优化)

    欢迎大家进群,一起探讨学习 微信公众号,每天给大家提供技术干货 博主技术笔记 博主网站地址1 博主网站地址2 博主开源微服架构前后端分离技术博客项目源码地址,欢迎各位star 1. 背景 今年开源了一 ...

  2. 公司老项目改造适配不同分辨率2k、3k、4k

    项目改造适配不同分辨率 最近公司要做项目适配2k.3k.4k屏的分辨率,在网上找了很多中方案,常用且方便的是使用zoom全局缩放,因为是老项目所以对样式进行了重写整体使用了flex+百分比布局 使用 ...

  3. 关于华为私有云部署若依springcloud微服务项目改造及部署

    关于华为私有云部署若依springcloud微服务项目改造及部署 1.项目介绍 ​ 当前微服务项目主流的注册中心为阿里巴巴的nacos,但介于甲方要求使用华为的注册中心,所以在接下来讲解项目改造: 2 ...

  4. vuex modules ajax,VUE项目爬坑---6、vuex的真正存在的意义是什么

    VUE项目爬坑---6.vuex的真正存在的意义是什么 一.总结 一句话总结: a.[避免低效的数据传递]:当多个组件嵌套的时候,只能父子传递,那么中间的组件只能做传递数据之用,数据不是它用,它却传递 ...

  5. Vue现有项目改造为Nuxt项目

    公司项目,最初只为了实现前后端分离式开发,直接选择了vue框架进行开发,然而现在项目基本完成了,发现蜘蛛根本就抓取不到网站数据,搜索引擎搜出来,都是一片空白没有数据,需要对项目做SEO优化. 本人第一 ...

  6. 8/人天,小记一次 JAVA(APP后台) 项目改造 .NET 过程(后台代码已完整开源于 Github)...

    Github: https://github.com/iccb1013/Jade.Net 我们只消耗了8/人天的时间,完成了全部工作,基于我们 Jade.Net 的开源后台代码,任何小规模的后台管理系 ...

  7. vue项目转换服务器端渲染,vue-server-renderer实现vue项目改造服务端渲染

    这是一篇教程,从创建项目到改造项目 vue-cli创建一个项目 在放你做demo的地方,创建一个项目 vue create vue-ssr // 如果你安装了vue-cli4,选择vue2的版本,以下 ...

  8. spring boot单模块项目改造成多模块项目

    用idea创建项目,默认是单模块项目的.如果一个项目比较大,包含多个子系统,可能会有一些公共的东西,独立出来,在几个子系统中使用.这时候应该用多模块(Module)项目,所有子系统,以及公共模块,都在 ...

  9. vue2-ssr从vue-cli搭建项目改造服务端渲染+打包上线部署

    为了完成vue+ssr,本人呕心沥血翻阅很多博主的文档,并在b站看了很多视频之后,经过个人实践,终于整理出一套完整版,无缺失,不报错的改造流程(亲测!!) 从创建=>打包=>上线部署,详细 ...

最新文章

  1. c语言大学程序设计题库,黑龙江大学C语言程序设计试题库程序单选
  2. arch linux引导不启动_Linux 内核源代码的目录结构
  3. 盛大创新院赞助首届.NET技术交流会即将召开
  4. 搭建SVN版本控制服务器
  5. [elixir! #0037] Agent 小传
  6. catia 桥接曲面圆角_4.3.7.1-Catia曲面之多桥接曲面_简单构面
  7. ppt复制切片器_这6个新手必学的PPT技能,让你效率提升10倍!套模板都比别人快...
  8. 音视频技术开发周刊 | 183
  9. jQuery插件ASP.NET应用之AjaxUpload
  10. java泛型方法 通配符_Java泛型教程–示例类,接口,方法,通配符等
  11. Android应用第一次安装成功点击“打开”后Home键切出应用后再点击桌面图标返回导致应用重启问题...
  12. 英国反垄断监管机构将对音乐流媒体市场展开调查
  13. 0x68111002_黑苹果10.12.2驱动R9 270显卡成功一例
  14. 数据预处理01_脏数据产生的原因
  15. SP_Flash_Tool_For_win10
  16. Java8 stream toMap 解决 key 冲突
  17. 系统自带测试软件,无需鲁大师检测!Windows自带工具检查系统健康度
  18. 创建windows虚拟机详细教程
  19. 怎样从 Google Play 下载 Android 程序到电脑上
  20. win10解决cmd无法切换盘符的问题

热门文章

  1. HDU 1159.Common Subsequence【动态规划DP】
  2. 卷积神经网络经典模型要点
  3. 原来信用卡肉这么肥,怪不得银行天天给你发短信叫你办理
  4. 与鬼古女夜晚后海边的“恐怖”聚会
  5. VGA显示器驱动设计与验证
  6. RHEL 6.0安装Qt
  7. REHL yum的配置(本地和centos源)
  8. 将1bpp的bmp图像存储为1bpp或者2bpp的tiff格式
  9. oracle unpivot 索引_oracle 11g 行列转换之unpivot、pivot
  10. python亲和度_数据挖掘——亲和性分析