组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
官方文档:https://cn.vuejs.org/v2/guide/components-registration.html
vue.js 有两大法宝,一个是数据驱动,另一个就是组件化,那么问题来了,什么叫做组件化,为什么要组件化?接下来我就针对这两个问题一一解答,所谓组件化,就是把页面拆分成多个组件,每个组件依赖的 CSS、JS、模板、图片等资源放在一起开发和维护。 因为组件是资源独立的,所以组件在系统内部可复用,组件和组件之间可以嵌套,如果项目比较复杂,可以极大简化代码量,并且对后期的需求变更和维护也更加友好。
Vue.component('my-component', {
// 选项
})
import HelloWorld from './components/HelloWorld'
export default {
components: {
HelloWorld
}
}
区别:全局组件是挂载在 Vue.options.components 下,而局部组件是挂载在 vm.$options.components 下,这也是全局注册的组件能被任意使用的原因。
所谓工欲善其事,必先利其器,在正式开发一个组件之前,我们先要掌握一些必备的知识,这里我只会简单介绍一下,详情参考官网。
组件的名称,必填
<lx-niu/>
<lx-niu></lx-niu/>
name: 'lxNiu'
js 中使用驼峰式命令,HTML 使用kebab-case命名。
组件属性,用于父子组件通信,可通过this.msg访问
<div>{
{
msg}}</div>
props: {
msg: {
type: String,
default: ''
}
}
show: Boolean // 默认false
msg: [String, Boolean] // 多种类型
处理data或者props中的属性,并返回一个新属性
<div>{
{
newMsg}}</div>
computed: {
newMsg() {
return 'hello ' + this.msg
}
},
用render函数描述template
<lx-niu tag='button'>hello world</lx-niu>
<script type="text/javascript">
export default {
name: 'lxNiu',
props: {
tag: {
type: String,
default: 'div'
},
},
// h: createElement
render(h) {
return h(this.tag,
{
class: 'demo'},
this.$slots.default)
}
}
</script>
render 中的 h 其实就是 createElement,它接受三个参数,返回一个 vnode
h 参数解释:
args1: {string | Function | Object} 用于提供DOM的html内容
args2: {Object} 设置DOM样式、属性、绑定事件之类
args3: {array} 用于设置分发的内容
注:vue编译顺序: template–> compile --> render --> vnode --> patch --> DOM
// mixin.js
export default {
data() {
return{
msg: 'hello world'
}
},
methods: {
clickBtn() {
console.log(this.msg)
}
},
}
// index.vue
<button @click="clickBtn">button</button>
import actionMixin from "./mixin.js";
export default {
methods: {
},
mixins: [actionMixin]
}
向子组件传递样式
// 父组件
<lx-niu :bodyStyle='{color: "red"}'/>
// 子组件
<template>
<div :style='bodyStyle'>hello world</div>
</template>
<script>
export default {
name: 'lxNiu',
props: {
bodyStyle: {
},
},
}
</script>
定义子组件的类名
// 父组件
<lx-niu round type='big'/>
// 子组件
<div :class="[
type ? 'lx-niu__' + type : '',
{'is-round': round},
]">控制</div>
//真实DOM
<div class='lx-niu__big is-round'>hello</div>
分发内容,有传入时显示,无传入 DOM 时显示默认,分为无名和具名两种,this.s l o t s . d e f a u l t 默 认 指 向 无 名 插 槽 , 多 个 s l o t 时 用 法 t h i s . slots.default 默认指向无名插槽,多个 slot 时用法 this.slots.default默认指向无名插槽,多个slot时用法this.slots.name
<lx-niu>
<div slot='header'>header</div>
<div class="body" slot='body'>
<input type="text">
</div>
<div slot='footer'>footer</div>
<button class='btn'>button</button>
</lx-niu>
<template>
<div>
<slot name='header'></slot>
<slot name='body'></slot>
<slot name='footer'></slot>
<slot></slot>
</div>
</template>
<script>
export default {
name: 'lxNiu',
mounted() {
this.$slots.header // 包含了slot="foo"的内容
this.$slots.default // 得到一个vnode,没有被包含在具名插槽中的节点,这里是button
}
}
</script>
等等。。。详细请查看官方文档:https://cn.vuejs.org/v2/guide/components-registration.html