美文网首页
vue基础入门(3)

vue基础入门(3)

作者: 螺钉课堂 | 来源:发表于2019-12-20 10:16 被阅读0次

    3.组件基础

    #3.1.什么是组件?

    #3.1.1.理解组件

    前端组件化开发是目前非常流行的方式,什么是前端组件化开发呢?就是将页面的某一部分独立出来,将这一部分的数据、视图、以及一些控制逻辑封装到一个组件内部,暴露一些开箱即用的函数或者属性供外部组件调用。这种组织代码的开发方式我们称为组件化开发。通俗的说,我们需要把一个页面拆分成若干的小单元,每个小单元就是一个小组件,例如,一个网页,我们可以做如下拆分

    image

    组件开发的好处就是可以复用代码,下面是组件库举例

    image

    点击查看,Element UI

    #3.1.2.vue中的组件

    在vue中,所有的 Vue 组件同时也都是 Vue 的实例,所以可接受相同的选项对象 (除了一些根级特有的选项) 并提供相同的生命周期钩子。Vue组件带有一个名字,在根实例中,组件被定义为元素使用,下面我们来定义一个button计数器组件

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
    <div id="app">
        <button-counter></button-counter>
        <button-counter></button-counter>
        <button-counter></button-counter>
        <button-counter></button-counter>
        <button-counter></button-counter>
    </div>
    <script src="node_modules/vue/dist/vue.js"></script>
    <script>
    
        Vue.component('button-counter',{
            data(){
               return {
                   num: 0
               }
            },
            methods:{
                fn(){
                   this.num++
                }
            },
            template:'<button @click="fn">点击我,自己加1:{{num}}</button>'
        });
        let vm = new Vue({
            el: '#app'
        });
    </script>
    </body>
    </html>
    
    

    注意:组件中的data必须写成函数的形式,如果不写成函数的形式,组件间数据改变会相互影响

    #3.1.3.组件定义实例

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <style>
            body {
                margin: 0;
            }
        </style>
    </head>
    <body>
    <div id="app">
        <header-component></header-component>
        <main-component></main-component>
        <footer-component></footer-component>
    </div>
    <script src="node_modules/vue/dist/vue.js"></script>
    <script>
        //头部组件
        Vue.component('header-component', {
            template: "<div :style='styles'>这里是头部区域</div>",
            computed: {
                styles() {
                    return {
                        width: '100%',
                        height: '100px',
                        backgroundColor: 'black',
                        color: 'white',
                        textAlign: 'center',
                        lineHeight: '100px',
                        fontSize: '30px'
                    }
                }
            }
        });
        Vue.component('main-component', {
            template: `<div :style="styles">
                        <mainleft-component></mainleft-component>
                        <mainright-component></mainright-component>
                        </div>`,
            computed: {
                styles() {
                    return {
                        width: '100%',
                        height: '500px',
                        backgroundColor: 'orangered',
                        paddingTop: '50px'
                    }
                }
            }
        });
        Vue.component('mainleft-component', {
            template: '<div :style="styles"></div>',
            computed: {
                styles() {
                    return {
                        width: '35%',
                        height: '400px',
                        backgroundColor: 'green',
                        float: 'left'
                    }
                }
            }
        });
        Vue.component('mainright-component', {
            template: '<div :style="styles"></div>',
            computed: {
                styles() {
                    return {
                        width: '60%',
                        height: '400px',
                        backgroundColor: 'blue',
                        float: 'right'
                    }
                }
            }
        });
        Vue.component('footer-component', {
            template: '<div :style="styles">这里是底部区域</div>',
            computed: {
                styles() {
                    return {
                        width: '100%',
                        height: '150px',
                        backgroundColor: 'black',
                        color: 'white',
                        textAlign: 'center',
                        lineHeight: '150px',
                        fontSize: '30px'
                    }
                }
            }
        });
        let vm = new Vue({
            el: '#app'
        });
    </script>
    </body>
    </html>
    
    

    #3.1.4.组件的父子关系

    image

    #3.2.父组件向子组件传数据

    组件有自己的作用域,并且相互之间是相互独立的,这样就涉及到组件间的通信问题,在子组件中是不能直接使用父组件中的数据的,要在子组件中使用父组件的数据,可以在子组件注册的时候用props选项来声明一个自定义属性,然后在使用组件的时候,通过这个自定义属性来绑定数据

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
    <div id="app">
        <button @click="showLogin">登录</button>
        <button @click="showRegister">注册</button>
        <template v-if="flagLogin">
            <dialog-component :title="loginTitle"></dialog-component>
        </template>
        <template v-if="flagRegister">
            <dialog-component :title="registerTitle"></dialog-component>
        </template>
    
    </div>
    <script src="node_modules/vue/dist/vue.js"></script>
    <script>
        Vue.component('dialog-component', {
            template: '<div :style="box"><div :style="boxTitle">{{title}}</div></div>',
            computed: {
                box() {
                    return {
                        width: '300px',
                        height: '300px',
                        border: '1px solid black'
                    }
                },
                boxTitle() {
                    return {
                        backgroundColor: 'green',
                        textAlign: 'center',
                        height: '30px',
                        lineHeight: '30px',
                        color: 'white'
                    }
                }
            },
            props:['title']
        });
        let vm = new Vue({
            el: '#app',
            data: {
                flagLogin: false,
                flagRegister: false,
                loginTitle: '登录',
                registerTitle: '注册'
            },
            methods: {
                showLogin() {
                    this.flagLogin = true
                },
                showRegister(){
                    this.flagRegister = true
                }
            }
        });
    </script>
    </body>
    </html>
    
    

    实例2: 新闻列表渲染

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
    <div id="app">
        <news-component :newsdata="newsdata"  :newstype="newstype"></news-component>
    </div>
    <script src="node_modules/vue/dist/vue.js"></script>
    <script>
        Vue.component('news-component', {
            template: `<div :style="wrap">
                            <div :style="wrapTitle">{{newstype}}</div>
                            <div :style="content">
                                <ul v-for="item in newsdata">
                                     <li>{{item.title}}</li>
                                </ul>
                            </div>
                        </div>`,
            computed: {
                wrap() {
                    return {
                        width: '300px',
                        height: '400px',
                        border: '1px solid black',
    
                    }
                },
                wrapTitle() {
                    return {
                        padding: '15px',
                        width: '100%',
                        borderBottom: '1px solid black',
                        boxSizing: 'border-box'
                    }
                },
                content(){
                    return {
                        padding: '10px'
                    }
                }
            },
            props:['newsdata', 'newstype']
        });
        let vm = new Vue({
            el: '#app',
            data: {
                newstype: '国内新闻',
                newsdata: [
                    {'title': '国家药监局:武汉生物百白破疫苗不合格属偶发'},
                    {'title': '下月起 这部分人群的抚恤补助标准将再次提高'},
                    {'title': '85岁老人40万买保健品 身无分文流落街头称继续买'}
                ]
    
            }
        });
    </script>
    </body>
    </html>
    
    

    进一步拆分组件

    Vue.component('news-component', {
            template: `<div :style="wrap">
                            <div :style="wrapTitle">{{newstype}}</div>
                            <div :style="content">
                                <news-list :news="newsdata"></news-list>
                            </div>
                        </div>`,
            computed: {
                wrap() {
                    return {
                        width: '300px',
                        height: '400px',
                        border: '1px solid black',
    
                    }
                },
                wrapTitle() {
                    return {
                        padding: '15px',
                        width: '100%',
                        borderBottom: '1px solid black',
                        boxSizing: 'border-box'
                    }
                },
                content() {
                    return {
                        padding: '10px'
                    }
                }
            },
            props: ['newsdata', 'newstype']
        });
        Vue.component('news-list', {
            template: `<ul>
                            <template v-for="item in news">
                                <li>{{item.title}}</li>
                            </template>
                       </ul>`,
            props:['news']
        });
        let vm = new Vue({
            el: '#app',
            data: {
                newstype: '国内新闻',
                newsdata: [
                    {'title': '国家药监局:武汉生物百白破疫苗不合格属偶发'},
                    {'title': '下月起 这部分人群的抚恤补助标准将再次提高'},
                    {'title': '85岁老人40万买保健品 身无分文流落街头称继续买'}
                ]
    
            }
        });
    
    

    #3.3.子组件向父组件传数据

    #3.3.1.自定义事件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="app"><button-component v-on:myevent="sayhi"></button-component></div>
    <script src="node_modules/vue/dist/vue.js"></script>
    <script>
        Vue.component('button-component', {
            template: `<button @click="$emit('myevent', 'nodeing')">点击</button>`
        });
        new Vue({
            el: '#app',
            methods: {
                sayhi(name){
                    alert('hi,' + name)
                }
            }
        })
    </script>
    </body>
    </html>
    
    

    注意: v-on 事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),因此,在定义事件名字的时候就不要用大写了,例如: myEvent,如果定义的名字为myEvent,在绑定事件的时候,v-on:myEvent会转成 v-on:myevent,这样就不会触发事件了

    #3.3.2.实例

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="app">
        <input type="text" v-model="inputValue">
        <button @click="add">增加</button>
        <ul >
            <list-item
                    v-for="(todo,index) in todos"
                    :key="index"
                    :todo="todo"
                    v-on:del="del_todo"
            ></list-item>
        </ul>
    </div>
    
    <script src="node_modules/vue/dist/vue.js"></script>
    <script>
        Vue.component('list-item', {
            template: `<li @click="$emit('del',todo)">{{todo}}</li>`,
            props: ['todos', 'todo']
        });
    
        new Vue({
            el: '#app',
            data: {
                inputValue: '',
                todos: []
            },
            methods: {
                add(){
                    this.todos.push(this.inputValue);
                    this.inputValue = ''
                },
                del_todo(todo){
                    this.todos = this.todos.filter((item)=>{
                        return item !== todo
                    })
    
                }
    
            }
        })
    </script>
    </body>
    </html>
    

    相关文章

      网友评论

          本文标题:vue基础入门(3)

          本文链接:https://www.haomeiwen.com/subject/dnubnctx.html