PythonVue

Vue中最重要的角色组件详解

2019-06-22  本文已影响15人  缺月楼

可复用性的组件详解

使用组件的原因

作用:提高代码的复用性

组件的使用方法

<div id="app">
        <my-componet></my-componet>
    </div>
    <!-- 对应的内容<div id="app"><div>我是一个全局组件</div></div> -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <script>
        // Vue.component(tag, {
        //     template: '<div></div>'
        // })
        // 注册组件 第一个参数 标签名 第二个是要渲染的魔板
        Vue.component('my-componet', {
            template: '<div>我是一个全局组件</div>'
        })
        var app = new Vue({
            el: '#app',
            data: {

            }
        })
    </script>
<div id="app" style="border:2px solid red ">
        <!-- 全局组件 -->
        <my-componet></my-componet>
        <!-- 局部组件  -->
        <app-componet></app-componet>
    </div>
    <!-- 对照试验 全局组件和局部组件 -->
    <div id="bpp" style="border:2px solid green;margin-top:5px; ">
        <!-- 全局组件 -->
        <my-componet></my-componet>
        <!-- app局部组件    只能在所注册的实例中使用   这里不会显示 -->
        <app-componet></app-componet>
    </div>
    <!-- 对应的内容<div id="app"><div>我是一个全局组件</div></div> -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <script>
        // Vue.component(tag, {
        //     template: '<div></div>'
        // })
        // 注册全局组件 第一个参数 标签名 第二个是要渲染的魔板
        Vue.component('my-componet', {
            template: '<div>我是一个全局组件</div>'
        })
        var app = new Vue({
            el: '#app',
            // 局部组件 
            components: {
                'app-componet': {
                    template: '<div>我是app局部注册的一个组件组件</div>'
                }
            },
            data: {

            }

        })
        var bpp = new Vue({
            el: '#bpp',
            data: {

            }
        })
    </script>
  • 注意
    vue组件的模板在某些情况下会受到html标签的限制,比如 <table>中只能还
    <tr> , <td>这些元素,所以直接在table中使用组件是无效的,此时可以使用is属性来挂载组件
<table>
     <tbody is="my-component"></tbody>
</table>

组件使用的小技巧

<div id="app">
        <!-- 推荐使用小写字母加­进行命名(必须) -->
        <my-component></my-component>
        <!-- 点击任何一个 都会执行 可用组件方式解决  -->
        <button @click="plus">{{count}}</button>
        <button @click="plus">{{count}}</button>

        <hr><br>
        <!-- 组件方式解决 及 data必须是一个方法实践  两次点击的按钮 对象是不一致的 -->
        <btn-component></btn-component>
        <btn-component></btn-component>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                count: 1
            },
               //组件 
            components: {
                'my-component': {
                    // `template`中的内容必须被一个`DOM元`素包括 ,也可以嵌套
                    template: '<div><span>组件小技巧</span></div>'
                },

                'btn-component': {
                    template: '<button @click="count++">{{count}}</button>',
                    // 组件中的data`必须是一个方法
                    data: function() {
                        return {
                            count: 0
                        }
                    }
                }
            },
            methods: {
                plus: function() {
                    return this.count++
                }
            }

        })
    </script>

使用props传递数据 父亲向儿子传递数据

  1. 在组件中使用props来从父亲组件接收参数,注意,在props中定义的属性,都可以在组件中直接使用
    2. propps来自父级,而组件中data return的数据就是组件自己的数据,两种情况作用域就是组件本身,可以在template,computed,methods中直接使用
  2. props的值有两种,一种是字符串数组,一种是对象,本节先只讲数组
  3. 可以使用v-­bind动态绑定父组件来的内容
    先看个小栗子:

 在父组件里向子组件传递消息:
    <div id="app" style="border:2px solid green;height:200px;">
        <h5 style="text-align:center">我是父组件</h5>
        <child-component msg="我是来自父组件的内容"></child-component>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <script>
        // 一个父组件 
        var app = new Vue({
            el: '#app',
            // 定义一个子组件
            components: {
                'child-component': {
                    // 在组件中使用props来从父亲组件接收参数,
                    props: ['msg'],
                    // 注意,在props中定义的属性,都可以在 组件中直接使用
                    template: '<div style="border:2px solid red;height:70px;">{{msg}}</div>'
                }
            },
        })
    </script>

可以使用v-­bind动态绑定父组件来的内容:小栗子

 在父组件里向子组件传递消息:
    <div id="app" style="border:2px solid green;height:400px;">
        <h5 style="text-align:center">我是父组件</h5>
        <child-component msg="我是来自父组件的内容"></child-component>
        <br>
        <hr>使用v-bind进行数据动态绑定 把input中的msg传递给子组件
        <input type="text" v-model="parentmsg">
        <bind-component :msg="parentmsg"></bind-component>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <script>
        // 一个父组件 
        var app = new Vue({
            el: '#app',
           //父组件定义的内容
            data: {
                parentmsg: '今晚的月亮真圆啊'
            },
            // 定义一个子组件
            components: {
                'child-component': {
                    // 在组件中使用props来从父亲组件接收参数,
                    props: ['msg'],
                    // 注意,在props中定义的属性,都可以在 组件中直接使用
                    template: '<div style="border:2px solid red;height:70px;">{{msg}}</div>'
                },
                'bind-component': {
                    // 在组件中使用props来从父亲组件接收参数,
                    props: ['msg'],
                    // 注意,在props中定义的属性,都可以在 组件中直接使用
                    template: '<div style="border:2px solid red;height:70px;">{{msg}}</div>'
                }
            },
        })
    </script>

使用不使用v-bind的区别 :

 在父组件里向子组件传递消息:
    <div id="app" style="border:2px solid green;height:400px;">
        <h5 style="text-align:center">我是父组件</h5>
        <child-component msg="我是来自父组件的内容"></child-component>
        <hr><br>
        <!-- v-bing 对照试验 传递数组  -->
        v-bind对照试验 传递数组
        <!-- msg.length 是7 -->
        <child-component msg="[3,6,7]"></child-component>
        <!-- 使用v-bind可以识别为数组     msg.length 是3 -->
        <child-component :msg="[3,6,7]"></child-component>
        <br>
        <hr>使用v-bind进行数据动态绑定 把input中的msg传递给子组件
        <input type="text" v-model="parentmsg">
        <bind-component :msg="parentmsg"></bind-component>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <script>
        // 一个父组件 
        var app = new Vue({
            el: '#app',
            data: {
                parentmsg: '今晚的月亮真圆啊'
            },
            // 定义一个子组件
            components: {
                'child-component': {
                    // 在组件中使用props来从父亲组件接收参数,
                    props: ['msg'],
                    // 注意,在props中定义的属性,都可以在 组件中直接使用
                    template: '<div style="border:2px solid red;height:70px;">{{msg}}</div>'
                },
                'bind-component': {
                    // 在组件中使用props来从父亲组件接收参数,
                    props: ['msg'],
                    // 注意,在props中定义的属性,都可以在 组件中直接使用
                    template: '<div style="border:2px solid red;height:70px;">{{msg}}</div>'
                }
            },
        })
    </script>

单向数据流

解释 : 通过 props 传递数据 是单向的了, 也就是父组件数据变化时会传递给子组
件,但是反过来不行。
目的 :是尽可能将父子组件解耦,避免子组件无意中修改了父组件的状态。
应用场景: 业务中会经常遇到两种需要改变 prop的情况

一种是父组件传递初始值进来,子组件将它作为初始值保存起来,在自己的作用域
下可以随意使用和修改。这种情况可以在组件 data内再声明一个数据,引用父组件的 prop

 <div id="app" style="border:2px solid green;height:400px;">
        <my-component msg="我是父组件传递的数据"></my-component>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>

    <script>
        // 步骤一:注册组件
        Vue.component('my-component', {
            // 步骤二: 将父组件的数据传递进来, 并在子组件中用props接收
            props: ['msg'],
            template: ' <div>{{count}}</div>',
            data: function() {
                return {
                    // 步骤三: 将传递进来的数据通过初始值保存起来
                    // <!-- props的值可以通过this.xxx  直接进行获取-->
                    count: this.msg
                }
            },
        })
        var app = new Vue({
            el: '#app',
            data: {

            }
        })
    </script>

另一种情况就是 prop 作为需要被转变的原始值传入。这种情况用计算属性就可以了

步骤一:注册组件
步骤二:将父组件的数据传递进来,并在子组件中用props接收
步骤三:将传递进来的数据通过计算属性进行重新计算
小栗子:

 <div id="app" style="border:2px solid green;height:400px;">
        <my-component msg="我是父组件传递的数据"></my-component>
        <hr> <br>
        <!-- 需求 :通过input中输入的数据动态改变div的宽度 -->
        <!-- 传递的数据仅仅是一个数据  需要计算属性重新计算拼接 -->
        <input type="text" v-model="width">
        <width-component :width="width"></width-component>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>

    <script>
        //  场景一 步骤一:注册组件
        Vue.component('my-component', {
                // 步骤二: 将父组件的数据传递进来, 并在子组件中用props接收
                props: ['msg'],
                template: ' <div>{{count}}</div>',
                data: function() {
                    return {
                        // 步骤三: 将传递进来的数据通过初始值保存起来
                        // <!-- props的值可以通过this.xxx  直接进行获取-->
                        count: this.msg
                    }
                },
            })
            //  场景二 步骤一:注册组件
        Vue.component('width-component', {
            // 步骤二: 将父组件的数据传递进来, 并在子组件中用props接收
            props: ['width'],
            template: ' <div :style="style"></div>',
            data: function() {
                return {

                }
            },
            computed: {
                style: function() {
                    // return 出来的就是直接拼接好的style
                    return {
                        width: this.width + 'px',
                        background: 'red',
                        height: '300px'
                    }
                }
            }
        })
        var app = new Vue({
            el: '#app',
            data: {
                width: 0
            }
        })
    </script>

数据验证

vue组件中camelCased(驼峰式) 命名与kebab­case(短横线命名)
 <div id="app" style="border:2px solid green;height:400px;">
        <!-- 会报错   Unknown custom element: myComponent  在组件中的`html`中使用必须使用`kebab­case`(短横线)命名方式。在`html`中不允许使用驼峰!!-->
        <myComponent myMsg='lalalalal'></myComponent>
        <!-- 正确方式 在组件中, 父组件给子组件传递数据必须用短横线。-->
        <my-component my-msg='lalalalal'></my-component>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>

    <script>
        Vue.component('myComponent', {
                props: ['myMsg'],
                //    在template中, 必须使用驼峰命名方式, 若为短横线的命名方式。 则会直接保错。
                template: ' <div>{{abc}}</div>',
                data: function() {
                    return {
                        // 在组件的data中,用this.XXX引用时,只能是驼峰命名方式。若为短横线的命名方式, 则会报错。
                        // abc: this.my - msg
                        // 正确的写法
                        abc: this.myMsg
                    }
                },
            })
        var app = new Vue({
            el: '#app',
            data: {
                a: '100',
                b: '666',
                c: true

            }
        })
    </script>

验证的 type 类型可以是:

String
Number
Boolean
Object
Array
Function
栗子:

 <div id="app" style="border:2px solid green;height:400px;">
        <input type="text" v-model='d'>
        <br>
        <type-component :a='a' :b='b' :c='c' :d='d' :e='e' :f='f' :g='g'></type-component>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>

    <script>
            // 数组验证
        Vue.component('typeComponent', {
            // 约定值的类型
            props: {
                a: String,
                b: [String, Number],
                // 必须是布尔类型 默认值是true typr required default
                c: {
                    type: Boolean,
                    default: true
                },
                d: {
                    type: Number,
                    // 必选项为true 必须传值进行渲染
                    required: true
                },
                // 不向子组件传递 就会取默认值 default
                e: {
                    type: Array,
                    default: function() {
                        return ['666e', 333]
                    }
                },
                //自定义验证函数
                f: {
                    validator: function(value) {
                        return value > 10
                    }
                },
                //验证选项必须为function
                g: {
                    type: Function
                }
            },
            template: ' <div>{{a}}-----{{b}} -----{{c}}----{{d}} ------{{e[0]}}----{{f}} -----{{g}}</div>',
            data: function() {
                return {}
            },
        })
        var app = new Vue({
            el: '#app',
            // 与上面的props中的选项对应 
            data: {
                a: '100a',
                // String或者是Number
                b: '666b',
                // 默认值为true
                c: '',
                // Missing required prop: "d"
                d: 66622,
                // 数组
                e: [],
                //自定义验证函数 value > 10 就是 88 > 10  就会渲染
                f: 88,
                // 验证类型为function
                g: console.log("我是一个函数")

            }
        })
    </script>
上一篇下一篇

猜你喜欢

热点阅读