共计 4801 个字符,预计需要花费 13 分钟才能阅读完成。
组件通信
父子组件传值
通过 props
向子组件传递数据
Parent
<template>
<div>
<h1> 父给子传值 </h1>
<child title="My journey with Vue"></child>
</div>
</template>
<script>
import child from './Child'
export default {
components: {child}
}
</script>
Child
<template>
<div>
<h1>Props Down Child</h1>
<h2>{{title}}</h2>
</div>
</template>
<script>
export default {// props: ['title'],
props: {title: String}
}
</script>
子父组件传值
通过监听子组件事件
Parent
<template>
<div>
<h1> 子给父传值 </h1>
这里的文字不须要变动
<child :fontSize="hFontSize" @enlargeText="enlargeText"></child>
</div>
</template>
<script>
import child from './Child'
export default {
components: {child},
data () {
return {hFontSize: 1}
},
methods: {enlargeText (size) {this.hFontSize += size}
}
}
</script>
Child
<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', 0.1)
}
}
}
</script>
不相干组件传值
通过 EventBus
事件总线
EventBus
又称为事件总线。在 Vue 中能够应用EventBus
来作为沟通桥梁的概念,就像是所有组件共用雷同的事件核心,能够向该核心注册发送事件或接管事件,所以组件都能够高低平行地告诉其余组件,但也就是太不便所以若应用不慎,就会造成难以保护的“劫难”,因而才须要更欠缺的 Vuex 作为状态管理中心,将告诉的概念回升到共享状态档次。
- 初始化
首先须要创立事件总线并将其导出,以便其它模块能够应用或者监听它。咱们能够通过两种形式来解决。先来看第一种,新创建一个 .js 文件,比方 eventbus.js
import Vue from 'vue'
export default new Vue()
另外一种形式,能够间接在我的项目中的 main.js 初始化全局 EventBus
- 发送事件
当初有两个不相干组件 01 和 02,当 01 组件中对应操作触发 value 变动时发送 numchange
事件
<!-- 01 -->
<template>
<div>
<h1> 不相干组件 -01</h1>
<div class="number" @click="sub">-</div>
<input type="text" style="width: 30px; text-align: center;" :value="value">
<div class="number" @click="add">+</div>
</div>
</template>
<script>
import bus from './eventbus'
export default {
props: {num: Number},
created () {this.value = this.num},
methods: {sub () {if (this.value > 1) {
this.value--
bus.$emit('numchange', this.value)
}
},
add () {
this.value++
bus.$emit('numchange', this.value)
}
}
}
</script>
<style>
.number {
display: inline-block;
cursor: pointer;
width: 20px;
text-align: center;
}
</style>
- 接管事件
<!--02-->
<template>
<div>
<h1> 不相干组件 -02</h1>
<div>{{msg}}</div>
</div>
</template>
<script>
import bus from './eventbus'
export default {data () {
return {msg: ''}
},
created () {bus.$on('numchange', (value) => {this.msg = ` 您抉择了 ${value}件商品 `
})
}
}
</script>
其余通信形式
通过 ref
操作子组件
Parent
<template>
<div>
<h1>ref Parent</h1>
<child ref="c"></child>
</div>
</template>
<script>
import child from './Child'
export default {
components: {child},
mounted () {this.$refs.c.test()
this.$refs.c.value = 'hello input'
}
}
</script>
Child
<template>
<div>
<h1>ref Child</h1>
<input ref="input" type="text" v-model="value">
</div>
</template>
<script>
export default {data () {
return {value: ''}
},
methods: {test () {this.$refs.input.focus()
}
}
}
</script>
Vuex
Vuex 是什么?
State
Vuex 应用繁多状态树,用一个对象就蕴含了全副的利用层级状态。
应用 mapState 简化 State 在视图中的应用,mapState 返回计算属性
- 数组参数
// 该办法是 vuex 提供的,所以应用前要先导入
import {mapState} from 'vuex'
// mapState 返回名称为 count 和 msg 的计算属性
// 在模板中间接应用 count 和 msg
computed: {...mapState(['count', 'msg']),
}
- 对象参数
// 该办法是 vuex 提供的,所以应用前要先导入
import {mapState} from 'vuex'
// 通过传入对象,能够重命名返回的计算属性
// 在模板中间接应用 num 和 message
computed: {
...mapState({
num: state => state.count,
message: state => state.msg
})
}
Getter
Getter 就是 store 中的计算属性,应用 mapGetter 简化视图中的应用
import {mapGetter} from 'vuex'
computed: {...mapGetter(['reverseMsg']),
// 改名,在模板中应用 reverse
...mapGetter({reverse: 'reverseMsg'})
}
Mutation
更改 Vuex 的 store 中的状态的惟一办法是提交 mutation。Vuex 中的 mutation 十分相似于事件:每
个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是咱们
理论进行状态更改的中央,并且它会承受 state 作为第一个参数
应用 Mutation 扭转状态的益处是,集中的一个地位对状态批改,不论在什么中央批改,都能够追踪到
状态的批改。能够实现高级的 time-travel 调试性能
import {mapMutations} from 'vuex'
methods: {...mapMutations(['increate']),
// 传对象解决重名的问题
...mapMutations({increateMut: 'increate'})
}
Action
Action 相似于 mutation,不同在于:
- Action 提交的是 mutation,而不是间接变更状态。
- Action 能够蕴含任意异步操作。
import {mapActions} from 'vuex'
methods: {...mapActions(['increate']),
// 传对象解决重名的问题
...mapActions({increateAction: 'increate'})
}
Module
因为应用繁多状态树,利用的所有状态会集中到一个比拟大的对象。当利用变得非常复杂时,store 对
象就有可能变得相当臃肿。
为了解决以上问题,Vuex 容许咱们将 store 宰割成模块(module)。每个模块领有本人的 state、
mutation、action、getter、甚至是嵌套子模块
Vuex 插件
Vuex 的 store 承受 plugins 选项,这个选项暴露出每次 mutation 的钩子。Vuex 插件就是一个函数,它接管 store 作为惟一参数:
在插件中不容许间接批改状态——相似于组件,只能通过提交 mutation 来触发变动。
const myPlugin = store => {
// 当 store 初始化后调用
store.subscribe((mutation, state) => {
// 每次 mutation 之后调用
// mutation 的格局为 {type, payload}
})
}
// 应用
const store = new Vuex.Store({
// ...
plugins: [myPlugin]
})
严格模式
在严格模式下,无论何时产生了状态变更且不是由 mutation 函数引起的,将会抛出谬误。这能保障所有的状态变更都能被调试工具跟踪到。
const store = new Vuex.Store({
// ...
strict: true
})
模仿实现
-
实现 install 办法
- Vuex 是 Vue 的一个插件,先实现 Vue 插件约定的 install 办法
-
实现 Store 类
- 实现构造函数,接管 options
- state 的响应化解决
- getter 的实现
- commit、dispatch 办法
install 办法
function install(Vue) {
_Vue = Vue;
_Vue.mixin({beforeCreate() {if (this.$options.store) {_Vue.prototype.$store = this.$options.store;}
},
});
}
Store 类
class Store {constructor(options) {const { state = {}, getters = {}, mutations = {}, actions = {}} = options;
this.state = _Vue.observable(state);
this.getters = Object.create(null);
Object.keys(getters).forEach((key) => {
Object.defineProperty(this.getters, key, {get: () => getters[key](state),
});
});
this._mutations = mutations;
this._actions = actions;
}
commit(type, payload) {this._mutations[type](this.state, payload);
}
dispatch(type, payload) {this._actions[type](this, payload);
}
}