vue组件间通信

 

vue组件间通信

1、 props 和 $emit

​ props: 主要用在父组件向子组件传递信息的时候,它既可以传递基本类型的数据,也可以传递数组或对象等引用类型的数据,但对于js引用类型, 父子组件会使用同一个数据,比较容易造成数据的混乱。

​ $emit: 子组件通过自定义函数的方式向父组件返回信息

用法
<!--父组件-->
<template>
  <div id="app">
      <!--基本类型-->
      <child :message='message' @childEmit='childEmit'></child>
      <!--props为对象类型-->
      <child :obj.sync='obj'></child>
  </div>
</tempate>
<script>
export default {
	data () {
    	return () {
        	message: '父传子信息',
            obj: {
            	name: 'hehe',
                age: 20
            }
    	}	
	},
    methods: {
        childEmit (data) {
            console.log('子组件传递上来的message', data)
        }
    }
}
</script>
<!--子组件-->
<template>
    <div @click='up'></div>
</template>
<script>
    export default {
        // props 可以配置,自行查阅官方文档
        props: {
            message: {
                type: String,
                default: '默认值'
            },
            obj: {
                type: Object,
                // 当时引用类型的时候,default必须是函数
                default () {
                    return {}
                }
            }
        },
        data () {
            return {
                message: '子组件自身的数据'
            }
        }
        methods: {
            up () {
                // 传递基本类型数据
                this.$emit('childEmit', this.message)
                // 传递引用类型(也可以传递基本类型,只要想实现父子组件数据双向绑定)
                this.$emit('update:obj', this.obj)
            }
        }
    }
</script>

2、ref

主要功能

1. 将其绑定在某个标签上,可以获取该标签的DOM对象 2. 将其绑在子组件上,可以得到该组件的引用, 之后可以方便的操作子组件中的数据

还是拿上面的程序举例子(以下只是父组件,子组件继续沿用上边的那个)

<!--父组件-->
<template>
  <div id="app">
      <!--基本类型-->
      <child ref='child' @click='changeMessage'></child>
  </div>
</tempate>
<script>
export default {
	data () {
    	return () {}	
	},
    methods: {
        changeMessage () {
            this.$refs.child.message1 = '直接修改子组件的数据'
        }
    }
}
</script>

3、routes 路由传参

路由传参主要分为两大类: 1. 编程式导航 2. 声明式导航

1. 编程式导航
this.$router.push({
    name: '路由名称'
    params: {
    	id: 'xxx'
	}
})   // --> 路由名称/id
this.$router.push({
    path: '路由路径',
    query: {
        id: 'xxx'
    }
})   // -->/路由路径?id=xxx
2. 声明式导航
<router-link :to="{ name: 'news', params: {userId: 1111}}">click to news page</router-link>
<router-link :to="{ name: 'news', query: {userId: 1111}}">click to new page</router-link>

两者的主要区别在于显示在浏览器地址栏中的信息不一样, query代表参数,拼接在url的后面,类似于get请求时的请求接口地址。而params传递的参数是url的一部分。 上述1,2 中注释已经说明了

4、vueBus

我一直理解的vueBus是一个小型的vuex, 通过一个新的vue实例去完成各个组件间的信息通信。

用法
<!-- APP.vue -->
<template>
    <div id="app">
        <!-- 如下有两个兄弟组件-->
        <brother-item1></brother-item1>
        ==============华丽的分割线========
        <brother-item2></brother-item2>
    </div>
</template>
// main.js
import Vue from 'vue'
// 定义一个vueBus实例
var eventBus = {
    install (Vue, options) {
        Vue.prototype.$bus = new Vue()
    }
}
Vue.use(eventBus)
<!-- brother-item1 -->
<template>
    <div>
        <h1>我是兄弟组件1</h1>
        <button @click="busOnClick1">我要去看我弟</button>
        <button @click="busOnClick2">我要走了</button>
    </div>
</template>
<script>
export default {
    methods: {
        busOnClick1: function () {
            // vueBus 触发事件
            this.$bus.$emit('sendMessage1', '哥哥来看你了')
        },
        busOnClick2: function () {
            this.$bus.$emit('sendMessage2', '哥哥我要走了')
        }
    }
}
</script>

<!-- brother-item2 -->
<template>
    <div>
        <h1>我是兄弟组件2</h1>
        <div>我在此接收我哥给我的数据: </div>
    </div>
</template>

<script>
export default {
    data () {
        return {
            message: ''
        }
    },
    created () {
        // vueBus绑定事件
        this.$bus.$on('sendMessage1', (params) => {
            this.message = params
        })
        this.$bus.$on('sendMessage2', params => {
            this.message = params
        })
    },
    beforeDestroy () {
        // 页面销毁的时候需要解除事件
        this.$bus.$off('sendMessage1')
        this.$bus.$off('sendMessage2')
    }
}
</script>

5、 vuex

vuex

6、 $attrs 和 $listeners 和 inheritAttrs

$attrs 包含了父作用域不作为prop被识别的特性绑定(style和class除外),当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定,并且可以通过 v-bind=”$attrs 传入内部组件——在创建更高层次的组件时非常有用。

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

inheritAttrs 默认值为true, 没有被子组件继承的父组件属性,不会当做特性展示在子组件根元素上面,即如果为true, 不是通过props传到子组件的属性,会自动当做普通属性绑定在子组件的根标签上,这对于深层的组件传递会产生不可预知的bug。

例子

<!--父组件-->
<template>
    <div class="parent">
        <child
           :message='message'
           placeholder='请输入账号'
           aa='14'
           @focus="handleInput">
        </child>
    </div>
</template>

<script>
import child from './child'
export default {
    components: {
        child
    },
    data () {
        return {
            message: '父元素信息',
            placeholder: '子组件的placeholder'
        }
    },
    methods: {
        handleInput () {
            console.log('父组件 handleInput')
        }
    }
}
</script>
<!--子组件-->
<template>
    <div class="child">
        <input type="text" v-bind="$attrs" v-on="$listeners">
    </div>
</template>

<script>
export default {
    inheritAttrs: false, // 如果不设置为false,则没有被子组件继承的父组件属性都会绑定在子组件根元素上
    props: {
        message: {
            type: String,
            default: ''
        }
    },
    mounted () {
        console.log('attrs', this.$attrs)
    }
}
</script>