vue之组件(三)
一、什么是组件
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。
二、组件用法
组件需要注册后才可以使用,注册有全局注册和局部注册两种方式。
2.1、全局注册后,任何V ue 实例都可以使用。如:
<div id="app1"><my-component></my-component></div>
Vue.component('my-component',{template: '<div>这里是组件的内容</div>'});var app1 = new Vue({ el: '#app1'});
要在父实例中使用这个组件,必须要在实例创建前注册,之后就可以用<my-component></my- component>
的形式来使用组件了
template的DOM结构必须被一个元素包含, 如果直接写成“这里是组件的内容”, 不带<div></ div >
是无法渲染的。(而且最外层只能有一个根的<div>标签)
2.2 、在Vue 实例中,使用component选项可以局部注册组件,注册后的组件只有在该实例作用域下有效。如:
<div id="app2"><my-component1></my-component1></div>
var app2 = new Vue({el: '#app2', components:{ 'my-component1': { template: '<div>这里是局部注册组件的内容</div>' } }});
2.3、data必须是函数
除了template选项外,组件中还可以像Vue实例那样使用其他的选项,比如data 、computed 、methods等。但是在使用data时,和实例稍有区别, data 必须是函数,然后将数据return 出去。
<div id="app"><my-component3></my-component3></div>
Vue.component('my-component3',
{template: '<div>{{message}}</div>', data: function(){ return { message: '组件内容' } }});var app3 = new Vue({ el: '#app3'});
一般return的对象不要引用外部的对象,因为如果return 出的对象引用了外部的一个对象, 那这个对象就是共享的, 任何一方修改都会同步。
所以一般给组件返回一个新的独立的data对象。
三、组件之组件分类
1、由 vue-router 产生的每个页面,它本质上也是一个组件(.vue),主要承载当前页面的 HTML 结构,会包含数据获取、数据整理、数据可视化等常规业务。整个文件相对较大,但一般不会有 props 选项和 自定义事件,因为它作为路由的渲染,不会被复用,因此也不会对外提供接口。在项目开发中,我们写的大部分代码都是这类的组件(页面),协同开发时,每人维护自己的页面,很少有交集。这类组件相对是最好写的,因为主要是还原设计稿,完成需求,不需要太多模块和架构设计上的考虑。
2、不包含业务,独立、具体功能的基础组件,比如日期选择器、模态框等。这类组件作为项目的基础控件,会被大量使用,因此组件的 API 进行过高强度的抽象,可以通过不同配置实现不同的功能。比如笔者开源的 iView,就是包含了 50 多个这样基础组件的 UI 组件库。
每个公司都有自己的组件使用规范或组件库,但要开发和维护一套像 iView 这样的组件库,投入的人力和精力还是很重的,所以出于成本考虑,很多项目都会使用已有的开源组件库。
独立组件的开发难度要高于第一类组件,因为它的侧重点是 API 的设计、兼容性、性能、以及复杂的功能。这类组件对 JavaScript 的编程能力有一定要求,也会包含非常多的技巧,比如在不依赖 Vuex 和 Bus(因为独立组件,无法依赖其它库)的情况下,各组件间的通信,还会涉及很多脑壳疼的逻辑,比如日期选择器要考虑不同时区、国家的日历习惯,支持多种日期格式。
3、业务组件。它不像第二类独立组件只包含某个功能,而是在业务中被多个页面复用的,它与独立组件的区别是,业务组件只在当前项目中会用到,不具有通用性,而且会包含一些业务,比如数据请求;而独立组件不含业务,在任何项目中都可以使用,功能单一,比如一个具有数据校验功能的输入框。业务组件更像是介于第一类和第二类之间,在开发上也与独立组件类似,但寄托于项目,你可以使用项目中的技术栈,比如 Vuex、axios、echarts 等,所以它的开发难度相对独立组件要容易点,但也有必要考虑组件的可维护性和复用性。
全局组件:
Vue.component("组件名称",{
template:`
<div>我是全局组件</div>
`
})
局部组件:
componnets:{
"组件名称":{
tempalte:`
<div>我是局部组件</div>
`
}
}
四、组件之组件通信
###4.1、父子组件通信:props
props:[]
or
props:{
}
###4.2、子父组件通信: $emit
$emit 自定义事件
参数:
0:自定义事件名称
1:传输的值
###4.3、兄弟组件通信:bus
var bus=new Vue()
发送:
bus.$emit("自定义事件名称",value)
接收:
bus.$on("自定义事件",callback)
4.4、跨级组件传值:provide inject
4.5、vuex通信
五、组件之插槽
插槽分类:
匿名插槽 具名插槽 插槽作用域
(1)插槽内容
Vue 实现了一套内容分发的 API,这套 API 的设计灵感源自 [Web Components 规范草案],将 <slot>
元素作为承载分发内容的出口。
在父组件里可以写成:
<div class="area_slot">
<nav-link :address="url">
</nav-link>
</div>
Vue.component('nav-link',{
props:['address'],
template:`<a :href="address" class="nav-link">
<span class="slot_span"></span>
<slot></slot>
</a>`
});
new Vue({
el:'.area_slot',
data:{
url:'http://www.baidu.com'
}
})