提示

本文主要讲解 Vue 中的组件。@ermo

# 组件

组件(Component)是 Vue.js 最强大的功能之一。组件可以封装可重用的代码,用于扩展 HTML 代码。

# 全局组件

定义全局组件的语法为:

Vue.component(name, options);

name 为组件名,options 为组件配置。

如下是一个最简单的组件示例,全局实例都可以使用的组件:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14"></script>
</head>

<body>
    <div id="app">
        <ermo></ermo>
        <ermo></ermo>
        <ermo></ermo>
        <ermo></ermo>
    </div>

    <script>
        Vue.component('ermo', {
            template: '<h2>文本</h2>'
        });
        var vm = new Vue({
            el: '#app'
        });
    </script>
</body>

</html>

组件中的模板也可以使用 Vue.js 中的指令,组件可以重复复用。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14"></script>
</head>

<body>
    <div id="btn-example">
        <button-component></button-component>
        <button-component></button-component>
        <button-component></button-component>
    </div>

    <script>
        Vue.component('button-component', {
            data: function() {
                return {
                    count: 0
                }
            },
            template: '<button v-on:click="count++">点我{{count}}</button>'
        });
        var btnVm = new Vue({
            el: '#btn-example'
        });
    </script>
</body>

</html>

上例中的 data 必须返回一个函数,这样每个组件实例调用才会返回一份独立的数据拷贝。

如果将 data 修改为如下,多个组件的数据是共享的,不建议这样使用。

data: {
    count: 0
}

# 局部组件

局部组件只有当前实例可以使用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14"></script>
</head>
<body>
    <div id="app">
        <ermo></ermo>
        <ermo></ermo>
        <ermo></ermo>
    </div>
    <script>
        var child = {
            template: '<h1>自定义组件</h1>'
        }
        var vm = new Vue({
            el: '#app',
            components: {
                ermo: child
            }
        });
    </script>
</body>
</html>

# 通过 Prop 向子组件传递数据

可以在父组件定义 Prop,子组件可以使用父组件中 Prop 中自定义的属性名,从而向父组件中传递数据。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14"></script>
</head>
<body>
    <div id="app">
        <ermo msg="属性值1"></ermo>
        <ermo msg="属性值2"></ermo>
        <ermo msg="属性值3"></ermo>
    </div>
    <script>
        Vue.component('ermo', {
            props: ['msg'],
            template: '<p> 自定义属性: {{ msg }} </p>'
        });
        var vm = new Vue({
            el: '#app'
        });
    </script>
</body>
</html>

# 动态绑定 Prop

在实例化子组件时可以使用 v-bind 将自定义属性动态绑定到其他元素上。这样每当子组件上的绑定值发生改变,该数据也会动态传递到父组件上。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14"></script>
</head>
<body>
    <div id="app">
        <div>
            <input type="text" v-model="titleText" placeholder="输入文字">
            <br>
            <child v-bind:title="titleText"></child>    
            <child v-bind:title="titleText"></child>    
            <child v-bind:title="titleText"></child>    
        </div>
    </div>
    <script>
        Vue.component('child', {
            props: ['title'],
            template: '<p>绑定数据: {{title}} </p>'
        });
        var vm = new Vue({
            el: '#app',
            data: {
                titleText: ''
            }
        });
        
    </script>
</body>
</html>

下例将 language 属性传递到可重复的每一个子组件中。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14"></script>
</head>

<body>
    <div id="app">
        <ol>
            <language-li v-for="item in languages" v-bind:language="item"></language-li>
        </ol>
    </div>
    <script>
        Vue.component('language-li', {
            props: ['language'],
            template: '<li> 语言: {{ language.name }},id: {{ language.id }} </li>'
        });
        var vm = new Vue({
            el: '#app',
            data: {
                languages: [
                    { id: 1, name: 'java' },
                    { id: 2, name: 'php' },
                    { id: 3, name: 'js' }
                ]
            }
        });
    </script>
</body>

</html>

# Prop 验证

组件可以为每一个 Prop 属性提供验证需求,为了定制 Prop 的验证,props 不再是一个数组,而是一个带有验证的对象,如下:

    <script>
        Vue.component('my-component', {
            props: {
                // 基础的类型检查
                age: Number,
                // 多个允许的类型
                propB: [String, Number],
                // 必填字符串
                propC: {
                    type: String,
                    required: true
                },
                // 带有默认值的数字
                propD: {
                    type: Number,
                    default: 100
                },
                propE: {
                    type: Object,
                    // 对象或数组必须返回一个函数
                    default: function () {
                        return { message: 'hello' }
                    }
                },
                // 自定义验证函数
                propF: {
                    validator: function(value) {
                        // 必须匹配下列值中的一个
                        return ['success', 'error', 'warn'].indexOf(value) !== -1
                    }
                }
            }
        });
    </script>
上次更新: 2/20/2023, 9:02:17 PM