Vue组件的相关说明

一、定义组件

首先创建一个Vue的实例

Vue.component('el-div',{
    template:"<div>我是自定义组件</div>"
})

然后我们就可以再页面中使用这个组件了

<div id="app">
    <el-div></el-div>
</div>

结果:

在这里插入图片描述

1、组件名的大小写

定义组件名的方式有两种:

使用连字符

Vue.component('my-component-name',{...})

使用驼峰命名

Vue.component('myComponentName',{...})

注意,尽管如此在DOM中只有使用驼峰的命名方式才是有效的

二、组件的复用

一个组件可以进行任意次数的复用

<div id="app">
    <el-div></el-div>
    <el-div></el-div>
    <el-div></el-div>
</div>

三、组件中的data

每个组件中都有一个data属性,其必须是个函数,其目的是为了维护一份被返回对象的独立的拷贝

Vue.component('el-button', {
        data() {
            return {
                count: 0
            }
        },
        methods: {
            add() {
                this.count++
            }
        },
        template: "<button @click='add' >点击次数{{count}}</button>"
    })
   <div id="app">
        <div id="app">
            <el-button></el-button>
            <el-button></el-button>
            <el-button></el-button>
        </div>
    </div>

在这里插入图片描述

四、组件的props

在这个实例中有一个props属性可以让我们向组件中传递数据

Vue.component('el-div',{
    props:['msg']
    template:"<div>{{msg}}</div>"
})
<div id="app">
        <el-div msg='我是自定义组件'></el-div>
</div>

我们也可以使用v-bind来向组件动态的绑定父级作用域中的数据

Vue.component('el-div',{
    props:['msg','id'],
    template:"<div>{{id}}、{{msg}}</div>"
})
var app = new Vue({
    el:"#app",
    data:{
        posts:[
            {id:01,title:"戒指"},
            {id:02,title:"耳饰"},
            {id:03,title:"项链"}
        ]
    }
})

接着使用v-for把我们数据渲染出来

<el-div v-for="post in posts" :msg='post.title' :id="post.id"></el-div>

结果:

在这里插入图片描述

注意:每个组件必须只有一个根元素

当我们组件中包含两个根元素时,会报以下错误 every component must have a single root element (每个组件必须只有一个根元素)

在这里插入图片描述

1、prop的大小写

当在props中使用了驼峰命名法时,在DOM模板中需要使用等价的短横线分割命名来替换

Vue.component('my-blog',{
    props:['blogList'],
    template:"<div>{{blogList}}</div>"
})
<my-blog blog-list="hello"></my-blog>

2、prop类型

当我们希望每个prop都有指定值的类型时,可以使用对象的方式列出prop

props:{
    id:Number,
    title:String,
    callback:Function
}

五、为组件绑定事件

让我们来通过一个案例来进行讲解

<div id="app">
    <ul>
        <el-li v-for="(post,index) in posts" :id="post.id" :post="post.text"></el-li>
    </ul>
</div>
 Vue.component("el-li", {
     props: ['id', 'post'],
     template: `<li>{{id}}、{{post}}<input type="button" value="删除"></li>`
 })
 new Vue({
     el: "#app",
     data: {
         posts: [
             { id: 01, text: "今天天气不错" },
             { id: 02, text: "明天天气会更好" },
             { id: 03, text: "昨天天气有点多云" }
         ]
     }
 })

此时我们已将数据渲染到页面上了,这里我做了一个简单css样式

在这里插入图片描述

接下来我们需要做的就是点击删除按键来删除对应的内容,所以我们就需要在组件中来创建点击事件,并为其注册事件。

但在组件中定义的方法无法访问Vue实例中的data属性,所以我们就需要使用$emit来监听组件中的事件。

此时我们只需要在<el-li>根组件中定义一个自定义事件,再通过$emit来监听事件即可

Vue.component("el-li", {
    props: ['id', 'post'],
    methods: {
        delPost(id) {
            // 使用this.$emit来监听事件,并把id传递给Vue实例中的methods方法
            this.$emit("del-post", id)
        }
    },
    template: `<li>{{id}}、{{post}}<input type="button" value="删除" @click="delPost(id)"></li>`
})
new Vue({
    el: "#app",
    data: {
        posts: [
            { id: 01, text: "今天天气不错" },
            { id: 02, text: "明天天气会更好" },
            { id: 03, text: "昨天天气有点多云" }
        ]
    },
    methods: {
        //自定义事件中需执行的函数
        currentPost(id) {
            //使用findIndex来筛选posts中的id等于传递过来id的数据的索引
             var index = this.posts.findIndex(item => {
                    return item.id == id
                })
                this.posts.splice(index, 1)
            
        }
    }
})
<div id="app">
    <ul>
        <el-li @del-post="currentPost" v-for="(post,index) in posts" :id="post.id" :post="post.text"></el-li>
    </ul>
</div>

到此为止这个小案例就完成了

六、组件局部注册

可以使用普通的js对象来定义组件

var ComponentA = {
   template:"<div>局部组件</div>"
}
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }

然后在components中定义你想要使用的组件

new Vue({
    el:"#app",
    components:{
        "component-a":compontA
    }
})

如果想在局部组件B中使用局部组件A,则

var componentB = {
    components:{
        "component-a":compontA
    }
}

注意:组件命名不能大写但可以使用连字符

七、组件嵌套案例

<!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://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .blogBox {
            margin: 0 auto;
            height: 500px;
            width: 900px;
            display: flex;
            flex-wrap: wrap;
            justify-content: space-between;
            align-items: center;

        }

        .blogList {
            width: 214px;
            height: 228px;
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            align-items: center;
            border: 1px solid #ccc;
            box-sizing: border-box;
            border-radius: 5px;
        }

        .info {
            width: 100%;
            padding: 10px;
            box-sizing: border-box;
            display: flex;
            flex-direction: column;
            justify-content: space-around;
            flex: 1
        }

        .info .title {
            font-size: 16px;
            color: #20232c;
        }

        .info .createTime {
            color: #666;
        }

        .info .author {
            color: #aaa;
            font-size: 14px;
        }

        .blogList .pic {
            width: 212px;
            height: 120px;
            position: relative;
        }

        .pic .live {
            position: absolute;
            top: 5px;
            right: 5px;
            width: 60px;
            height: 20px;
            background: #FF9245;
            color: #fff;
            font-size: 12px;
            text-align: center;
            line-height: 20px;
            border-radius: 5px 5px 0 0;
        }

        .pic img {
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body>
    <div id="app">

        <blog-box :posts="posts"></blog-box>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>

        var blogList = {
            props: ['title', 'author', 'picUrl', 'create_time'],
            template: `
                 <div class="blogList">
                <div class="pic">
                    <img :src="picUrl" alt="">
                    <div class="live">直播预约</div>
                </div>
                <div class="info">
                    <div class="title">{{des()}}</div>
                    <div class="createTime">{{time()}}</div>
                    <div class="author">{{author}}</div>
                </div>
            </div>

            `,
            data() {
                return {

                }
            },
            methods: {
                des() {
                    return this.title.substr(0, 11) + "..."
                },
                time() {
                    return moment(this.create_time).format('YYYY-MM-DD HH:mm:ss')
                }
            }
        }
        var blogBox = {
            props: ['posts'],
            template: ` <div class="blogBox">
                <blog-list v-for="post in posts" :picUrl="post.picUrl" :title="post.title" :author="post.author" :create_time="post.create_time"></blog-list>
                </div>`,
            components: {
                "blog-list": blogList
            }
        }
        var app = new Vue({
            el: "#app",
            data: {
                posts: [
                    { id: 0, title: "黑客入门必去的五个学习网站", author: "程序高小槑", picUrl: "./images/1.png", create_time: 1614937477826 },
                    { id: 1, title: "黑客入门必去的五个学习网站", author: "程序高小槑", picUrl: "./images/2.png", create_time: 1614937577826 },
                    { id: 2, title: "黑客入门必去的五个学习网站", author: "程序高小槑", picUrl: "./images/3.png", create_time: 1614937677826 },
                    { id: 3, title: "黑客入门必去的五个学习网站", author: "程序高小槑", picUrl: "./images/4.png", create_time: 1614937777826 },
                    { id: 4, title: "黑客入门必去的五个学习网站", author: "程序高小槑", picUrl: "./images/5.png", create_time: 1614937877826 },
                    { id: 5, title: "黑客入门必去的五个学习网站", author: "程序高小槑", picUrl: "./images/6.png", create_time: 1614937977826 },
                    { id: 6, title: "黑客入门必去的五个学习网站", author: "程序高小槑", picUrl: "./images/7.png", create_time: 1614931477826 },
                    { id: 7, title: "黑客入门必去的五个学习网站", author: "程序高小槑", picUrl: "./images/8.png", create_time: 1614932477826 },
                ]
            },
            components: {
                "blog-box": blogBox
            }
        })

    </script>
</body>

</html>

效果图:
在这里插入图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值