组件(component)是vue.js最核心的功能,用来实现局部(特定)功能效果的代码集合(html/css/js/image…..)。
组件是可复用的 Vue 实例, 把一些公共的模块抽取出来,然后写成单独的的工具组件或者页面,在需要的页面中就直接引入即可那么我们可以将其抽出为一个组件进行复用。例如页面头部、侧边、内容区,尾部,上传图片,等多个页面要用到一样的就可以做成组件,提高了代码的复用率。
非单文件组件:一个文件中包含多个组件。(真正开发中几乎不用)
单文件组件:一个文件中只包含1个组件。
1. 模板页面
页面模板
2. JS 模块对象
3. 样式
组件不仅仅是把模板的内容进行复用,更重要的是组件间的通信,通常父组件的模板中包含子组件,父组件要正向地向子组件传递数据以及参数,子组件接收到参数后再根据参数的不同来渲染不同的内容或执行操作。这个正向传递数据的过程就是通过props来实现的。
父组件:vue-cli创建的项目结构中的App.vue为组件之根(父组件)
通过列表页(父组件)与列表项目组件(子组件)为例子,演示props的使用。
父组件示例代码(App.vue):
这是列表页
子组件(列表项目组件)接收父组件传递过来的数据,子组件列表项目代码(ListItem.vue):
- 这是第一条数据
{{message}}
{{msg}}
props中声明的数据与组件data函数返回的数据的主要区别:
- props中声明的数据来自父级,而data中是组件自己的数据,作用域是组件本身;
- 这两种数据都可以在模板(template)及方法(method)中使用;
父组件示例代码(App.vue):
这是列表页
子组件(列表项目组件)接收父组件动态传递过来的数据,子组件列表项目代码(ListItem.vue)不变。
初始状态下,listdata设置的字符串为“原始数据”,如左图,单击改变数据的按钮之后,listdata值改变为“单击按钮之后的数据”,如右图所示。
上一节我们讲到父组件数据变化可以传递给子组件,但是反过来是不成立的,所以props传递数据是单向的。之所以这么设计,就是尽可能将父子组件解耦,避免子组件无意间修改父组件的状态。
业务中经常会遇到两种需要改变props传递过来数据的情况:
父组件传递初始值,子组件将其初始值保存起来,再自己作用域内可以随意使用和更改,这个时候可以在子组件的data中再声明一个数据来引用父组件传递过来的数据。
父组件代码示例:(App.vue)
这是列表页
子组件代码: (ListItem.vue)
- 这是第一条数据
{{receive}}
{{msg}}
子组件中声明了receive,在组件初始化的时候就会获得来自父组件的message,之后就与message无关了,只需要维护receive,这样就避免了直接操作message。
通过前面的学习,我们已经知道父组件与子组件通信通过props传递数据就可以,但是vue组件通信的场景远不止这一种,最容易想到的还有子组件传给父组件。组件之间传值可以用下图表示:
组件通信流程图
Vue.js允许正向传值,也就是父组件传值给子组件。正向传值不需要条件触发,是主动的,逆向传值则是不允许的,需要主动触发,需要主动抛出自定义事件去监听。
语法:
this.$emit('event',val)
$emit为实例方法,用来触发事件监听。其中,参数event代表自定义事件名称,参数val代表通过自定义事件传递的值,注意这里的val为可选参数。
示例代码:(父组件App.vue)
父组件
子组件传递的数据:{{message}}
示例代码:(子组件ListItem.vue)
子组件
emit初始显示状态 单击按钮之后传值父组
兄弟组件之间的传值最容易想到的解决方案是通过共同的父组件进行中转,这里假设一个场景,组件1中的某个数量需要在组件2中同步展示,这个时候就会涉及到兄弟组件之间的传值。通过一个案例来看一下具体代码的实现方式:
示例代码:(App.vue)
父组件
{{message}}
示例代码:(ChildOne.vue)
子组件
示例代码:(ChildTwo.vue)
子组件2
{{count}}
兄弟组件传值之后显示
slot的官方定义是用于组件内容分发,slot还有一个形象的名字“插槽”。简单通俗的解释就是在组件化开发中,虽然组件是一样的,但是在不同的使用场景,组件的某一部分需要有不同的内容显示。
匿名slot从字面理解就是没有名字的插槽,特点是可以放任何内容。
假设场景:设想一个弹出提示框的场景,提示框都包括头部、中间内容和底部内容三部分,头部和底部都是固定不变的,改变的知识中间内容,所以我们在定义组件时可以将中间内容定义为插槽。
示例代码:(子组件popup.vue)
头部区域
如果没有分发内容,则显示默认提示
底部区域
示例代码:(父组件App.vue)
显示弹出框内容
具名slot可以用一个特殊属性name来配置如何分发内容,多个slot可以有不同的名字,具名slot将匹配内容片段中有对应slot特性的元素。
代码示例:(computer.vue子组件)
这儿是CPU插槽
这儿是显卡插槽
这儿是内存插槽
这儿是硬盘插槽
代码示例:(App.vue父组件)
Initel Core i7
GTX980Ti
Kingston 32G
Samsung SSD 1T