一、定义组件
首先创建一个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>
效果图: