不一样的角度理解Vue组件

什么是组件

以Java、C#等面向对象编程语言的角度去理解Vue组件,能够发现组件和面向对象编程的方式和风格很相似。一切事物皆为对象,通过面向对象的方式,将现实世界的事物抽象成对象,现实世界中的关系抽象成类、继承。

在面向对象编程语言中,类(组件)具有属性,它是对象的状态的抽象;类(组件)具有操作,它是对象的行为的抽象。

将“类”与“组件”置换之后,如果没有感觉违和,恭喜你,已经对组件有了深刻的认识。

比如将人类这一对象抽取为一个组件,基本的属性有:姓名、年龄、国籍;基本的方法有:吃饭、睡觉、跑步等。

对外我们需要暴露(getter)姓名、年龄、国籍三个属性,并可以由外部对组件属性进行初始化(setter)。

<template>
    <div class="person">
        <div>{{ name }} + {{ age }} + {{ country }}</div>
        <button @click="eat">点击</button>
    </div>
</template>

<script>
export default {
    name: 'person',
    props: {
        name: {
            type: String,
            required: false,
            default: '无名氏'
        },
        age: {
            type: Number,
            required: false,
            default: 0
        },
        country: {
            type: String,
            required: false,
            default: '地球人'
        }
    },
    methods: {
        eat() {
            consloe.log('吃饭')
        },
        sleep() {
            consloe.log('睡觉')
        },
        run() {
            consloe.log('跑步')
        }
    }
}
</script>

在使用组件时,通过传参的方式为组件传递值。

<person :age="20" :name="'小明'" :country="'中国人'"></person>

对外公开接口,将数据与操作数据的源代码进行有机的结合,形成“组件”,其中数据和函数都是组件的成员。

因为组件已经封装了数据以及操作数据的过程,所以我们不需要关注组件内部的方法是如何实现的,或者说,我们不用关心组件内发生了什么,我们只需要给它数据,而它给我们结果就行。

自定义事件

但是,外部不可以直接访问属性值,如果我想获取person组件相关的属性,该如何做?

答案是使用$emit自定义事件

修改button的点击事件函数:

<button @click="handleClick">点击</button>

添加处理点击事件的函数:

export default {
    name: 'person',
    methods: {
        handleClick() {
            this.$emit('getAll', {
                age: this.age,
                name: this.name,
                country: this.country
            })
        }
    }
}

在使用组件时,对组件添加自定义函数@getAll

<template>
    <div>
        <person :age="20" :name="'小明'" :country="'中国人'" @getAll="getAll"></person>
    </div>
</template>

<script>
export default {
    name: 'test',
    methods: {
        getAll(info) {
            consloe.log(info)
        }
    }
}
</script>

测试代码提取地址,提取码:pvcq

实际案例

在网页开发中,你可能会用到标签,而你可能会想到标签不可能在一个页面使用一次,可能是多次使用到。你还可能会想到因为不同的情况而自定义一些宽度、高度和颜色。

所以可以将标签相关的HTML代码和CSS封装到组件中,对外,我们暴露width、height和type参数。在使用时,因为不同的情况而需要自定义,那么传递参数即可。

<template>
    <view
        :style="{ width: width, height: height }"
        :class="['owl-tag-' + type]"
        class="owl-tag text-xs flex align-center justify-center"
    >
        <slot></slot>
    </view>
</template>

<script>
    name: 'owl-tag',
    props: {
        // 可传入有效值为 primary | gray
        type: {
            type: String,
            default: 'primary'
        },
        width: {
            type: String,
            required: false
        },
        height: {
            type: String,
            required: false
        }
    }
</script>

<style>
.owl-tag {
    border-radius: 8rpx;
    padding: 6rpx 10rpx;
}

.owl-tag-primary {
    color: white;
    background-color: #87cefa;
}

.owl-tag-gray {
    color: #81868a;
    background-color: #f0f1f5;
}
</style>

这些工作做好了,一个组件就被我们定义好了。想用就调用,想改就传参,这就是组件的好处。

<template>
    <owl-tag
        :type="'primary'"
        :height="'45rpx'"
        :width="'120rpx'"
    >
        官方帖
    </owl-tag>
</template>

改变type的值为gray,呈现的效果如下: