在父组件中,能够经过子组件标签属性的形式将数据或者函数传给子组件,子组件经过props去读取父组件传过来的数据vue
用法vuex
父组件传数据给子组件:bash
通常的属性值都是用来给子组件展现的app
子组件传数据给父组件异步
属性值为函数类型的,通常是用来子组件向父组件传递数据,子组件经过调用父组件传过来的函数,能够修改父组件的状态数据函数
缺点:工具
隔层组件间传递: 必须逐层传递(麻烦)优化
兄弟组件间: 必须借助父组件(麻烦)ui
注意:this
//子组件获取父组件传过来的值
props: {
obj: {//obj为{id:'2'}
type: Object
}
}复制代码
引用类型的props,咱们能够在子组件中直接修改引用类型属性的值(如:this.obj.id='3',会生效),可是不能直接改变引用类型存储的地址值(如:this.obj = {id: '3'}),会发出警告。
虽然子组件能够直接修改父组件的状态值,但咱们不建议这样作,咱们但愿全部的 prop 都使得其父子 prop 之间造成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,可是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而致使你的应用的数据流向难以理解。
脏数据问题:如v-model是实现了双向绑定,经过v-model更改数据,会更改父组件的数据,致使脏数据
解决方法:
利用计算属性的set和get,在set中需实现子组件调用父组件的方法,确保数据流向是单向的
computed:{
msg: {
get(){
return this.data
},
set(){
this.$emit('EventName', this.data)
}
}}复制代码
方式1: 给子组件标签绑定事件监听
子组件向父组件的通讯方式
功能相似于function props
经过在父组件中给子组件标签绑定自定义事件的监听,再由子组件触发事件,实现子组件向父组件传递数据的方法,事件名必须一致,且不能有大写字母,v-on
事件监听器在 DOM 模板中会被自动转换为全小写 (由于 HTML 是大小写不敏感的)
// 方式一: 经过v-on绑定
<component @delete_todo="deleteTodo"/>
// 方式二: 经过$on()绑定
this.$refs.xxx.$on('delete_todo', function (todo) {
this.deleteTodo(todo)})
经过this.$emit('delete_todo', todo)触发事件复制代码
不适合隔层组件和兄弟组件间的通讯
注意:
在组件标签上绑定事件,会被解析为vue自定义事件
在普通的标签上绑定事件,会被解析为DOM事件
<--!
表示在组件component绑定了一个名为click的vue自定义事件,
至关于作了vm.$on('click',fn)
注意:不是常规理解的点击事件,这里与点击无关,只是名字恰好是click,
固然实际操做中不建议取这类特殊的名字
-->
<component @click="fn"/>
<--! 表示在div上绑定一个click的点击事件,是DOM事件 -->
<div @click="fn"/>复制代码
方式2: 经过单独的vm对象绑定监听/分发事件
任意组件间通讯(相似于pubsub)
建立一个公用的vm对象
import Vue from 'vue'export default new Vue()复制代码
在接收消息的组件,绑定监听
import vm from './vm.js'mounted(){
vm.$on('delete_todo', function (todo) {
this.deleteTodo(todo)
})}复制代码
在发送消息的组件,触发事件
vm.$emit('delete_todo', todo)复制代码
事件总线(EventBus),其实跟上面的用法同样,这里是把vm实例绑在了Vue的显示原型上
//点击任意一个组件,其余组件的值跟着变化,利用总线去实现兄弟之间的通讯
Vue.prototype.bus = new Vue()
var vm = new Vue({
el:"#app"
})
//v-a组件
Vue.component('v-a', {
template:'<div @click="handle">{{msg}}</div>',
data(){
return {
msg: 'v-a'
}
},
mounted () {
//绑定事件监听
this.bus.$on('bus',(msg)=>{
this.msg = msg
})
},
methods: {
handle () {
//触发事件
this.bus.$emit('bus', this.msg)
}
}})
//v-b组件
Vue.component('v-b', {
template:'<div @click="handle">{{msg}}</div>',
data(){
return {
msg: 'v-b'
}
},
mounted () {
//绑定事件监听
this.bus.$on('bus',(msg)=>{
this.msg = msg
})
},
methods: {
handle () {
//触发事件
this.bus.$emit('bus', this.msg)
}
}})复制代码
适用于任何关系的组件间的通讯
缺点:相对于vuex,管理不够集中
用法:
引入pubsub-js库
在接收消息的组件订阅消息(subscribe)
PubSub.subscribe('name',(name,data)=>{})复制代码
在发送消息的组件发布消息 ( publish)
PubSub.publish('name',data)复制代码
其余用法能够参考官方API文档,这里不细说
vuex是专门为vue.js应用程序定义的状态管理模式,当多个组件须要共享数据时,咱们通常用vuex去管理状态数据,实现多个组件间的相互通讯
vuex的核心
state:存放数据
mutations:修改数据
actions:提交mutation,修改数据
getters:存放数据,相似于vue的计算属性
知道了这几个核心概念后,咱们还须要知道怎么合理使用他们
如何从仓库store读取数据
state
从store的实例中咱们能够经过store.state去得到状态数据,为了使得store能够全局使用,咱们须要经过Vue.use(Vuex),将vuex注给全部vue子的组件,Vue.use回去调用插件的install方法,将stroe绑到Vue.prototype,这样Vue的实例对象都能经过vm.store获取或操做仓库的数据组件内经过this.$store.state能够得到
state:{
data: 0
}复制代码
getters
有些状态熟悉须要根据其余状态属性计算而动态得到,通常都是存在getters中,组件经过调用this.$store.getters
Getter 接受 state 做为其第一个参数
getters:{
data2(state){
return state.data+1
}
}复制代码
如何修改仓库store的数据
mutations(同步修改)
更改 Vuex 的 store 中的状态的惟一方法是提交 mutation,接受 state 做为第一个参数 ,mutation接收提交载荷,第二个参数为载荷,在大多数状况下,载荷应该是一个对象 ,这样能够接收多个数据
mutations:{
mutationType:(state,data)=>{
state.data = data
}
}复制代码
actions(异步修改)
在action中提交mutation,组件经过store.dispatch触发action
由于vue的调试工具没法检测到mutations的异步变化,因此咱们若是须要异步修改状态数据,通常是放在action去异步获取到数据后再提交mutation,确保vue的调试工具能够检测到,mutation的变化
注意点:
当组件须要给vue中的状态数据添加属性时,经过obj.的形式没法实现
由于Vuex 的 store 中的状态是响应式的,那么当咱们变动状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也须要与使用 Vue 同样遵照一些注意事项:
咱们最好提早在 store 中初始化好全部所需属性。
当须要在对象上添加新属性时,咱们应该
使用 Vue.set(obj, 'newProp', 123)
, 或者
以新对象替换老对象。例如,利用 stage-3 的对象展开运算符,咱们能够这样写:
state.obj = { ...state.obj, newProp: 123 }复制代码
优化
import {mapState,mapGetters,mapMutations,mapActions} from "vuex";使得在使用vuex时,组件能够写的更加的简洁
数据比较多的时候,使用module
使用常量存放mutation_type
优势:
多组件共享状态(数据的管理)
组件间的关系也没有限制
功能比pubsub强大, 更适用于vue项目
父向子通讯
通讯是带数据的标签
注意: 标签是在父组件中解析