Vue从入门到精通入门篇之组件开发
2018年12月17日
前言
在前面两篇文章已经详细介绍了 Vue
的语法及实例属性,看完之后基本就对 Vue
有个基本的掌握了,接下来这篇咱们就来讲讲 Vue
的组件!内容包括组件开发,组件复用,组件的数据传递,组件间的事件通知,通过插槽进行内容分发,动态组件等!
什么是组件
首先我们先来说说什么是组件:组件简单来说就是可复用的 Vue
实例,每个组件都是一个 Vue
实例!所以他们与 Vue
实例一样,有相同的属性,只有 el
属性是根实例所有特有的!
由于组件是可复用的,通常我们将组件当成是自定义元素来用:
父组件:
<div id="app">
<div>
<Button text="按钮1" @click="clickBtn(1)" />
<Button :text="btnText" @click="clickBtn(2)" />
</div>
</div>
<script>
import Button from './Button';
new Vue({
el: document.getElementById('app'),
data: function() {
return {
btnText: '按钮2'
};
},
components: {
Button,
},
methods: {
clickBtn: function(type) {
console.log(type)
}
},
})
</script>
子组件 - button组件:
<!-- {% raw %} -->
<div>
<button>{{ text }}</Button>
</div>
<!-- {% endraw %} -->
<script>
export default {
data: function() {
return {};
},
props: ['text'],
methods: {
click: function() {
this.$emit('click');
}
},
}
</script>
想上面例子里的 Button
就是一个可复用的组件,当我们开发好组件之后,在父组件内引入并注册之后,就可以将其当成是自定义标签一样重复使用!
组件注册
上面的例子简单的介绍了什么是组件,接下来说说组件的注册!组件的注册有两种类型,分别是局部注册和全局注册;
全局注册:顾名思义,就是注册在全局 Vue
上的,一旦注册之后,在所有 Vue
实例上都可以直接使用:
import Vue from 'vue';
Vue.component('Button', {
props: ['text'],
...
})
局部注册:就是在使用时,在父组件上直接注册,就像一开始介绍什么是组件时候的例子,使用的就是局部注册:
import Button from './Button';
new Vue({
el: document.getElementById('app'),
data: function() {
return {
btnText: '按钮2'
};
},
// 使用局部注册 注册组件
components: {
Button,
},
methods: {
clickBtn: function(type) {
console.log(type)
}
},
})
数据传递及事件通知
在 Vue
里,组件通过 prop
从父组件向下传递给子组件:
Input组件:
<div>
<input v-model="value" />
</div>
<script>
export default {
data: function() {
return {};
},
props: ['value'],
methods: {
click: function() {
this.$emit('click');
}
},
}
</script>
上面的例子中,value
属性就是父组件通过 prop
传递进来的,那么也就是说,在组件中,有些需要的外部数据,都可以使用 prop
传递进来;同样,上面的例子中只是展示了怎么将数据传递近组件,那么如果数组在组件中发生了改变,我们要怎么将发生的变化传递给外面了?
这里就要用到上面说的事件传递了,接着上面例子:
<div>
<input v-model="val" @input="input" />
</div>
<script>
export default {
data: function() {
return {
val: ''
};
},
props: ['value'],
// 监控父组件传入的值 并初始化组件的值
watch: {
value: function(val) {
this.val = val;
}
}
methods: {
// 向外传递input事件
input: function(event) {
this.$emit('input', this.val);
}
},
}
</script>
上面的例子我们可以看到,我们在组件内部input的值的输入变化时,通过 $emit
方法向外进行了传递,并且将最新值当做参数给传递出去了,那么在外面我们就可以使用 @input
事件监听组件内部值的变化了,当然在这种表单元素且通过 input
事件进行传递的,我们可以直接使用 v-model
指令进行双向绑定:
父组件:
<div id="app">
<div>
<!-- 使用prop进行传递 使用input事件监听变化 -->
<Input :value="value1" @input="input" />
<!-- 使用v-model指令进行双向绑定 -->
<Input v-model="value2" />
</div>
</div>
<script>
import Input from './Input';
new Vue({
el: document.getElementById('app'),
data: function() {
return {
value1: '',
value2: '',
};
},
components: {
Input,
},
methods: {
input: function(value) {
this.value1 = value;
}
},
})
上面的例子中,我们使用 prop
将 value1
的值传递近组件,然后使用 input
事件监听变化,并将新值赋值给 value1
,从效果上来说,可以实现和通过 v-model
进行双向绑定的 value2
的效果一模一样!实际上,在 v-model
内部也是通过 prop
绑定变量,通过 input
事件监听变化的!
组件间通信
父子组件通信
:从上面的例子中我们可以看出,父组件与子组件之间通过 prop
将数据自上而下的传递进子组件内部,在由子组件由内向外抛出事件的方式完成父子组件间的数据交互,或者叫通信的!这就是我们常用的父子组件间通信的方式!当然这种方式在父子组件直接进行通信还是比较方便的,但是对于不同层级像隔比较多的组件间通信,再使用这种方式就比较麻烦了!
跨层级组件间通信
:除父子组件之外,我们还会遇到很多不同层级的组件之间也许要进行通信的例子,如果还是用 prop
进行层层传递,再由事件进行层层的往外通知的方式,就得需要找到需要通信间的组件间的共同父组件,然后层层组件间进行传递消息,这种方式无疑是不合适的!这里我们可以借助 vuex
来完成不同组件间的通信,除此之外,我们还可以定义一个 event-bus
插件来完成通信工作;这里具体的使用方式就不在本篇文章中祥述了,在下篇文章我们会详细的介绍使用 vuex
或 event-bus
来进行跨层级组件间的通信!
通过插槽分发内容
在平常我们开发组件中,有时我们不仅需要从父组件传递数据进入组件中,还有可能需要从父组件中传递进来元素文字之类的内容,单纯的通过 prop
进行数据传递有时并不能满足我们的需求,或者说不够灵活;幸好 Vue
中有自定义 <slot>
元素可以进行内容分发,首先我们通过例子看一下 <slot>
的使用方法:
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})
如你所见,只需要在模板中加上 <slot></slot>
就可以了!那么在外边使用时,只需要将需要传递的内容放在组件中间就可以被传递进来:
<div>
<alert-box>
<!-- 这部分内容将被传递进组件插槽中 start -->
<div class="inner">
<h2>这是标题</h2>
<p>这是内容</p>
</div>
<!-- 这部分内容将被传递进组件插槽中 end -->
</alert-box>
</div>
具名插槽
除了上面例子中的用法之外,有时候我们需要多个插槽,分别传递不同的内容进入组件,这时候我们就可以使用带有名称的 slot
来进行传递:
Vue.component('pop-box', {
template: `
<div class="demo-alert-box">
<header>
<slot name="header"></slot>
</header>
<main>
<slot name="main"></slot>
</main>
</div>
`
})
那么在使用插槽时,我们只需要在父组件中,将需要传递的内容使用 slot="name"
属性指定插槽对应的名称即可:
<div>
<pop-box>
<!-- 这部分内容将被传递进组件的header插槽中 -->
<h2 slot="header">这是标题</h2>
<!-- 这部分内容将被传递进组件的main插槽中 -->
<p slot="main">这是内容</p>
</pop-box>
</div>
以上就是插槽及具名插槽的使用方法了,这东西说起来不太容易说清,但是通过上面的代码例子还是很容易就能看出来具体怎么使用的,用起来也并不复杂,而且插槽分发给我们组件带来了极大的灵活性,可以更有效的提高组件的可复用性,大家不防多尝试一下!
动态组件
有时候在我们平常的开发中,会遇到一些组件之间进行切换的情况,比如选项卡等场景,而在 Vue
中提供了 <component>
元素加 is
属性来实现这种动态组件:
<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>
在上述示例中,currentTabComponent 可以包括:
- 已注册组件的名字,或
- 一个组件的选项对象
结尾
本文详细介绍了组件相关的内容,讲到这里组件部分内容也就讲完了,以上内容都是本人结合自己的使用经验总结出来的,除了上面这些以外还有一些细节部分内容本文可能没有讲到,大家可以去官方文档 - 组件基础看更详细的介绍!
转载说明
本文允许全文转载,转载请注明来源: 平凡公子 - vue从入门到精通入门篇之组件开发