Vue组件之间的通信

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HH921227/article/details/80336768

Vue组件

Vue组件是可复用的Vue实例,因此其接受与 new Vue 相同的选项,如 data、computed、watch、methods 以及生命周期钩子等,只用像 el 这中根实例特有的选项,其不可使用。

Vue.Component('Link', {
    data(){
        return {
            href: 'https://vuex.vuejs.org/zh-cn/'
        };
    },
    template: '<a v-bind:href="href">Vuex</a>'
})

// 组件使用
<Link></Link>

Tips
data必须是一个函数,每个组件实例都可以维护一份被返回对象的独立拷贝。

data(){
    return {
        href: 'https://vuex.vuejs.org/zh-cn/'
    };
}

Vue组件注册

  • 全局注册
    通过Vue.Component(componentName,options)进行全局组件注册
Vue.Component('button-count',{
    ...options
})
  • 局部注册
    通过components选项进行组件局部注册
import ButtonCount from 'ButtonCount';
new Vue({
    components: {
        ButtonCount
    }
})

Vue组件数据传递

  • 通过 prop 向子组件传递数据
    所有的prop都是父子组件之间形成一个单行向下的数据传递,即父组件的prop更新会向子组件传递,反之不行。
// parent
<template>
    <span :class="classes">
        <Icon :type="person" :size="20" :color="#ddd"></Icon>
    </span>
</template>
<script>
    export default {
        name: 'Avater',
        props: {
            type: {
                type: String,
                default: 'circle'
            }
        },
        computed: {
            classes() {
                return `${this.type}`
            }
        }
    }
</script>
// child
<template>
    <i :class="classes" :style="styles"></i>
</template>
<script>
    export default {
        name: 'Icon',
        props: {
            type: String,
            size: [Number,String],
            color: String
        },
        computed: {
            classes(){
                return `${this.type}`
            },
            styles(){
                const style = {};
                if(this.color){
                    style['color'] = this.color;
                }
                if(this.size){
                    style['font-size'] = (typeof this.size === 'number') ? `${this.size}px` : `${this.size}`;
                }
            }
        }
    }
</script>
  • 通过 slot 向子组件传递数据
    通过元素实现内容分发
// parent
<template>
    <Layout>
        <section slot="header">this layout header</section>
        <section slot="main">this layout main</section>
        <section slot="footer">this layout footer</section>
    </Layout>
</template>
<script>
export default {
    name: 'ParentLayout'
}
</script>
// child
<template>
    <div>
        <header>
            <slot name="header"></slot>
        </header>
        <main>
            <slot name="main"></slot>
        </main>
        <footer>
            <slot name="footer"></slot>
        </footer>
    </div>
</template>
<script>
export default {
    name: 'Layout'
}
</script>
  • 通过自定义事件向父组件传递数据
    触发的事件名需要完全匹配监听这个事件所用的名称
// parent
<template>
<BaseButton @click="handClick">click me</BaseButton>
</template>
<script>
export default {
    name: 'ParentButton',
    methods: {
        handClick(event){
            console.log(event);
        }
    }
}
</script>
// child
<template>
    <button @click="handClick"></button>
</template>
<script>
export default {
    name: 'BaseButton',
    methods: {
        handClick(){
            this.$emit('click',event);
        }
    }
}
</script>
  • 通过 event bus 实现非父子组件通信
    使用一个空的 Vue 实例作为中央事件总线
    在这两个组件之间引入这个中央事件总线,然后emit,on相应的事件
// Bus
var bus = new Vue()
// 触发组件 A 中的事件
bus.$emit('selected', value)
// 在组件 B 创建的钩子中监听事件
bus.$on('selected', function (val) {
  // ...
})


  • 通过 vuex 实现组件数据共享

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。虽然 Vuex 可以帮助我们管理共享状态,但也附带了更多的概念和框架。这需要对短期和长期效益进行权衡。如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 global event bus 就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。

阅读更多

扫码向博主提问

HH921227

非学,无以致疑;非问,无以广识
  • 擅长领域:
  • 前端
  • Vue
  • React
  • Http
  • 算法
去开通我的Chat快问
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页