【轻松学vue】vue.js基础入门教程(十一)组件

组件

组件(Component)是vue.js最强大的功能之一。
组件可以扩展HTML元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用。
组件在vue脚手架开发中扮演着很重要的角色。

1) 注册全局组件

<div id="app">
    <button-counter></button-counter>
</div>
<script>
    Vue.component('button-counter',{
        data:function(){
           return {
               count:0
           }
        },
        template:"<button v-on:click='count++'>你敲击了{{count}}次</button>"
    });
    var app = new Vue({
        el:"#app"
    })
</script>

注意:
a. 组件的注册应该写在vue实例之前
b. Vue.component()中传入的第一个值是组件名称,第二个值是一个对象,是组件的选项参数
c. data选项必须是一个函数,目的是组件复用时组件数据的相互独立
d. 组件名称不要和原有的html标签名称相同,会产生冲突
e. 组件名称使用“component-name”和“componentName”(小驼峰)时,模板中调用组件都要写为:<component-name></component-name>

2)通过props选项,向子组件传递数据

<div id="app">
    <blog-post title="博客标题"></blog-post>
</div>
<script>
    Vue.component('blog-post',{
        props:["title"],
        template:"<h1>{{title}}</h1>"
    });
    var app = new Vue({
        el:"#app"
    })
</script>

在实际开发当中,data中可能存在多组博文数据,我们可以这样操作

<div id="app">
    <blog-post v-for="blog in blogs" v-bind:key="blog.id" v-bind:title="blog.title"></blog-post>
</div>
<script>
    Vue.component('blog-post',{
        props:["title"],
        template:"<h1>{{title}}</h1>"
    });
    var app = new Vue({
        el:"#app",
        data:{
            blogs:[
                {id:1,title:"标题1"},
                {id:2,title:"标题2"},
                {id:3,title:"标题3"},
                {id:4,title:"标题4"}
            ]
        }
    })
</script>

3)单个根元素
一般一个组件模板中都不止一个包含一个标签,此时我们需要把多个标签包含在一个根元素中,不然只会显示第一个元素内容。

<div id="app">
    <blog-post v-for="blog in blogs" v-bind:key="blog.id" v-bind:title="blog.title" v-bind:content="blog.content"></blog-post>
</div>
<script>
    Vue.component('blog-post',{
        props:["title","content"],
        template:"<div>" +
            "<h1>{{title}}</h1>" +
            "<p>{{content}}</p>" +
            "</div>"
    });
    var app = new Vue({
        el:"#app",
        data:{
            blogs:[
                {id:1,title:"标题1",content:"博文1"},
                {id:2,title:"标题2",content:"博文2"},
                {id:3,title:"标题3",content:"博文3"},
                {id:4,title:"标题4",content:"博文4"}
            ]
        }
    })
</script>

如果博客数据中包含多个字段,我们可以考虑把整个的博客数据传入组件

<div id="app">
    <blog-post v-for="blog in blogs" v-bind:key="blog.id" v-bind:blog="blog"></blog-post>
</div>
<script>
    Vue.component('blog-post',{
        props:["blog"],
        template:"<div>" +
            "<h1>{{blog.title}}</h1>" +
            "<p>{{blog.content}}</p>" +
            "<p>{{blog.time}}</p>" +
            "<p>{{blog.comment}}</p>" +
            "</div>"
    });
    var app = new Vue({
        el:"#app",
        data:{
            blogs:[
                {id:1,title:"标题1",content:"博文1",time:"今天",comment:"评论1"},
                {id:2,title:"标题2",content:"博文2",time:"今天",comment:"评论2"},
                {id:3,title:"标题3",content:"博文3",time:"今天",comment:"评论3"},
                {id:4,title:"标题4",content:"博文4",time:"今天",comment:"评论4"}
            ]
        }
    })
</script>

4)监听子组件事件

<div id="app">
    <div v-bind:style="{fontSize:fontSize+'em'}">
        <blog-post v-for="blog in blogs" v-bind:key="blog.id" v-bind:blog="blog" v-on:enlarge-text="fontSize+=0.1"></blog-post>
    </div>
</div>
<script>
    Vue.component('blog-post',{
        props:["blog"],
        template:"<div>" +
            "<button v-on:click='$emit(\"enlarge-text\")'>放大字体</button>" +
            "<h1>{{blog.title}}</h1>" +
            "<p>{{blog.content}}</p>" +
            "<p>{{blog.time}}</p>" +
            "<p>{{blog.comment}}</p>" +
            "</div>"
    });
    var app = new Vue({
        el:"#app",
        data:{
            blogs:[
                {id:1,title:"标题1",content:"博文1",time:"今天",comment:"评论1"},
                {id:2,title:"标题2",content:"博文2",time:"今天",comment:"评论2"},
                {id:3,title:"标题3",content:"博文3",time:"今天",comment:"评论3"},
                {id:4,title:"标题4",content:"博文4",time:"今天",comment:"评论4"}
            ],
            fontSize:1
        }
    })
</script>

a. 组件调用处绑定自定义事件
b. 组件模板内部绑定正常的vue事件,如:v-on:click,执行组件调用处的自定义事件,以此达到父组件监听子组件事件的目的
v-on:click可以放置一个方法名,在methods方法中使用$emit执行组件调用处的自定义事件

Vue.component('blog-post',{
    props:["blog"],
    template:"<div>" +
        "<button v-on:click='enlargeText'>放大字体</button>" +
        "<h1>{{blog.title}}</h1>" +
        "<p>{{blog.content}}</p>" +
        "<p>{{blog.time}}</p>" +
        "<p>{{blog.comment}}</p>" +
        "</div>",
    methods:{
        enlargeText:function () {
            this.$emit('enlarge-text');
        }
    }
});

5)动态组件
在不同组件之间进行动态切换是非常有用的,如选项卡的操作,可以通过页面标签<component>绑定is属性来实现

<style>
    .tab-button{
        border: 0;
        outline: none;
    }
    .active{
        background: #999;
        color: #ffffff;
    }
    #app div{
        height: 200px;
        border: 1px solid #cccccc;
    }
</style>
<div id="app">
    <button v-for="tab in tabs" v-bind:class="['tab-button',{active:currentTab===tab.menuCode}]" v-on:click="currentTab=tab.menuCode">{{tab.menuName}}</button>
    <component v-bind:is="currentTabComponent"></component>
</div>
<script>
    Vue.component('tab-home',{
        template:'<div>首页组件</div>'
    });
    Vue.component('tab-about',{
        template:'<div>关于我们组件</div>'
    });
    Vue.component('tab-contact',{
        template:'<div>联系我们组件</div>'
    });
    var app = new Vue({
        el:"#app",
        data:{
            currentTab:'home',
            tabs:[
                {
                    menuCode:'home',
                    menuName:'首页'
                },
                {
                    menuCode:'about',
                    menuName:'关于我们'
                },
                {
                    menuCode:'contact',
                    menuName:'联系我们'
                }
            ]
        },
        computed:{
            currentTabComponent:function () {
                return 'tab-'+this.currentTab;
            }
        }
    })
</script>

最终实现:
易动学院
6)在动态组件上使用keep-alive
将动态组件放入到keep-alive标签中,可以使组件中切换状态保持住

<style>
    .tab-button{
        border: 0;
        outline: none;
    }
    .active{
        background: #999;
        color: #ffffff;
    }
    #app div{
        height: 200px;
        border: 1px solid #cccccc;
    }
    .navli{
        list-style: none;
        cursor: pointer;
    }
    .navactive{
        background: #999999;
        color: #ffffff;
    }
    .nav-ul{
        width:20%;
        float: left;
    }
    .navComponent{
        width: 70%;
        float: left;
    }
</style>

<div id="app">
    <button v-for="tab in tabs" v-bind:class="['tab-button',{active:currentTab===tab.menuCode}]" v-on:click="currentTab=tab.menuCode">{{tab.menuName}}</button>
    <keep-alive>
        <component v-bind:is="currentTabComponent"></component>
    </keep-alive>
</div>

<script>
    Vue.component('tab-home',{
        data:function(){
            return {
                currentNav:"nav1",
                navs:[
                    {
                        navCode:"nav1",
                        navName:"导航1"
                    },
                    {
                        navCode:"nav2",
                        navName:"导航2"
                    },
                    {
                        navCode:"nav3",
                        navName:"导航3"
                    }
                ]
            }
        },
        template:'<div>' +
            '<ul class="nav-ul">' +
            '<li v-for="nav in navs" v-bind:class="[\'navli\',{navactive:currentNav===nav.navCode}]" v-on:click="currentNav=nav.navCode">{{nav.navName}}</li>' +
            '</ul>' +
            '<component v-bind:is="currentNavComponent" class="navComponent"></component>'+
        '</div>',
        computed: {
            currentNavComponent: function () {
                return this.currentNav;
            }
        }
    });
    Vue.component('nav1',{
        template:'<div>导航1内容</div>'
    });
    Vue.component('nav2',{
        template:'<div>导航2内容</div>'
    });
    Vue.component('nav3',{
        template:'<div>导航3内容</div>'
    });
    Vue.component('tab-about',{
        template:'<div>关于我们组件</div>'
    });
    Vue.component('tab-contact',{
        template:'<div>联系我们组件</div>'
    });
    var app = new Vue({
        el:"#app",
        data:{
            currentTab:'home',
            tabs:[
                {
                    menuCode:'home',
                    menuName:'首页'
                },
                {
                    menuCode:'about',
                    menuName:'关于我们'
                },
                {
                    menuCode:'contact',
                    menuName:'联系我们'
                }
            ]
        },
        computed:{
            currentTabComponent:function () {
                return 'tab-'+this.currentTab;
            }
        }
    })
</script>

易动学院
7)注册局部组件
全局组件很容易产生不被用到的组件资源浪费,此时会用到局部组件注册(在脚手架环境下体现更明显)

<div id="app">
    <component-a></component-a>
    <component-b></component-b>
</div>
<script>
    var componentA = {
        template:"<h1>局部组件A</h1>"
    }
    var componentB = {
        template:"<h1>局部组件B</h1>"
    }
    var app = new Vue({
        el:"#app",
        components:{
           'component-a':componentA,
           'component-b':componentB
        }
    })
</script>

QQ:732005030
扫码加微信
易动学院

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值