Vue组件通信方式
Vuex核心概念和基本使用回顾
组件内的状态管理流程
状态管理
state:驱动应用的数据源
actions:响应在view上的用户输入导致的状态变化
view:以申明的方式将state映射到视图
单向数据流
箭头是数据的流向,此处数据流向是单向的 ,数据绑定到视图展示给用户,当用户和视图交互通过actions更改数据后,在把更改后的数据绑定到视图
组件间通信方式回顾-父组件给子组件传值
父组件给子组件传值
字符串中通过props接受数据
父组件中给子组件通过相应属性传值
//父组件
Props Down Parent
//子组件
Props Down Child
{{ title }}
子组件给父组件传值
通过自定义事件子组件给父组件传值
在父组件注册子组件的事件
在子组件触发事件向父组件传值
//父组件
Event Up Parent
这里的文字不需要变化
//子组件
Props Down Child
文字增大
不相关组件之间传值
自定义事件传值
event-bus
创建event-bus文件创建vue实例并导出,只需要使用此vue对象的 $on #emit方法注册和触发方法
需要传值的组件中引入该对象并注册或者触发事件
//event-bus事件中心
import Vue from 'vue'
export default new Vue()
//组件1
Event Bus Sibling01
-
+
//组件2
Event Bus Sibling02
{{ msg }}
组件间通信方式回顾-通过 ref 获取子组件
$root
$parent
$children
$refs
在普通HTML标签上使用ref,获取到的是dom对象
在组件标签上使用ref,获取到的是组件实例
ref Parent
ref Child
简易的状态管理方案
问题:
多个视图依赖同一状态
来自不同的视图的行为需要变更统一状态
更好的方法:
把不同组件的共享状态抽离出来,存储到一个全局对象中,并且要保证这个对象是响应式的
Vuex 概念回顾
什么是vuex
vuex 是专门为vue.js 设计的状态管理库
vuex 采用集中式的方式存储要共享的状态
vuex 的作用是进行状态管理,解决复杂的组件通信,数据共享
vuex 集成到了devtools中,提供了time-travel时光旅行历史回滚功能
什么情况下使用vuex
非必要的情况不要使用vuex
大型的单页应用程序
多个视图依赖同一状态
来自不同视图的行为需要变同统一状态
Vuex 的核心概念
Store
仓库,每一个应用只有一个Store,不能直接改变Store的状态,需要提交Mutation来更改Store状态
State
状态,保存在Store中,因为Store是唯一的,所以State也是唯一的,称为单一状态书,但是所有的状态都保存在State中会让程序难以维护,可以通过后续的模块解决该问题,
State是响应式的
Getter
就像是vuex中的计算属性,方便从一个属性派生出其他的值,内部对结果缓存,只有依赖的状态改变时才会重新计算
Mutation
状态的变化需要提交Mutation来完成
Action
和Mutation 类似,Action可以进行异步操作,内部改变状态的时候都需要提交Mutation
Module
由于使用单一状态树应用的所有状态会集中到一个比较大的对象上来,当应用变得非常复杂时,Store会变的相当臃肿,解决改问题,vuex允许我们将Store分割成模块,每个模块拥有自己的state,Getter,Mutation,Action 甚至是子模块
基本代码结构
Store模块中基础代码
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
}
})
mian.js中挂载到vue实例上
import store from './store'
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
State基本使用
Store模块中state
state: {
count: 0,
msg: 'Hello Vuex'
},
需要使用的组件中
count: {{$store.state.count}}
msg: {{$store.state.msg}}
简化重复的$store.state
使用计算属性来简化$store.state
这种方式简化了视图中 重复的$store.state
如果当前组件已经定义了vuex中的重复属性key则会冲突
count: {{count}}
msg: {{msg}}
getter的基本使用
Store模块中添加getters
{
state: {
count: 0,
msg: 'Hello Vuex'
},
getters: {
reverseMsg (state) {
return state.msg.split('').reverse().join('')
}
},
}
需要使用的组件中
getter-msg: {{$store.getter.reverseMsg}}
简化重复的$store.getter
getter-msg: {{reverseMsg}}
Mutation的基本使用
Mutation必须是同步执行的
Store模块中增加
mutations: {
increate (state, payload) {
state.count += payload
}
},
用map方法映射到组件methods中
Mutation
时光旅行
还原到点击按钮这次的值,方便调试
历史回滚
回滚到这次提交
Action
执行异步操作,提交Mutation来修改state
Action的调用需要使用dispatch来调用
用settimeout来演示异步操作,在store模块中添加Action
actions: {
increateAsync (context, payload) {
setTimeout(() => {
context.commit('increate', payload)
}, 2000)
}
},
使用map方法映射到methods
Mutation
module的基本使用
目录结构
store
modules 模块文件夹
cart.js
products.js
index.js
模块cart内容
const state = {
products: [
{ id: 1, title: 'iPhone 11', price: 8000 },
{ id: 2, title: 'iPhone 12', price: 10000 }
]
}
const getters = {}
const mutations = {
setProducts (state, payload) {
state.products = payload
}
}
const actions = {}
export default {
namespaced: true,//命名空间
state,
getters,
mutations,
actions
}
模块products内容
const state = {}
const getters = {}
const mutations = {}
const actions = {}
export default {
namespaced: true, //命名空间
state,
getters,
mutations,
actions
}
Store模块入口
import Vue from 'vue'
import Vuex from 'vuex'
import products from './modules/products'
import cart from './modules/cart'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
products,
cart
}
})
组件中使用 命名空间方式
products: {{ products }} Mutation
Vuex 严格模式
所有的状态变更必须通过Mutation,这仅仅只是约定, 如果不遵从约定直接更改state,devtools无法跟踪到这次状态的修改,开启严格模式后直接修改state会抛出错误
在new Store的时候strict设置为true打开严格模式
不要在生产环境中开启严格模式严格模式会深度检查状态树,来检查不合规的状态改变会影响性能
export default new Vuex.Store({
strict: process.env.NODE_ENV !== 'production',
})
vuex插件
vuex的插件就是一个函数
这个函数接收一个store的参数
本地储存(存储到localStorage,sessionStorage中)
获取本地储存中的数据
state: cartProducts: JSON.parse(window.localStorage.getItem('cart-products')) || []
插件函数
const myPlugin = store => {
store.subscribe((mutation, state) => {
if (mutation.type.startsWith('cart/')) {
window.localStorage.setItem('cart-products', JSON.stringify(state.cart.cartProducts))
}
})
}
注册插件
plugins: [myPlugin]
注意:
不是任何项目都适合vuex
中大型项目需要管理状态较多才合适vuex
小型项目使用vuex会适得其反