随着模块化开发的理念越来越被开发者所重视,如何快速高效的开发项目成为了开发中所要注意的重点。在vue.js中组件系统作为一个重要的概念,它提供的组件可以独立、重复的使用来构建大型的应用。组件可以扩展HTML元素,封装可重用的HTML代码,我们可以将组件看作自定义的HTML元素。

组件的使用步骤:

1.使用 Vue.extend()创建组件构造器
2.使用 Vue.componnet()注册组件
3.在 Vue的实例作用域范围内使用组件

vue组件——最简单的demo实例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue-组件</title>
    <script type="text/javascript" src="http://unpkg.com/vue"></script>
</head>
<body>
    <div id="app">
        <my-component></my-component>
    </div>
    
    <script>
        // 创建组件构造器
        var myComponent = Vue.extend({
            template: '<div>this is a component!</div>'
        });
        // 全局注册组件
        Vue.component('my-component', myComponent)
        
        var vm = new Vue({
            el: '#app'
        })
    </script>
</body>
</html>

这个例子是我们常见的一个组件使用,这是vue1.x中的组件的写法,vue2.x提出了更加语义化的写法,但要注意vue.extend()的使用,这里不做赘述,详情看下文。
提醒:这里需要注意,组件注册需要在Vue实例之前,这里和自定指令需要注意的事项一致。

组件的全局注册和局部注册

组件和指令一样都可以分为全局的和局部的。
上面的示例就是一个全局的组件,在开发中我们可能更多的需要的不是全局组件,而是局部组件。组件包含在其他组件内的情况出现的几率比较大,这时我们可以用选项的components对象属性实现局部注册组件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue-组件</title>
    <script type="text/javascript" src="http://unpkg.com/vue"></script>
</head>
<body>
    <div id="app">
        <my-component1></my-component1>
        <my-component2></my-component2>
    </div>
    
    <script>
        var myComponent1 = Vue.extend({
            template: '<div>this is a component1!</div>'
        });

        var myComponent2 = Vue.extend({
            template: '<div>this is a component2!</div>'
        });

        var vm = new Vue({
            el: '#app',
            components: {
                'myComponent1': myComponent1,
                'myComponent2': myComponent2
            }
        })
    </script>
</body>
</html>

这种局部注册组件的方式使我们常用的形式之一。

我们也经常见到这样的组件使用方式,如下图示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue-组件</title>
    <script type="text/javascript" src="http://unpkg.com/vue"></script>
</head>
<body>
    <div id="app">
        <div v-text="parentMsg"></div>
        <!-- 组件1 -->
        <my-component1></my-component1>
        <!-- 组件2 -->
        <my-component2></my-component2>
        <!-- 组件3 -->
        <div id="component"></div>
        <!-- 挂载组件 -->
        <div id="globalComponent"></div>
    </div>
    
    <script>
        var myComponent1 = {
            template: '<div v-text="child-msg"></div>',
            props: ['childMsg'],
            data: function(){
                return {
                    msg: 'this is a component1!'
                }
            }
        };

        var myComponent2 = {
            template: '<div v-text="msg"></div>',
            data: function(){
                return {
                    msg: 'this is a component2!'
                }
            }
        };

        var myComponent3 = {
            template: '<div v-text="msg"></div>',
            data: function(){
                return {
                    msg: 'this is a component3!'
                }
            }
        };

        // 全局组件
        var myGlobalComponent = Vue.component('my-component1', myComponent1);

        // 扩展实例的构造器组件
        var myCmopnentExtend = Vue.extend(myComponent3);

        // 实例化的构造器组件可以自由的绑定在任意元素按上
        var vc = new myCmopnentExtend().$mount('#component');

        // 创建vm 实例,使用局部组件
        var vm = new Vue({
            el: '#app',
            data: {
                parentMsg: 'haha'
            },
            components: {
                'myComponent2': myComponent2
            }
        });
        
        // 挂载组件
        var vb = new myGlobalComponent().$mount('#globalComponent');
    </script>
</body>
</html>

这种使用方法vue.js官网提供的方法,vue2.x在中推荐使用的,前者是在vue1.0中推荐的。
但是在这里我们需要注意的是,vue.extend()这种创建构造器和vue.component()全局注册组件,可以通过$mount('xxx')绑定到任意指定的元素(在VUE2.0中这种function component,它不是vue的实例,只能进行视图的渲染而不能进行逻辑操作)。

组件间的通信

父子组件间的通信用vue.js开发文档中的介绍就是props down, events up;
非父子组件间的通信,可以使用一个空Vue实例,来作为中央事件总线。

<div id="app">

    <h2 v-text="sTitle"></h2>
    <mc-one :child-msg="parentMsg"></mc-one>
    <mc-two :child-msg="parentMsg" v-on:backmsg="strReverse"></mc-two>
    <div class="msg3" v-text="parentMsg"></div>
</div>

<script>
    var bus = new Vue();
    //     子组件1
    var childOne = {
        name: 'childOne',
        props: ['childMsg'],
        template: '<div v-text="childMsg" @click="commit" class="msg1"></div>',
        data: function(){
            return {
                msg: 'component1'
            }
        },
        methods:{
            commit: function(){
                bus.$emit('oneToTwo', {
                    msg: 'i am component1'
                });
            }
        },
        mounted(){
            bus.$on('twoToOne', (data) => {
                this.msg = data.msg
            })
        }
    };
    //     子组件2
    var childTwo = {
        name: 'childTwo',
        props: ['childMsg'],
        template: '<div v-text="msg" @click="btnClick" class="msg2"></div>',
        data: function(){
            return {
                msg: 'component2'
            }
        },
        mounted(){
            bus.$on('oneToTwo', (data) => {
                this.msg = data.msg;
            })
        },
        methods:{
            btnClick: function(){
                this.$emit('backmsg');
            }
        }
    };
    // 父组建
    var vm = new Vue({
        el: '#app',
        data: {
            sTitle:'组件间的通信',
            parentMsg:'i am parent component'
        },
        components: {
            'mcOne': childOne,
            'mcTwo': childTwo
        },
        methods: {
            strReverse: function(){
                this.parentMsg = this.parentMsg.split('').reverse().join('');
            }
        }
    });
</script>

这个小demo包含了3部分父组件,子组件1,子组件2,父组件通过props向子组件1传递信息,子组件1通过空组件bus中央总线向子组件2传递信息,子组件2通过event 向父组件传递信息。

在开发中小型应用时这样的状态信息传递已经可以满足大部分项目的要求,但对中大型项目来说,随着状态信息的增多,业务逻辑的复杂,就需要统一的状态管理模式来保证应用中所有的组件的正确状态。我们就需要vuex来进行状态信息的处理和传递了。

vuex本文不做论述。


缘自世界
3.5k 声望8.4k 粉丝

心态很重要,我始终相信没有不会做的,只有不想做的,在这个人人都聪明的今天,你不凭智慧,只需努力就能打败90%的对手,如果你再展现出你50%的智慧,我想没有什么问题可以难倒你。