文章内容输出来源:大前端高薪训练营
一、组件内的状态管理流程
每个组件都有自己的状态、视图和行为等组成部分。
new Vue({
// state
data () {
return {
count: 0
}
},
// view
template: `<div>{{ count }}</div>`,
// actions
methods: {
increment () {
this.count++
}
}
})
复制代码
状态管理包含以下几部分:
- state,驱动应用的数据源
- view,以声明方式将 state 映射到视图
- actions,响应在 view 上的用户输入导致的状态变化
二、组件间的通信方式
1.父组件给子组件传值
- 子组件中通过 props 接收数据
<template>
<div>
<h2>{{title}}</h2>
</div>
</template>
<script>
export default {
// props 有两种类型:数组、对象,需要约定值的类型用对象
// props: ['title'],
props: {
title: String
}
}
</script>
复制代码
- 父组件中给子组件通过相应属性传值
<template>
<div>
<child title="My journey with Vue"></child>
</div>
</template>
<script>
import child from './01-Child'
export default {
components: {
child
}
}
</script>
复制代码
2.子组件给父组件传值
- 在子组件中使用
$emit
发布一个自定义事件:
<template>
<div>
<h1 :style="{ fontSize: fontSize + 'em' }">Props Down Child</h1>
<button @click="handler">文字增大</button>
</div>
</template>
<script>
export default {
props: {
fontSize: Number
},
methods: {
handler () {
this.$emit('enlargeText', 01)
}
}
}
</script>
复制代码
- 在使用这个组件的时候,使用
v-on
监听这个自定义事件,并且父组件中注册子组件内部触发的事件
<template>
<div>
<h1 :style="{ fontSize: hFontSize + 'em' }">Event Up Parent</h1>
这里的文字不需要变化
<child :fontSize="hFontSize" v-on:enlargeText="enlargeText"></child>
<child :fontSize="hFontSize" v-on:enlargeText="enlargeText"></child>
<child :fontSize="hFontSize" v-on:enlargeText="hFontSize + $event"></child>
</div>
</template>
<script>
import child from './02-child'
export default {
components: {
child
},
data () {
return {
hFontSize: 1
}
},
methods: {
enlargeText (size) {
this.hFontSize += size
}
}
}
</script>
复制代码
3.不相关组件传值
不相关组件的通信也是使用自定义事件的方式,因为没有父子关系,所以不能再由子组件触发自定义事件传值,而是需要使用eventbus
创建一个公共实例,这个实例的作用是作为事件组件或者事件中心。
// eventbus.js
// 不需要传递任何选项,为了用了调用实例的 $emit 和 $on来触发和注册事件
import Vue from 'Vue'
export default new Vue()
复制代码
然后在需要通信的两端:
使用$on
订阅
import bus from './eventbus'
// 没有参数
bus.$on('自定义事件名称', () => {
// 执行操作
})
// 有参数
bus.$on('自定义事件名称', data => {
// 执行操作
})
复制代码
使用$emit
发布
import bus from './eventbus'
// 没有自定义传参
bus.$emit('自定义事件名称');
// 有自定义传参
bus.$emit('自定义事件名称',数据);
复制代码
4.其他常见方式(不推荐使用)
只有当项目非常小或者在开发自定义组件的时候才会用到。
- $root
- $parent
- $children
- $refs
ref 两个作用:
- 在普通HTML标签上使用 ref, 获取到的是DOM
- 在组件标签上使用 ref,获取到的是组件实例
注意:ref这种方式不到万不得已不要使用,会导致数据的混乱。
创建 base-input 组件
<template>
<input ref="input">
</template>
<script>
export default {
methods: {
// 用来从父级组件聚焦输入框
focus: function () {
this.$refs.input.focus()
}
}
}
</script>
复制代码
在使用子组件的时候,添加 ref 属性:
<base-input ref="usernameInput"></base-input>
复制代码
然后在父组件等渲染完毕后使用 $refs 访问:
mounted () {
this.$refs.usernameInput.focus()
}
复制代码
$refs
只会在组件渲染完成后生效,并且他们不是响应式的。应该避免在模板或计算属性中访问$refs
。
三、简易的状态管理方案
如果多个组件之间要共享状态(数据),使用上述方式虽然可以实现,但是比较麻烦,而且多个组件之间互相传值很难跟踪数据的变化,如果出现问题很难定位。
因此,我们可以把多个组件的共享状态抽取出来,以一个全局单例模式管理,在这种模式下我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为。你可能已经想到了Vuex。
这里我们先用哪个简单的方式实现:
- 首先创建一个共享的仓库 store 对象
export default {
debug: true,
state: {
user: {
name: 'xiaomao',
age: 18,
sex: '男'
}
},
setUserNameAction (name) {
if (this.debug) {
console.log('setUserNameAction triggered: ', name)
}
this.state.user.name = name
}
}
复制代码
- 把共享的仓库 store 对象,存储到需要共享状态的组件的data中
<template>
<div>
<h1> componentA </h1>
user name : {{ sharedState.user.name }}
<button @click="change"> Change Info </button>
</div>
</template>
<script>
import store from './store'
export default {
methods: {
change () {
store.setUserNameAction('componentA')
}
},
data () {
return {
privateState: {},
sharedState: store.state
}
}
}
</script>
复制代码
<template>
<div>
<h1> componentB </h1>
user name : {{ sharedState.user.name }}
<button @click="change"> Change Info </button>
</div>
</template>
<script>
import store from './store'
export default {
methods: {
change () {
store.setUserNameAction('componentB')
}
},
data () {
return {
privateState: {},
sharedState: store.state
}
}
}
</script>
复制代码
四、Vuex回顾
1. 什么是Vuex
- Vuex是专门为Vue.js设计的状态管理库
- Vuex采用集中式的方式存储需要共享的状态
- Vuex的作用是进行状态管理,解决复杂组件通信,数据共享
- Vuex集中到了devtools中,提供了time-travel时光旅行历史回滚等功能
2. 什么情况下使用Vuex
- 非必要情况下不要使用Vuex
- 大型的单页面应用程序
- 多个视图依赖同一个状态
- 来自不同视图的行为需要变更同一状态
例如:购物车组件
3. Vuex核心概念
- Store: 是一个容器,包含着应用中的大部分状态,不能直接改变store中的状态,要通过mutation的方式改变状态。
- State:是状态,保存在Store中,因为Store是唯一的,所以State也是唯一的,也称为单一状态树。这里的状态是响应式的。
- Getter:是Vuex中的计算属性,方便从一个属性派生出其他的值。它内部会对计算的属性进行缓存,只有当依赖发生改变的时候,才会重新进行计算。
- Mutation: 状态的变换必须要通过提交Mutation来完成。
- Action:和Mutation类似,不同的是Action可以进行异步操作,内部改变状态的时候,都需要提交Mutation。
- Module:当Store太多臃肿时,可以将Store分成多个模块,每个模块里有State、Mutation、Action、Getter,甚至是子模块。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END