vue传值和事件方式集合

398 阅读1分钟

一、vue的传值方式

1、父向子传递
  • 属性Props
//child
porops:{msg:String}
//parent
<Helloworld msg="我是传递给child的" />
2、子向你传递
  • 引用refs
//child
data(){
	return {
		hw:"我是子类父类可以调用"
	}
}

//parent
<Helloworld ref="hw" />
this.$refs.hw
3.provideinject实现袓孙传值

provide:就相当于加强版父组件prop

inject:就相当于加强版子组件的props

只要在上一层级的声明的provide,那么下一层级无论多深都能够通过inject来访问到provide的数据

提示:provideinject绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。

如果需要传可响应的值,请使用引用类型的数值,比如{}||[]等。

  • 袓组件
<template>
    <div id="app">
        <Child />
    </div>
</template>
<script>
  import Child from 'Child'
  export default{
    components:{
      	Child
    },  
    provide(){
        return {
            msg:"我是祖组件要给孙组件准备的"
        }
    },
    data(){
      return {
      }
    },
    methods:{
    }
  }
</script>
  • 儿组件
<template>
    <div>
        <Child1 />
    </div>
</template>
<script>
  import Child1 from 'Child1'
  export default{
    components:{
      	Child1
    }, 
    data(){
      return {
      }
    },
    methods:{
    }
  }
</script>
  • 孙组件
<template>
    <div>
      <p>{{msg}}</p>
    </div>
</template>
<script>
  export default{
    inject:['msg']
    data(){
      return {
      }
    },
    methods:{
    }
  }
</script>

二、vue的事件方式

1、子向父传递
//child
this.$emit('add',good)
//parent
<Helloworld @add="add($event)"/>
2、兄弟之间
  • A组件
<template>
    <div>
        <span @click="postBrotherMsg">Brother</span>
    </div>
</template>

<script>
export default {
    name: "BrotherA",
    methods: {
        postBrotherMsg() {
            this.$parent.$emit("foo", "我是兄长,弟弟收好了");
        }
    }
};
</script>
  • B组件
<template>
    <div>
        <span @click="postBrotherMsg">Brother</span>
    </div>
</template>

<script>
export default {
    name: "BrotherB",
    mounted() {
        this.$nextTick(() => {});
        this.$parent.$on("foo", val => console.log('兄长,弟弟收到了。你的信息是:',val));
    }
};
</script>
<style lang="scss" scoped>
</style>
  • 父组件
<template>
    <div id="app">
        <BrotherA />
        <BrotherB />
    </div>
</template>
3、袓孙之间(隔辈之间)传递
1.使用$attrs$listeners实现袓孙组件之间数据传递
本质探索

$attrs:包含了父作用域不作为prop被识别(且获取)的特性绑定(class和style除外),就是说,他获取到的除了prop里的可以收到和元素自有属性之外的所有自定义属性

$listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。

  • 孙组件
<template>
    <div>
      <p @click="test2">$attrs:{{$attrs['two']}}</p>
    </div>
</template>
<script>
  import Child1 from 'Child1'
  export default{
    inheritAttrs: false,
    data(){
      return {
      }
    },
    methods:{
      test2(){
        this.$emit('test2','我是孙子组件')
      }
    }
  }
</script>
  • 儿组件
<template>
    <div>
      <p @click="test1">$attrs:{{$attrs['one']}}</p>
        <Child1 v-bind="$attrs" v-on="$listeners"/>
    </div>
</template>
<script>
  import Child1 from 'Child1'
  export default{
    components:{
      	Child1
    },  
    inheritAttrs: false,
    data(){
      return {
      }
    },
    methods:{
      test1(){
        this.$emit('test1','我是儿子组件')
      }
    }
  }
</script>
  • 袓组件
<template>
    <div id="app">
        <Child :one="child1" :two="child2" @test1="onTest1" @test2="onTest2"/>
    </div>
</template>
<script>
  import Child from 'Child'
  export default{
    components:{
      	Child
    },  
    data(){
      return {
        one:"我是child1",
        two:"我是child2"
      }
    },
    methods:{
      onTest1(val){
        conosle.log("我是父亲接收到的test1事件回调",val)
      },
      onTest2(val){
        conosle.log("我是父亲接收到的test2事件回调",val)
      }
    }
  }
</script>

总结:可以用于传值和事件从后代组件

2.使用dispatch函数实现后代向祖先传值
//main.js里
Vue.prototye.dispatch = dispatch;
/**
eventName 派发事件名称
data 派发的数据
**/
function dispatch(eventName,data){
    let parent = this.$parent
    while(parent){
      	if(parent){
          parent.$emit(eventName,data)
          parent =  parent.$parent;
        }else{
          break
        }
    }
}

  • 后代组件
<template>
    <div>
      <p @click="dispatch('hello','hello world')">{{msg}}</p>
    </div>
</template>
<script>
  export default{
    data(){
      return {
      }
    },
    methods:{
    }
  }
</script>
  • 祖组件
<template>
    <div id="app">
        <Child />
    </div>
</template>
<script>
  import Child1 from 'Child1'
  export default{
    components:{
      	Child1
    }, 
    data(){
      return {
      }
    },
    mounted(){
    	this.$on('hello',(val)=>console.log(val))
    },
    methods:{
    }
  }
</script>
3.使用事件总线
  • main.js
class Bus{
    constructor(){
        this.callbacks = {}
    }
    $on(name,fn){
        this.callbacks[name] =  this.callbacks[name] || []
        this.callbacks[name].push(fn)
    }
    $emit(name,args){
        if(this.callbacks[name]){
            this.callbacks[name].forEach(cb=>cb(args))
        }
    }
}
Vue.prototype.$bus = new Bus()
  • A组件
<template>
    <div>
      <p @click="test1">{{msg}}</p>
    </div>
</template>
<script>
  export default{
    name:"ComA",
    data(){
      return {
      }
    },
    methods:{
      test1(){
        this.$bus.$emit('foo')
      }
    }
  }
</script>
  • B组件
<template>
    <div id="app">
      <ComA />
    </div>
</template>
<script>
  export default{
    data(){
      return {
      }
    },
    mounted(){
    	this.$on('msg',(val)=>console.log(val))
    },
    methods:{
    }
  }
</script>

最后一种使用Vuex,但vuex比较大,后续会跟上,敬请期待