Vue2组件

时间:2024-10-17 16:52:26

1.Vue组件

在vue中,组件是最重要的组合部分,官方中定义组件为可复用的vue实例,分为全局组件和局部组件,接下来通过实例来分别演示两种不同的组件。

1.1.全局组件

全局组件可以在任意Vue实例下使用。

<div id="app">
    <mycomponent></mycomponent>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    Vue.component('mycomponent', {
        template: '<h3>我是全局组件</h3>'
    });
    var vm = new Vue({
        el: '#app',
    });
</script>

通过上面的例子,我们可以总结出全局组件的使用步骤:

  1. 使用vue.component()注册组件,需要提供2个参数:组件的标签名和组件构造器。
  2. vue.component()内部会调用组件构造器,创建一个组件实例
  3. 将组建挂载到某个vue实例下。

注意:一个组件的template部分,必须要包裹在一个根容器中。

因为组件是可复用的vue实例,所以它们也能有data、computed、watch、methods以及生命周期钩子等。

<div id="app">
    <mycomponent></mycomponent>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    Vue.component('mycomponent', {
        template: `<div>
                        <h3>我是全局组件</h3>
                        {{num}} <button @click="add">加</button>
                   </div>`,
        data(){
            return {
                num:1
            }
        },
        methods:{
            add(){
                this.num++;
            }
        }
    });
    var vm = new Vue({
        el: '#app',
    });
</script>

上面代码中有两个注意事项:

  1. 组件模板的内容,可以写在一对反引号中(``),这样就可以不使用字符串拼接的形式了。
  2. 一个组件的data选项必须是一个函数,该函数返回一个对象。

1.2.局部组件

如果不需要全局注册,或者是让组件使用在其它组件内,可以用选项对象的components属性实现局部注册。 因此我们可以将上面的全局组件改为局部组件。

<div id="app">
    <mycomponent></mycomponent>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    let obj = {
        template: `<div>
                       <h3>我是局部组件</h3>
                       {{num}} <button @click="add">加</button>
                   </div>`,
        data(){
            return {
                num:1
            }
        },
        methods:{
            add(){
                this.num++;
            }
        }
    };
    var vm = new Vue({
        el: '#app',
        components:{    //声明局部组件
            mycomponent:obj
        }
    });
</script>

1.3.组件模板

如果组件中的template内容过多,那么可以使用组件模板来声明template中的内容。

<div id="app">
    <mycomponent></mycomponent>
</div>
<!-- 组件模板 -->
<template id="mytemplate">
    <div>
        <h3>我是局部组件</h3>
        {{num}} <button @click="add">加</button>
    </div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    let obj = {
        template: '#mytemplate',      //使用选择器应用组件模板
        data() {
            return {
                num: 1
            }
        },
        methods: {
            add() {
                this.num++;
            }
        }
    };
    var vm = new Vue({
        el: '#app',
        components: { //声明局部组件
            mycomponent: obj //组件名:组件实例
        }
    });
</script>

2.父子组件

当我们继续在组件中写组件,形成组件嵌套的时候,就是我们所说的父子组件了。

<div id="app">
    <mycomponent></mycomponent>
</div>
<template id="mytemplate">
    <div>
        <h3>我是父组件</h3>
        <!-- 在父组件中使用子组件 -->
        <subcomponents></subcomponents>
    </div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    let obj = {
        template: '#mytemplate',
        data() {
            return {}
        },
        components:{          //声明子组件
            subcomponents:{
                template:`<div>我是子组件</div>`
            }
        }
    };
    var vm = new Vue({
        el: '#app',
        components: { //声明局部组件
            mycomponent: obj //组件名:组件实例
        }
    });
</script>

3.组件之间的通信

组件与组件之间是可以互相通信的。包括父子组件之间、兄弟组件之间等等,都可以互相通信。 下面只讨论父子组件之间通信问题。

3.1.子组件获取父组件数据

在vue中,组件实例的作用域是孤立的,默认情况下,父子组件的数据是不能共享的,也就是说,子组件是不能直接访问父组件的数据的。为此,vue给我们提供了一个数据传递的选项prop,用来将父组件的数据传递给子组件。具体使用如下:

<div id="app">
    <mycomponent></mycomponent>
</div>
<template id="mytemplate">
    <div>
        <h3>我是父组件</h3>
        <subcomponents msg="hello world!"></subcomponents>
    </div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    let obj = {
        template: '#mytemplate',
        data() {
            return {}
        },
        components:{
            subcomponents:{
                template:`<div>我是子组件,我能获取父组件传递的数据:{{msg}}</div>`,
                props:['msg']
            }
        }
    };
    var vm = new Vue({
        el: '#app',
        components: { //声明局部组件
            mycomponent: obj //组件名:组件实例
        }
    });
</script>

上面实例中,子组件获取父组件传递的数据的步骤为:
1在子组件标签中,声明 msg 属性,属性值即为父组件向子组件传递的值。
2在子组件中,使用props选项,声明接收父组件向子组件传递值的载体,即 ‘msg’ 。
3子组件中就可以使用 msg 获取父组件向子组件传递的值了。
也可以使用 v-bind 绑定子组件标签属性,这样就可以将父组件data数据传递个子组件了。

<div id="app">
    <mycomponent></mycomponent>
</div>
<template id="mytemplate">
    <div>
        <h3>我是父组件</h3>
        <subcomponents :msg="welcome"></subcomponents>
    </div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    let obj = {
        template: '#mytemplate',
        data() {
            return {
                welcome:'hello world!'
            }
        },
        components:{
            subcomponents:{
                template:`<div>我是子组件,我能获取父组件传递的数据:{{msg}}</div>`,
                props:['msg']
            }
        }
    };
    var vm = new Vue({
        el: '#app',
        components: { //声明局部组件
            mycomponent: obj //组件名:组件实例
        }
    });
</script>

3.2.父组件获取子组件数据

和上面不一样的是,父组件想要获取子组件的数据时,需要子组件通过emit主动将自己的数据发送给父组件。

<div id="app">
    <mycomponent></mycomponent>
</div>
<template id="mytemplate">
    <div>
        <h3>我是父组件,接收子组件传递过来的数据:{{msg}}</h3>
        <subcomponents @childmsg="get" msg="hello world!"></subcomponents>
    </div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    let obj = {
        template: '#mytemplate',
        data() {
            return {
                msg:''
            }
        },
        methods:{
            get(msg) {
                this.msg = msg;
            }
        },
        components: {
            subcomponents: {
                template: `<div>
                             我是子组件,我能获取父组件传递的数据:{{msg}}
                             <input type="button" value="给父组件发数据" @click="send">
                           </div>`,
                props: ['msg'],
                data() {
                    return {
                        message: '我是子组件的数据'
                    }
                },
                methods: {
                    send() {
                        this.$emit('childmsg', this.message);
                    }
                }
            }
        }
    };
    var vm = new Vue({
        el: '#app',
        components: { //声明局部组件
            mycomponent: obj //组件名:组件实例
        }
    });
</script>

首先,我们需要在子组件中触发一个主动发送数据的事件,上面的例子中是一个点击事件send

其次,在点击事件中使用emit方法,这个emit接收两个参数:传递数据的事件和需要传递的数据,这个传递数据的事件也是自定义的;

然后在父组件中引用子组件,并在引用的子组件中使用on监听上一步传递数据的事件,上面的例子中是childmsg

最后在父组件中使用这个事件,这个事件带有一个参数,就是从子组件发送过来的数据。