1 案例todoList
在学习组件前先简单做一个案例巩固下前面的基本语法。该案例是通过用户从输入框输入数据点击提交按钮后,将数据以列表的形式展示出来
基本思路: 先定义一个输入框和提交按钮。用v-modal指令将输入框和vue实例数据项进行绑定,当用户输入数据后,数据项data就会接收到此数据。再用v-on指令监听提交按钮的点击事件,当触发了点击事件后,就会执行将data接收的数据存入到list数组中的方法。最后用v-for指令遍历输出。
这里贴出代码
<body>
<div id="root">
<input v-model="inputValue"/>
<button v-on:click="handleSubmit">提交</button>
<ul>
<li v-for="(item, index) of list" :key="index">{{item}}</li>
</ul>
</div>
<script>
new Vue({
el: "#root",
data: {
inputValue: '',
list: []
},
methods: {
handleSubmit: function(){
this.list.push(this.inputValue) //将输入的数据用push方法存入到数组list中
this.inputValue='' //清空输入框中用户输入的数据
}
}
})
</script>
</body>
2 组件基础
2.1 组件是什么
简单来说组件就是可以重复使用的vue实例,含有一个名字。与 new Vue 接收相同的选项,例如 data、computed、watch、methods 等。仅有的例外是el
这样的选项。还有不同的一点是 一个组件的 data 选项必须是一个函数,而不是像new Vue一样是个数据。
data: function () {
return {
count: 0
}
}
2.2 为什么要用组件
- 如果某一个部分需要在多个场景中使用,那么我们可以将其抽出为一个组件进行复用。提高代码的复用率。
- 在实际开发中会有页头、侧边栏、内容区等区域,每个区域又包含了其它的像导航链接、博文之类的区域。可以将其分为各个组件,然后再以父组件嵌套子组件的形式开发,组件化开发易于后期维护和管理
2.3 组件如何用
创建组件的一般语法是 Vue.component(‘组件名’,data,template,…)
通过一个栗子来看下,定义一个名为button-counter的组件,点击按钮的次数会被记录下来。
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">你点了我 {{ count }} 次.</button>'
})
我们再通过 new Vue
所创建的根实例中,把这个组件当成一个自定义元素来使用
<div id="app">
//使用组件button-counter
<button-counter></button-counter>
</div>
<script>
// 定义一个名为 button-counter 的组件
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">你点了我 {{ count }} 次.</button>'
})
//创建根实例
new Vue({ el: '#app' })
</script>
</body>
3 使用组件注意事项
3.1 组件注册的两种方式
1.全局注册
上面举栗子的组件就是全局注册的方式,简单来说就是用 Vue.component
来创建组件。创建好后在任何模板中都可以使用该组件
Vue.component('my-component-name', {
// ... 选项 ...
})
它们在注册之后可以用在任何新创建的 Vue 根实例 (new Vue) 中。并且假如创建了一个component-a组件和一个component-b组件,你可以在component-a组件中使用component-b,也就是说组件在各自内部也可以相互使用。
2.局部注册
通过定义一个javascript对象的形式来定义一个组件
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var Componentc = { /* ... */ }
然后在创建的 Vue 根实例 (new Vue) 中的在 components 选项中声明你想要使用的组件:
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
对于 components 对象中的每个 property 来说,其 property 名就是自定义元素的名字,其 property 值就是这个组件的选项对象。
3.2 父子组件通信
父组件到子组件的通讯主要为:子组件接受使用父组件的数据,这里的数据包括属性和方法(String,Number,Boolean,Object, Array ,Function)。vue提倡单项数据流,因此在通常情况下都是父组件传递数据给子组件使用,子组件触发父组件的事件,并传递给父组件所需要的参数。
由于是入门这里只简单介绍下
(引用来源:https://www.jianshu.com/p/649929d88699)
父组件到子组件通信
- 通过props传递数据
父子通讯中最常见的数据传递方式就是通过props传递数据,就好像方法的传参一样,父组件调用子组件并传入数据,子组件接受到父组件传递的数据进行验证使用。
以案例todoList为例。由于此案例中ul标签下的li标签的作用就是将用户输入的数据展示在页面上,因此我们可以将其抽取为一个组件。
<body>
<div id="root">
<input v-model="inputValue"/>
<button v-on:click="handleSubmit">提交</button>
<ul>
//调用子组件todo-item,并将数组list中的每一项item作为参数传递给子组件的content
<todo-item
v-for="(item, index) of list"
:key="index"
:content="item"
>
</todo-item>
</ul>
</div>
<script>
//全局注册一个子组件todo-item
Vue.component('todo-item',{
props: ['content'],
template: '<li>{{content}}</li>'
})
new Vue({
el: "#root",
data: {
inputValue: '',
list: []
},
methods: {
handleSubmit: function(){
this.list.push(this.inputValue)
this.inputValue=''
}
}
})
</script>
</body>
子组件到父组件通信
- 通过$emit传递数据给父组件
这里还是以todoList案例为栗子,增加删除功能,主要是当用户点击对应的 li 时,就会将其从列表其中删除。
增加删除功能的基本思路:在上面我们已经将展示数据的 li 标签抽取成了一个子组件,再用v-on指令监听是否点击li,当我们点击 li 时,子组件会将此li的下标传递给父组件,并且触发监听事件delete,然后在父组件中通过其传递过来的下标将该数据从list数组中删除掉。
<div id="root">
<input v-model="inputValue"/>
<button v-on:click="handleSubmit">提交</button>
<ul>
<!-- 监听delete事件,触发则执行父组件的handleDelete方法 -->
<todo-item
v-for="(item, index) of list"
:key="index"
:content="item"
:index="index"
v-on:delete="handleDelete"
>
</todo-item>
</ul>
</div>
<script>
Vue.component('todo-item',{
props: ['content', 'index'], //接收父组件传递过来的数据,但是只在页面上展示content
template: '<li v-on:click="handleClick">{{content}}</li>', //监听是否点击li,点击则执行handleClick方法
methods: {
handleClick: function() {
this.$emit('delete', this.index) //向父组件发送消息。发送对应的li下标,并触发自定义的delete事件
}
}
})
new Vue({
el: "#root",
data: {
inputValue: '',
list: []
},
methods: {
handleSubmit: function(){
this.list.push(this.inputValue)
this.inputValue=''
},
handleDelete: function(index){
this.list.splice(index, 1) //执行方法,从子组件传递的下标开始删除数组中的后一位数据
}
}
})
</script>
</body>