组件(Component)是Vue.js最强大的功能之一。
组件可以扩展HTML元素,封装可重用的代码。学会了组件的使用,才能更好地将前面学习的知识运行起来,组件的使用使我们的项目更具有解耦性。更加符合MVVM的设计思想。
(1)基础语法
注册一个全局组件语法:
Vue.component(tagName,option) 其中tagName为组件名,options为配置项。
组件是一个可以复用的Vue实例,且带有名字,所以它们和new Vue() 接收相同的选项,例如data,computed,methods等等。需要注意的是,一个组件的data选项必须是一个函数。
(2)全局组件
定义一个名为<button-counter>的全局新组件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue组件</title>
<script type="text/javascript" src="../vue/vue.min.js" ></script>
</head>
<body>
<div id="app">
<div id="counter-event-example">
<button-counter v-on:increment="incrementTotal"></button-counter>
+
<button-counter v-on:increment="incrementTotal"></button-counter>
<p>{{total}}</p>
</div>
</div>
<script>
//注册全局组件
Vue.component('button-counter',{
template:'<button v-on:click="incrementHandler">{{counter}}</button>',
data:function(){
return{
counter:0
}
},
methods:{
incrementHandler:function(){
this.counter+=1;
this.$emit('increment')
}
}
});
new Vue({
el:'#counter-event-example',
data:{
total:0
},
methods:{
incrementTotal:function(){
this.total+=1
}
}
});
</script>
</body>
</html>
(3)局部组件
定义一个名为<button-counter>的局部新组件
创建的局部组件只能在父组件内使用
<div id="app">
<button-counter></button-counter>
</div>
<script>
var Child = {
template: '<h1>自定义组件!</h1>'
}
// 创建根实例
new Vue({
el: '#app',
components: {
// <button-counter> 将只在父模板可用
'button-counter': Child
}
})
</script>
(4)通过Prop向子组件传递数据
prop是子组件用来接收父组件传递过来的数据的一个自定义属性。
父组件的数据需要通过props把数据传给子组件,子组件需要显示的用props选项声明“prop”。
当一个值传递给一个prop特性的时候,它就变成了那个组件实例的一个属性,能够在组件实例中访问这个值,就像是访问data中的值一样。
一个组件默认可以拥有任意数量的prop,任何值都可以传递给任何的prop。
(5)子组件通过自定义事件向父组件发送消息
a:子组件监听一个@click事件,<button @cilck="changeSize">改变字体大小</button>
b:子组件声明方法
methods:{
changeSize(){
//通过$emit()方法传入事件名字,来触发自定义事件,传递父级组件
this.$emit('postChangeSize')
}
}
c:父组件通过子组件传递来的事件名 @postChangeSize='bigChange'
bigChange方法在父级methods中声明
methods:{
bigChange(){
this.fontsize += 1
}
}
组件复杂实例:(先声明子组件,再挂载子组件,最后使用子组件)
<!DOCTYPE html>
<!-- 笔记:
1.在每一个自定义组件中
通过Prop向子组件传递数据时
每一个props属性 如title
都是本组件可以直接调用的
2.在v-bind:title2='title'中
title2是要传给下一层的属性
title是接收本组件的属性(如:props['title'])
3.通过自定义事件向父级组件发送消息
(1)子级组件监听一个@click事件 <button @click="changeSize">改变字体大小</button>
(2)子级组件声明方法
methods:{
changeSize(){
//通过$emit()方法传入事件名字,来触发自定义事件,传给父级组件
this.$emit('postChangeSize')
}
}
(3)父级组件通过子级组件传来的事件名 @postChangeBigSize="bigChange"
bigChange方法在父级methods中声明
methods:{
bigChange(){
this.fontsize += 1
}
}
在style中直接使用
v-bind:style="{fontSize:fontsize+'px'}"
(4)
-->
<html>
<head>
<meta charset="utf-8">
<title>vue组件练习</title>
<script src="../vue/vue.min.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
.main {
width: 100%;
}
body {
color: #fff;
}
.head {
width: 100%;
height: 70px;
background-color: purple;
text-align: center;
font-size: 20px;
line-height: 70px;
}
.wrap {
width: 100%;
height: 600px;
}
.wrap .aside {
width: 30%;
height: 600px;
background-color: green;
float: left;
/*侧边栏浮动*/
}
.wrap .content {
width: 70%;
height: 600px;
background-color: saddlebrown;
float: left;
/*内容区浮动*/
}
</style>
</head>
<body>
<div id="app">
</div>
<script type="text/javascript">
/* 声明局部组件 */
var Vheader = {
template: `<header class="head">
<h3>{{title2}}</h3> <!--模板语法渲染 -->
<span>{{count}}</span>
<button @click='count +=1'>点击</button>
</header>
`,
data() {
return {
count: 0
}
},
props: ['title2'], <!-- props接收title -->
methdos: {
}
};
var Vaside = {
template: `<div class="aside">侧边栏</div>`
};
var Vcontent = {
template: `<div class="content">
<ul>
<li v-for="post in posts" v-bind:key="post.id">
<h2>我的博客ID:{{post.id}}</h2>
<h3>我的博客标题:{{post.title}}</h3>
<p>我的博客内容:{{post.content}}</p>
<hr>
</li>
</ul>
<button @click="changeBigSize">字体大小+1</button>
<button @click="changeSmallSize">字体大小-1</button>
</div>
`,
props: ['posts'],
methods: { //声明方法
changeBigSize() {
//通过$emit()方法传入事件名字,来触发自定义事件
this.$emit('postChangeBigSize', 1, 3)
},
changeSmallSize() {
//通过$emit()方法传入事件名字,来触发自定义事件
this.$emit('postChangeSmallSize')
}
}
};
/* 把组件分别挂载到入口组件中 */
var Vmain = {
template: `
<div class="main" v-bind:style="{fontSize:fontsize+'px'}">
<Vheader v-bind:title2 = 'title'></Vheader>
<div class="wrap">
<Vaside/>
<!-- 绑定自定义属性和自定义事件-->
<Vcontent v-bind:posts="appPosts" @postChangeBigSize="bigChange" @postChangeSmallSize="smallChange"/>
</div>
</div>
`,
data() {
return {
fontsize: 16 //默认字体大小为16
}
},
components: {
Vheader, //等价于Vheader:Vheader 可以简写
Vaside,
Vcontent
},
//自定义的属性
props: ['title', 'appPosts'], //props中的title接收<Vmain v-bind:title = 'text'></Vmain>中的title
methods: {
//字体变大的方法
bigChange(value, item) {
this.fontsize += 1
console.log(this.fontsize)
console.log(value + "--" + item) //value=1 item=3
},
//字体变小的方法
smallChange() {
this.fontsize -= 1
}
}
};
new Vue({
el: "#app",
//第三步:使用子组件
template: `<Vmain v-bind:title = 'text' v-bind:appPosts="posts"></Vmain>`,
//title是属性名 text是数据属性的名字
data: {
//text指的是数据
text: '就这吧',
posts: [{
id: 1,
title: '标题1',
content: '内容1'
},
{
id: 2,
title: '标题2',
content: '内容2'
},
{
id: 3,
title: '标题3',
content: '内容3'
}
]
},
components: {
//第二步:声明变量,挂载子组件 可以表示组件名,value表示组件对象
Vmain: Vmain
}
})
</script>
</body>
</html>