Vue简明实用教程(14)——Vue的组件


版权声明

  • 本文原创作者:谷哥的小弟
  • 作者博客地址:http://blog.csdn.net/lfdfhl

概述

VUE推荐前端采用 SPA 方式进行开发。在SPA(single page application)方式中,一个应用程序只有一个HTML页面。所以,也倡导一个页面中只有一个Vue的实例。

为了实现代码重用提升开发效率,可以根据业务功能将页面划分为不同的组件(component)以便于日后维护与修改。组件是可复用的实例,与Vue实例类似,它拥有自身的data、computed、methods 、生命周期函数。

组件

Vue的组件可以为两大类:

  • 1、全局组件
  • 2、局部组件

全局组件

全局注册的组件可以用在其被注册之后的任何 通过 new Vue 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。简单地说:全局组件注册给Vue实例后可在任意Vue实例的范围内使用该组件。

全局组件语法

Vue.component('my-component-name', {
  // ... options ...
})

全局组件要点

  • 1、全局组件的名称请勿使用Java风格的驼峰命名法,名称中最好勿含大写字母
  • 2、全局组件的Html代码必须有且只有一个root元素(例如:div)
  • 3、全局组件的data必须是一个函数
  • 4、在Vue的作用范围内根据组件名使用全局组件,其使用方式非常类似于普通标签的使用

全局组件示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue</title>
    <!-- 引入vue -->
    <script src="js/vue.js"></script>
    <script type="text/javascript">
        // 声明Vue的实例
        let vueInstance = null;
        // 入口函数
        window.onload = function () {
            // 定义全局组件1
            Vue.component('com1',{
                template:'<div><h2>Hello Vue</h2></div>'
            });

            // 定义全局组件2
            Vue.component('com2',{
                // 显示数据
                template:'<div><h2>Hello {{site}}</h2></div>',
                data(){
                    return{
                        site:"CSDN"
                    }
                }
            });

            // 定义全局组件3
            Vue.component('com3',{
                // 双向绑定
                template:'<div><h2>Hello {{site}}</h2><input type="text" v-model="site"></div>',
                data(){
                    return{
                        site:"CSDN"
                    }
                }
            });

            // 定义全局组件4
            Vue.component('com4',{
                // 点击事件
                template:'<div><h2>Hello {{counter}}</h2><button @click="add(10)">点击执行counter++</button></div>',
                data(){
                    return{
                        site:"CSDN",
                        counter:0
                    }
                },
                methods:{
                    add(count){
                        this.counter+=count;
                    }
                },
                computed:{

                },
                // 组件生命周期方法
                beforeCreate(){
                    console.log("beforeCreate");
                },
                created(){
                    console.log("created");
                },
                // ...省略组件的其它声明周期方法...
                beforeDestroy(){
                    console.log("beforeDestroy");
                },
                destroyed(){
                    console.log("destroyed");
                },
            });

            // 初始化Vue实例
            vueInstance=new Vue({
                el: "#div1",
                data: {
                    name: "谷哥的小弟"
                },
                methods: {
                },
                computed:{
                }
            });
        }
    </script>
</head>
<body>
    <h2 style="color: red;">本文作者:谷哥的小弟</h2>
    <h2 style="color: red;">博客地址:http://blog.csdn.net/lfdfhl</h2>
    <div id="div1">
        <h3>{{name}}</h3>
        <hr/>
        <!-- 使用全局组件 -->
        <com1></com1>
        <hr/>
        <com2></com2>
        <hr/>
        <com3></com3>
        <hr/>
        <com4></com4>
    </div>

</body>
</html>

在这里插入图片描述

局部组件

局部组件指的是未在全局组件中注册的组件,因此只能使用于局部。从使用语法和用途上来讲局部组件与全局组件并无明显区别,大致一致。

局部组件语法

new Vue({
    el: ,
    data: {
        
    },
    methods: {

    },
    computed: {

    },
    // 局部组件
    components: {
    }
})

局部组件示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue</title>
    <!-- 引入vue -->
    <script src="js/vue.js"></script>
    <script type="text/javascript">
        // 局部组件
        let com1={
            // 显示数据
            template:'<div><h2>Hello {{site}}</h2></div>',
            data(){
                return{
                    site:"CSDN"
                }
            }
        }

        // 声明Vue的实例
        let vueInstance = null;
        // 入口函数
        window.onload = function () {

            // 初始化Vue实例
            vueInstance = new Vue({
                el: "#div1",
                data: {
                    name: "谷哥的小弟"
                },
                methods: {

                },
                computed: {

                },
                components: {
                    // 局部组件1
                    com1:com1,
                    // 局部组件2
                    com2: {
                        template: '<div><h2>Hello {{counter}}</h2><button @click="add(10)">点击执行counter++</button></div>',
                        data() {
                            return {
                                site: "CSDN",
                                counter: 0
                            }
                        },
                        methods: {
                            add(count) {
                                this.counter += count;
                            }
                        }
                    }
                }
            });
        }
    </script>
</head>
<body>
<h2 style="color: red;">本文作者:谷哥的小弟</h2>
<h2 style="color: red;">博客地址:http://blog.csdn.net/lfdfhl</h2>
<div id="div1">
    <h3>{{name}}</h3>
    <hr/>
    <!-- 使用局部组件 -->
    <com1></com1>
    <com2></com2>
</div>

</body>
</html>

在这里插入图片描述

父组件向子组件传递数据

在Vue框架中,父组件可通过prop向子组件传递数据。所有的prop都使得其父子prop之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

父组件向子组件传递的数据可分为两类:

  • 1、静态数据
  • 2、动态数据

父组件向子组件传递静态数据

父组件在标签上使用key=value的方式声明静态数据,子组件内部使用props数组接收所有key并在子组件中使用静态数据。

父组件向子组件传递动态数据

父组件在标签上使用v-bind:key=value的方式绑定动态数据(例如:Vue实例中data里的数据),子组件内部使用props数组接收所有key并在子组件中使用动态数据。故,子组件的数据可随着父组件中数据的变化而变化。

父组件向子组件传递数据示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue</title>
    <!-- 引入vue -->
    <script src="js/vue.js"></script>
    <script type="text/javascript">
        // 局部组件1
        let com1={
            // 显示数据以及从父组件传递而来的静态数据
            template:'<div><h2>Hello {{site}} {{nickname}} {{number}}</h2></div>',
            data(){
                return{
                    site:"CSDN"
                }
            },
            // 接收从父组件传递而来的静态数据
            props:['nickname','number']
        };

        // 局部组件2
        let com2={
            // 显示数据以及从父组件传递而来的动态数据
            template:'<div><h2>Hello {{site}} {{myname}} {{myage}}</h2></div>',
            data(){
                return{
                    site:"CSDN"
                }
            },
            // 接收从父组件传递而来的动态数据
            props:['myname','myage']
        }

        // 声明Vue的实例
        let vueInstance = null;
        // 入口函数
        window.onload = function () {

            // 初始化Vue实例
            vueInstance = new Vue({
                el: "#div1",
                data: {
                    name: "谷哥的小弟",
                    age:18
                },
                methods: {

                },
                computed: {

                },
                components: {
                    // 局部组件1
                    com1:com1,
                    // 局部组件2
                    com2:com2,
                }
            });
        }
    </script>
</head>
<body>
<h2 style="color: red;">本文作者:谷哥的小弟</h2>
<h2 style="color: red;">博客地址:http://blog.csdn.net/lfdfhl</h2>
<div id="div1">
    <hr/>
    <!-- 父组件向子组件传递静态数据 -->
    <com1 nickname="zxx" number=9527></com1>
    <hr/>

    <!-- 父组件向子组件传递动态数据 -->
    <h3>{{name}}</h3>
    <input type="text" v-model="name">
    <br/>
    <h3>{{age}}</h3>
    <input type="text" v-model="age">
    <br/>
    <!-- 向组件传递两个数据:myname和myage其值为Vue实例中data里的数据-->
    <com2 v-bind:myname="name" v-bind:myage="age"></com2>
</div>

</body>
</html>

在这里插入图片描述

父组件向子组件传递事件

父组件除了可以向子组件传递数据以外还可以向子组件传递事件。也就是说:在父组件中定义事件(函数),当事件(函数)被传递至子组件时子组件可执行该事件(函数)。

而且,通过事件的传递可以变相的实现子组件向父组件传递数据。

父组件向子组件传递事件语法如下:

<组件标签 @被传递的事件="父组件中事件名"></组件标签>

子组件执行父组件的事件语法如下:

 this.$emit("被传递的事件",[参数]);

示例如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue</title>
    <!-- 引入vue -->
    <script src="js/vue.js"></script>
    <script type="text/javascript">
        // 局部组件1
        let com1={
            // 显示数据以及从父组件传递而来的动态数据
            // 处理点击事件
            template:'<div><h2>Hello {{site}} {{myname}} {{myage}}</h2><button @click="childf1">Click Here</button></div>',
            data(){
                return{
                    site:"CSDN"
                }
            },
            // 接收从父组件传递而来的动态数据
            props:['myname','myage'],
            methods:{
                childf1(){
                    alert("This is childf1");
                }
            }
        };

        // 局部组件2
        let com2={
            // 显示数据以及从父组件传递而来的动态数据
            // 处理点击事件
            template:'<div><h2>Hello {{site}} {{myname}} {{myage}}</h2><button @click="childf2">Click Here</button></div>',
            data(){
                return{
                    site:"CSDN"
                }
            },
            // 接收从父组件传递而来的动态数据
            props:['myname','myage'],
            methods:{
                childf2(){
                    alert("This is childf2");
                    // 执行父组件传递而来的事件
                    this.$emit("myparentevent");
                }
            }
        };

        // 局部组件3
        let com3={
            // 显示数据以及从父组件传递而来的动态数据
            // 处理点击事件
            template:'<div><h2>Hello {{site}} {{myname}} {{myage}}</h2><button @click="childf3">Click Here</button></div>',
            data(){
                return{
                    site:"CSDN"
                }
            },
            // 接收从父组件传递而来的动态数据
            props:['myname','myage'],
            methods:{
                childf3(){
                    alert("This is childf3");
                    // 执行父组件传递而来的事件并传参
                    this.$emit("myparentevent",27);
                }
            }
        };

        // 局部组件4
        let com4={
            // 显示数据以及从父组件传递而来的动态数据
            // 处理点击事件
            template:'<div><h2>Hello {{site}} {{myname}} {{myage}}</h2><button @click="childf4">Click Here</button></div>',
            data(){
                return{
                    site:"CSDN"
                }
            },
            // 接收从父组件传递而来的动态数据
            props:['myname','myage'],
            methods:{
                childf4(){
                    alert("This is childf4");
                    // 执行父组件传递而来的事件并传参
                    let obj={"country":"China","city":"HK"};
                    this.$emit("myparentevent",obj);
                }
            }
        };

        // 声明Vue的实例
        let vueInstance = null;
        // 入口函数
        window.onload = function () {

            // 初始化Vue实例
            vueInstance = new Vue({
                el: "#div1",
                data: {
                    name: "谷哥的小弟",
                    age:18
                },
                methods: {
                    parentf1(){
                        alert("This is parentf1");
                    },
                    parentf2(){
                        alert("This is parentf2");
                    },
                    parentf3(age){
                        alert("This is parentf3");
                        // 接收子组件传递而来的数据并修改父组件中data里的数据
                        this.age=age;
                    },
                    parentf4(obj){
                        alert("This is parentf4");
                        // 接收子组件传递而来的对象
                        alert(obj.country+" "+obj.city);
                    }
                },
                computed: {

                },
                components: {
                    // 局部组件1
                    com1:com1,
                    // 局部组件2
                    com2:com2,
                    // 局部组件3
                    com3:com3,
                    // 局部组件4
                    com4:com4,
                }
            });
        }
    </script>
</head>
<body>
<h2 style="color: red;">本文作者:谷哥的小弟</h2>
<h2 style="color: red;">博客地址:http://blog.csdn.net/lfdfhl</h2>
<div id="div1">
    <hr/>
    <!-- 父组件向子组件传递动态数据 -->
    <h3>{{name}}</h3>
    <input type="text" v-model="name">
    <br/>
    <h3>{{age}}</h3>
    <input type="text" v-model="age">
    <br/>
    <!-- 向组件传递两个数据:myname和myage其值为Vue实例中data里的数据-->
    <com1 v-bind:myname="name" v-bind:myage="age"></com1>

    <hr/>
    <!-- 父组件向子组件传递动态数据和事件 -->
    <h3>{{name}}</h3>
    <input type="text" v-model="name">
    <br/>
    <h3>{{age}}</h3>
    <input type="text" v-model="age">
    <br/>
    <!-- 向组件传递两个数据:myname和myage其值为Vue实例中data里的数据-->
    <!-- 向组件传递事件 -->
    <com2 v-bind:myname="name" v-bind:myage="age" @myparentevent="parentf2"></com2>


    <hr/>
    <!-- 父组件向子组件传递动态数据和事件 -->
    <h3>{{name}}</h3>
    <input type="text" v-model="name">
    <br/>
    <h3>{{age}}</h3>
    <input type="text" v-model="age">
    <br/>
    <!-- 向组件传递两个数据:myname和myage其值为Vue实例中data里的数据-->
    <!-- 向组件传递事件 -->
    <com3 v-bind:myname="name" v-bind:myage="age" @myparentevent="parentf3"></com3>

    <hr/>
    <!-- 父组件向子组件传递动态数据和事件 -->
    <h3>{{name}}</h3>
    <input type="text" v-model="name">
    <br/>
    <h3>{{age}}</h3>
    <input type="text" v-model="age">
    <br/>
    <!-- 向组件传递两个数据:myname和myage其值为Vue实例中data里的数据-->
    <!-- 向组件传递事件 -->
    <com4 v-bind:myname="name" v-bind:myage="age" @myparentevent="parentf4"></com4>
</div>

</body>
</html>

在这里插入图片描述

插槽

在组件开发中,我们还可以使用插槽slot在template中预先占位;再在使用组件时替换占位即可。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue</title>
    <!-- 引入vue -->
    <script src="js/vue.js"></script>
    <script type="text/javascript">
        // 局部组件
        let com1={
            // 在template中设置两个插槽s1和s2
            template:'<div><slot name="s1"></slot><h2>Hello {{site}}</h2><slot name="s2"></slot></div>',
            data(){
                return{
                    site:"CSDN"
                }
            }
        }

        // 声明Vue的实例
        let vueInstance = null;
        // 入口函数
        window.onload = function () {

            // 初始化Vue实例
            vueInstance = new Vue({
                el: "#div1",
                data: {
                    name: "谷哥的小弟"
                },
                methods: {

                },
                computed: {

                },
                components: {
                    // 局部组件1
                    com1:com1
                }
            });
        }
    </script>
</head>
<body>
<h2 style="color: red;">本文作者:谷哥的小弟</h2>
<h2 style="color: red;">博客地址:http://blog.csdn.net/lfdfhl</h2>
<div id="div1">
    <h3>{{name}}</h3>
    <hr/>
    <!-- 不使用插槽 -->
    <com1></com1>
    <hr/>
    
    <!-- 在局部组件中使用插槽 -->

    <!-- 向插槽s1插入内容 -->
    <com1><span slot="s1">Welcome</span></com1>
    <hr/>
    <!-- 向插槽s2插入内容 -->
    <com1><span slot="s2">Welcome</span></com1>
    <hr/>
    <!-- 向插槽s1和s2插入内容 -->
    <com1><span slot="s1">Hello</span><span slot="s2">Welcome</span></com1>
</div>

</body>
</html>

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谷哥的小弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值