vue组件通信_父子组件_兄弟组件之间各种传值(组件多种传值集合)

vue组件通信,父子组件/ 兄弟组件之间各种传值

文章参考https://libusi.blog.csdn.net/article/details/131668644

1.1 父传子组件(方式一 props)

父传子注意问题:
  • 1 绑定的属性可否驼峰式? —>不可以

    父子组件通信 props 如果用到驼峰标识会遇到问题(v-bind目前版本不支持驼峰,必须进行转化使用),一般建议props不使用驼峰传值,如果非要使用驼峰命名传值,需要注意格式;

    <div :c-info="info"></div>
    props:{
    	cInfo:{
    		type: Object, // Array, String
    		default() { return {}}
    	}
    }
    
  • 2 类型不一样,算传值成功了吗? --》不可以

父组件:

总体:

两步走:
    1、在子组件身上定义一个属性,将数据传递给子组件
    <child-component :xxx="data"></child-component>2、子组件使用props接收数据
​		在template同级的地方,写props:["xxx"]
<template>
  <div>
    <child-component :parentData="data"></child-component>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
 
export default {
      
      
  components: {
      
      
    ChildComponent
  },
  data () {
      
      
    return {
      
      
      data: '父组件传递的数据'
    }
  }
}
</script>
子组件:
<template>
  <div>
    子组件接收到的数据:{
   
   { parentData }}
  </div>
</template>
 
<script>
export default {
      
      
  props: {
      
      
    parentData: String
  }
}
</script>

总结:

props完整的写法是一个对象,其中default代表默认值,如果父组件没有传数据过来,就显示默认值; type是检查传过来的数据的类型;

可以设置传递时的类型(String,Number,Boolean,Array, Object,Date,Function,Symbol),也可以设置默认值等;

类型:
props:{
                //必须是数字类型
                propA: Number,

                //必须是字符串或数字类型
                propB: [String, Number],

                //布尔值,如果没有定义,默认是true
                propC: {
                    type:Boolean,
                    default:true
                },

                //数字,而且必须上传
                propD: {
                    type: Number,
                    required:true
                },

                //自定义一个验证函数
                propE: {
                    validator: function(value){
                        return value > 10;
                    }
                },

                //如果是数组或对象,默认必须是一个函数来返回
                propF: {
                    type: Array,
                    default:function(){
                        return [];
                    }
                }
            }
});

1.2 父传子(方式二 p a r e n t 和 parent和 parentchildren)

使用 p a r e n t 和 parent和 parentchildren父组件向子组件传递数据,

父组件通过$children获取子组件实例并调用子组件方法传递数据

父组件:
<template>
  <div>
  	<button @click="handleClick">向子组件传递数据</button>
    <child-component ref="child"></child-component>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
export default {
      
      
  components: {
      
      
    ChildComponent
  },
  methods: {
      
      
    handleClick () {
      
      
      this.$refs.child.handleData('父组件传递的数据')
    }
  }
}
</script>
子组件:
<template>
  <div>
    子组件
  </div>
</template>
 
<script>
export default {
      
      
  methods: {
      
      
    handleData (data) {
      
      
      console.log('子组件接收到的数据:' + data)
    }
  }
}
</script>

1.3 父传子(方式三 a t t r s 和 attrs和 attrslisteners)

父组件向子组件传递属性和事件,子组件通过 a t t r s 获取属性,通过 attrs获取属性,通过 attrs获取属性,通过listeners获取事件并绑定在子组件上。

父传子:
<template>
  <div>
    <child-component attr1="属性1" attr2="属性2" @event1="handleEvent"></child-component>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
 
export default {
      
      
  components: {
      
      
    ChildComponent
  },
  methods: {
      
      
    handleEvent (data) {
      
      
      console.log('父组件接收到的数据:' + data)
    }
  }
}
</script>
子组件:
<template>
  <div>
    子组件
  </div>
</template>
 
<script>
export default {
      
      
  mounted () {
      
      
    this.$emit('event1', '子组件传递的数据')
  }
}
</script>

1.4 父传子(方式四 provide和inject)

父组件向子组件传递数据,父组件通过provide提供数据,子组件通过inject注入数据。

父组件:
<template>
  <div>
    <child-component></child-component>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
 
export default {
      
      
  components: {
      
      
    ChildComponent
  },
  provide () {
      
      
    return {
      
      
      parentData: '父组件提供的数据'
    }
  }
}
</script>
子组件:
<template>
  <div>
    <child-component></child-component>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
 
export default {
      
      
  components: {
      
      
    ChildComponent
  },
  provide () {
      
      
    return {
      
      
      parentData: '父组件提供的数据'
    }
  }
}
</script>

1.5 父传子(方式五 $parent属性)

子组件可以通过$parent获取父组件的实例,进而访问父组件的属性和方法。

父组件:
<template>
  <div>
    <child-component></child-component>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
 
export default {
      
      
  components: {
      
      
    ChildComponent
  },
  data () {
      
      
    return {
      
      
      parentData: '父组件数据'
    }
  },
  methods: {
      
      
    handleParent () {
      
      
      console.log('父组件的方法')
    }
  }
}
</script>
子组件:
<template>
  <div>
    <button @click="handleChild">调用父组件方法</button>
  </div>
</template>
 
<script>
export default {
      
      
  methods: {
      
      
    handleChild () {
      
      
      console.log(this.$parent.parentData)
      this.$parent.handleParent()
    }
  }
}
</script>

1.6 父传子(方式六 $root属性)

子组件可以通过$root获取根组件的实例,进而访问根组件的属性和方法

父组件:
<template>
  <div>
    <child-component></child-component>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
 
export default {
      
      
  components: {
      
      
    ChildComponent
  },
  mounted () {
      
      
    console.log('根组件的数据:' + this.rootData)
    this.rootMethod()
  },
  data () {
      
      
    return {
      
      
      rootData: '根组件的数据'
    }
  },
  methods: {
      
      
    rootMethod () {
      
      
      console.log('根组件的方法')
    }
  }
}
</script>
子组件:
<template>
  <div>
    子组件
  </div>
</template>
 
<script>
export default {
      
      
  mounted () {
      
      
    console.log('根组件的数据:' + this.$root.rootData)
    this.$root.rootMethod()
  }
}
</script>

2.1 子传父(方式一 e m i t 触发和 emit触发和 emit触发和on监听)

组件向父组件传递数据,子组件通过** e m i t 触发 ∗ ∗ 事件,父组件通过 ∗ ∗ emit触发**事件,父组件通过** emit触发事件,父组件通过on监听**事件并接收数据。

子传父的要点:子组件修改父组件的数据,本质上是去触发父组件修改数据

1.子级通过this.$emit('xxx', arg);
2.父级 <tag @xxx="fatherEvent" ></tag>
父组件:
<template>
  <div>
    <child-component @childEvent="handleChild"></child-component>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
 
export default {
      
      
  components: {
      
      
    ChildComponent
  },
  methods: {
      
      
    handleChild (data) {
      
      
      console.log('父组件接收到的数据:' + data)
    }
  }
}
</script>
子组件:
<template>
  <div>
    <button @click="handleClick">点击触发事件</button>
  </div>
</template>
 
<script>
export default {
      
      
  methods: {
      
      
    handleClick () {
      
      
      this.$emit('childEvent', '子组件传递的数据')
    }
  }
}
</script>

2.2 子传父(方式二 $refs属性)

父组件可以通过$refs获取子组件的实例,进而访问子组件的属性和方法

父组件
<template>
  <div>
    <button @click="handleParent">向子组件传递数据</button>
    <child-component ref="child"></child-component>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
 
export default {
      
      
  components: {
      
      
    ChildComponent
  },
  methods: {
      
      
    handleParent () {
      
      
      this.$refs.child.childData = '父组件修改的数据'
    }
  }
}
</script>
子组件:
<template>
  <div>
    子组件接收到的数据:{
   
   { childData }}
  </div>
</template>
 
<script>
export default {
      
      
  data () {
      
      
    return {
      
      
      childData: '子组件原始数据'
    }
  }
}
</script>

3.1 兄弟组件传递(方式一 EventBus中央事件)

父组件和子组件之间通过中央事件总线(EventBus)进行通信。

EventBus.js:
import Vue from 'vue'
export const EventBus = new Vue()
组件A:
<template>
  <div>
    <button @click="handleParent">向子组件传递数据</button>
    <child-component></child-component>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
import {
      
       EventBus } from './EventBus'
 
export default {
      
      
  components: {
      
      
    ChildComponent
  },
  methods: {
      
      
    handleParent () {
      
      
      EventBus.$emit('parent-event', '父组件传递的数据')
    }
  }
}
</script>
组件B:
<template>
  <div>
    子组件接收到的数据:{
   
   { childData }}
  </div>
</template>
 
<script>
import {
      
       EventBus } from './EventBus'
 
export default {
      
      
  data () {
      
      
    return {
      
      
      childData: ''
    }
  },
  mounted () {
      
      
    EventBus.$on('parent-event', data => {
      
      
      this.childData = data
    })
  }
}
</script>

3.2 兄弟组件传递(方式二 Vuex)

父组件和子组件之间通过Vuex进行通信,共享同一状态树。

store.js:
import Vue from 'vue'
import Vuex from 'vuex'
 
Vue.use(Vuex)
 
export default new Vuex.Store({
  state: {
    data: '共享的数据'
  },
  mutations: {
    setData (state, data) {
      state.data = data
    }
  }
})
组件A:
<template>
  <div>
    <button @click="handleParent">向子组件传递数据</button>
    <child-component></child-component>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
import store from './store'
 
export default {
      
      
  components: {
      
      
    ChildComponent
  },
  methods: {
      
      
    handleParent () {
      
      
      store.commit('setData', '父组件传递的数据')
    }
  }
}
</script>
组件B:
<template>
  <div>
    子组件接收到的数据:{
   
   { childData }}
  </div>
</template>
 
<script>
import {
      
       mapState } from 'vuex'
 
export default {
      
      
  computed: {
      
      
    ...mapState(['data']),
    childData () {
      
      
      return this.data + ',子组件加工处理后的数据'
    }
  }
}
</script>

4 其他高级组件传递使用

4.1 provide / inject (高级)

provide / inject 可以让祖先组件向所有后代组件注入一个依赖,让这些组件使用相同的依赖注入。

祖先组件:
<template>
  <div>
    <child-component></child-component>
    <grand-child></grand-child>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
import GrandChild from './GrandChild.vue'
 
export default {
      
      
  components: {
      
      
    ChildComponent,
    GrandChild
  },
  provide: {
      
      
    sharedObj: {
      
      
      message: '这是祖先组件注入的对象'
    }
  }
}
</script>
直接子组件:
<template>
  <div>
    子组件
  </div>
</template>
 
<script>
export default {
      
      
  inject: ['sharedObj']
}
</script>
间接子组件:
<template>
  <div>
    子组件接收到的数据:{
   
   { childData }}
  </div>
</template>
 
<script>
export default {
      
      
  inject: ['sharedObj'],
  computed: {
      
      
    childData () {
      
      
      return this.sharedObj.message + ',子组件加工处理后的数据'
    }
  }
}
</script>
4.2 provide / inject + Vuex (高级)

使用provide / inject注入Vuex的实例,使所有组件使用相同的Vuex实例。

store.js:
import Vue from 'vue'
import Vuex from 'vuex'
 
Vue.use(Vuex)
 
export default new Vuex.Store({
  state: {
    data: '共享的数据'
  },
  mutations: {
    setData (state, data) {
      state.data = data
    }
  }
})
根组件:
<template>
  <div>
    <child-component></child-component>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
import store from './store'
 
export default {
      
      
  components: {
      
      
    ChildComponent
  },
  provide () {
      
      
    return {
      
      
      store
    }
  }
}
</script>
子组件和孙组件:
<template>
  <div>
    组件接收到的数据:{
   
   { componentData }}
  </div>
</template>
 
<script>
export default {
      
      
  inject: {
      
      
    store: {
      
      
      default: null
    }
  },
  computed: {
      
      
    componentData () {
      
      
      return this.store.state.data + ',组件加工处理后的数据'
    }
  }
}
</script>
4.3 localStorage(浏览器缓存)

使用浏览器缓存来存储数据,在需要通信的组件中存储并监听缓存中的数据。

组件A:
<template>
  <div>
    <button @click="handleClick">向组件B传递数据</button>
  </div>
</template>
 
<script>
export default {
      
      
  methods: {
      
      
    handleClick () {
      
      
      localStorage.setItem('data', '组件A传递的数据')
    }
  }
}
</script>
组件B:
<template>
  <div>
    组件B接收到的数据:{
   
   { data }}
  </div>
</template>
 
<script>
export default {
      
      
  data () {
      
      
    return {
      
      
      data: ''
    }
  },
  mounted () {
      
      
    window.addEventListener('storage', this.handleStorageUpdate)
    this.updateData()
  },
  beforeDestroy () {
      
      
    window.removeEventListener('storage', this.handleStorageUpdate)
  },
  methods: {
      
      
    handleStorageUpdate (event) {
      
      
      if (event.key === 'data') {
      
      
        this.updateData()
      }
    },
    updateData () {
      
      
      this.data = localStorage.getItem('data') || ''
    }
  }
}
</script>
4.4 发布订阅(Pub/Sub)模式

使用一个消息中心,订阅者向消息中心订阅消息,发布者向消息中心发布消息,消息中心将消息通知给所有订阅者。

消息中心:
// PubSub.js
export const PubSub = {
  events: {},
  subscribe (event, callback) {
    if (!this.events[event]) {
      this.events[event] = []
    }
    this.events[event].push(callback)
  },
  publish (event, data) {
    if (!this.events[event]) {
      this.events[event] = []
    }
    this.events[event].forEach(callback => callback(data))
  }
}
组件A:
<template>
  <div>
    <button @click="handleClick">向组件B传递数据</button>
  </div>
</template>
 
<script>
import {
    
     PubSub } from './PubSub'
 
export default {
    
    
  methods: {
    
    
    handleClick () {
    
    
      PubSub.publish('event', '组件A传递的数据')
    }
  }
}
</script>
组件B:
<template>
  <div>
    组件B接收到的数据:{
   
   { data }}
  </div>
</template>
 
<script>
import {
      
       PubSub } from './PubSub'
 
export default {
      
      
  data () {
      
      
    return {
      
      
      data: ''
    }
  },
  mounted () {
      
      
    PubSub.subscribe('event', data => {
      
      
      this.data = data
    })
  }
}
</script>
4.5 WebSocket (高级)

使用WebSocket协议实现实时通信,将所有组件连接到同一个WebSocket服务器,通过推送消息实现通信。

连接WebSocket服务器:
const ws = new WebSocket('ws://localhost:3000')
 
ws.onopen = function () {
  console.log('WebSocket已连接')
}
 
ws.onclose = function () {
  console.log('WebSocket已关闭')
}
 
ws.onerror = function () {
  console.log('WebSocket出错')
}
组件A:
<template>
  <div>
    <button @click="handleClick">向组件B传递数据</button>
  </div>
</template>
 
<script>
const ws = new WebSocket('ws://localhost:3000')
 
export default {
      
      
  methods: {
      
      
    handleClick () {
      
      
      ws.send('组件A传递的数据')
    }
  }
}
</script>
组件B:
<template>
  <div>
    组件B接收到的数据:{
   
   { data }}
  </div>
</template>
 
<script>
const ws = new WebSocket('ws://localhost:3000')
 
export default {
      
      
  data () {
      
      
    return {
      
      
      data: ''
    }
  },
  mounted () {
      
      
    ws.onmessage = event => {
      
      
      this.data = event.data
    }
  }
}
</script>
4.6 路由参数传递(高级)

使用路由参数来传递数据,通常适用于父子组件之间或兄弟组件之间的通信。

父组件:
<template>
  <div>
    点击以下链接可以传递数据:<br>
    <router-link :to="{ name: 'child', params: { data: '父组件传递的数据' } }">传递数据到子组件</router-link>
  </div>
</template>
子组件:
<template>
  <div>
    子组件接收到的数据:{
   
   { $route.params.data }}
  </div>
</template>
 
<script>
export default {
      
      
  mounted () {
      
      
    console.log('子组件接收到的数据:' + this.$route.params.data)
  }
}
</script>
兄弟组件:
<template>
  <div>
    兄弟组件接收到的数据:{
   
   { $route.params.data }}
  </div>
</template>
 
<script>
export default {
      
      
  mounted () {
      
      
    console.log('兄弟组件接收到的数据:' + this.$route.params.data)
  }
}
</script>
4.7 Vuex状态管理(高级)

使用Vuex管理公共状态,组件通过Vuex进行通信。

store.js:
import Vue from 'vue'
import Vuex from 'vuex'
 
Vue.use(Vuex)
 
export default new Vuex.Store({
  state: {
    data: '共享的数据'
  },
  mutations: {
    setData (state, data) {
      state.data = data
    }
  }
})
组件A:
<template>
  <div>
    <button @click="handleClick">向组件B传递数据</button>
  </div>
</template>
 
<script>
import store from './store'
 
export default {
      
      
  methods: {
      
      
    handleClick () {
      
      
      store.commit('setData', '组件A传递的数据')
    }
  }
}
</script>
组件B:
<template>
  <div>
    组件B接收到的数据:{
   
   { data }}
  </div>
</template>
 
<script>
import {
      
       mapState } from 'vuex'
 
export default {
      
      
  computed: {
      
      
    ...mapState(['data'])
  },
  mounted () {
      
      
    console.log('组件B接收到的数据:' + this.data)
  }
}
</script>

猜你喜欢

转载自blog.csdn.net/weixin_42786460/article/details/135319525