Vue组件

组件基础

组件是可复用的Vue实例,并且带有名字。通过Vue.component创建组件

可以通过new Vue创建的Vue根实例中,把组件作为自定义元素使用。

<div id="app">
    <button-counter></button-counter>
</div>

<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    Vue.component('button-counter',{
        data: function(){
            return {count: 0}
        },
        template: '<button v-on:click="count++">{{ count }}</button>'
    })

    var vm = new Vue({
        el: '#app'
    })
</script>

创建一个叫做的组件,定一个函数,返回count为0的值,然后通过template模板返回html元素。

因为组件是可以复用的Vue实例,所以可以与new Vue创建的实例接受相同的选项

例如datacomputedwatchmethods

以及生命周期钩子,唯一的例外就是el,这是根实例特有的选项。

复用(可以多次使用)
<div id="app">
    <button-counter></button-counter>
    <button-counter></button-counter>
    <button-counter></button-counter>
</div>
关于data

data必须是一个函数,而不是一个对象

//当data是一个对象时
data:{
	count: 0
}
//函数
data: function() {
	return {
		count: 0
	}
}

这样的作用是,防止复用多个组件时,其中的变量会互相影响

组件的注册

组件的注册类型分为全局注册和局部注册,所有的全局注册都是通过Vue.component创建的

通过Prop子组件传递数据

prop就是在组件上面自定义的属性

prop注册时是attribute,当一个值传递给prop attribute时,它就会变成组件的一个property

attribute和property的区别

attribute:
是html标签上面的某一个属性,例如id,class,value等以及一系列的自定义属性
它的值,只会返回为字符串
property:
是js获取的一个DOM对象上面的属性值

例如
<input type="text" id='test' value="foo">
其中attribute就是id,value
打印value
//"foo"
当在input这个输入框输入bar时
value就变成了bar,打印property,会返回bar。打印attribute依旧还是foo并没有改变
<div id="app">
    <blog-post title="My Vue"></blog-post>
<blog-post title="My Web"></blog-post>
</div>

<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    Vue.component('blog-post',{
        props: ['title'],
        template: '<h3>{{ title }}</h3>'
    });
    var vm = new Vue({
        el: '#app'
    })
</script>
动态传递prop
<div id="app">
    <blog-post v-for="post in posts" v-bind:keys="post.id" v-bind:title="post.title"></blog-post>
</div>

<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    Vue.component('blog-post',{
        props: ['title','keys'],
        template: '<h3>{{ keys }} {{ title }}</h3>'
    });
    var vm = new Vue({
        el: '#app',
        data: {
            posts: [
                {id:1,title:'Foo'},
                {id:2,title:'Bar'},
                {id:3,title:'Dav'}
            ]
        }
    })
</script>
单个根元素

当属性开始变多,不止一个title时

同时需要多条html语句才能显示时

需要一个父元素进行一个包裹

一个组件只能拥有一个根元素()

<template id="blogpost">
    <div>
        <h3>{{ post.id }} {{ post.title }}</h3>
        <div v-html="post.content"></div>
    </div>
</template>
<div id="app">
    <blog-post v-for="post in posts" v-bind:post="post"></blog-post>
</div>

<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    Vue.component('blog-post',{
        props: ['post'],
        template: '#blogpost'
    });
    var vm = new Vue({
        el: '#app',
        data: {
            posts: [
                {id:1,title:'Foo',content:'<h3>J.H</h3>'},
                {id:2,title:'Bar',content:'<h3>J.H</h3>'},
                {id:3,title:'Dav',content:'<h3>J.H</h3>'}
            ]
        }
    })
</script>
监听子组件事件

通过一个例子,实现监听子组件事件,功能就是放大字号。

在父组件也就是根实例中添加一个postFontSize数据,用来支持放大字号功能。

首先在template模板中,添加一个按钮,但是这个按钮不能做任何事。

所以要使用v-on监听子组件的事件,在bost-post中添加一个v-on监听事件,然后再子组件通过调用内建的$emit方法传入事件名称来触发一个事件。

<template id="blogpost">
    <div >
        <h3>{{ post.id }}.{{ post.title }}</h3>
        <button v-on:click="$emit('enlarge-text')">Elarge text</button>
        <p v-html="post.content"></p>
    </div>
</template>

<div id="app">
    <div :style="{ fontSize: postFontSize+'em' }">
        <blog-post v-for="post in posts" v-bind:post="post" v-on:enlarge-text="postFontSize += 0.1"></blog-post>
    </div>
</div>

<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    Vue.component('blog-post',{
        props: ['post'],
        template: '#blogpost'
    });
    var vm = new Vue({
        el: '#app',
        data: {
            posts: [
                {id:1,title:'Foo',content:'<h5>J.H</h5>'},
                {id:2,title:'Bar',content:'<h5>J.H</h5>'},
                {id:3,title:'Dav',content:'<h5>J.H</h5>'}
            ],
            postFontSize: 1
        }
    })
</script>
使用事件抛出一个值

可以使用一个事件抛出一特定的值,使用$emit的第二参数来提供这个值

<template id="blogpost">
    <div >
        <h3>{{ post.id }}.{{ post.title }}</h3>
        <button v-on:click="$emit('enlarge-text',0.1)">Elarge text</button>
        <p v-html="post.content"></p>
    </div>
</template>

当父组件监听到这个事件的时候,通过$event访问这个值

<blog-post v-for="post in posts" v-bind:post="post" v-on:enlarge-text="postFontSize += $event"></blog-post>

可以通过函数处理事件

        methods: {
            onEnlargeText: function(enlargeAmount) {
                this.postFontSize += enlargeAmount
            }
        }
 v-on:enlarge-text="onEnlargeText

这时对事件的处理就是封装一个函数,提供一个enlargeAmount的参数传入,这个参数的值,依旧是靠$event访问。

在组件上使用v-model

自定义事件可以用于创建支持v-model的自定义输入组件

<input v-model="searchtext">

相当于

<input
	v-bind:value="searchtext"
	v-on:input="searctext=$event.target.value"
>

value(attrbute)绑定到一个叫value的prop上

input事件被触发时,将新的值通过自定义的input事件抛出

所以组件的写法

Vue.component('custom-input'),{
    props: ['value'],
    template:'
    	<input
	v-bind:value="searchtext"
	v-on:input="$emit('input',$event.target.value)"
	>
    '
})

这时才可以在custom-input上运行v-model

<custom-input v-model="searchtext"></custom-input>