- 将一个具备完整功能的项目的一部分分割多处使用
- 加快项目的进度
- 可以进行项目的复用 // 就是活字印刷
组件注册分为:全局注册 和 局部注册
全局组件
全局组件,定义完毕后,就可以直接在项目中任何组件中使用
Vue.component('组件名称', { })
第1个参数是标签名称,第2个参数是一个选项对象。全局组件注册后,任何vue实例都可以用。
!注意:
- data 必须是函数,同时这个函数要求 返回一个对象
=> 会被调用多次,对象是引用类型,会影响到别人,但是通过函数返回的话每次都是一个新的,互相之间没有影响
- 必须是单个根节点包裹
内容可以是模板字符串
太麻烦(不会这么写的)!看看就行
<div id="app">
<!-- 全局组件注册完毕后,直接调用 -->
<hello></hello>
</div>
<script>
// 全局组件注册 -- 一次定义,全局可用
// vue2.x中建议我们组件用小写(首字母大小写不区分)
// 组件是小驼峰名称 userName => 转成小写的形式 => user-name
// data必须是一个函数返回一个对象
// Vue.component('名称',{配置})
let cmp = Vue.component('hello', {
data() {
return {
title: 'hello 全局组件'
}
},
// template (字符串模板)/render(接近于原生的json对象) => vue它是一个虚拟dom(json对象)
// render中的入参默认是h变量,建设更换,更换后它不支持 jsx
// template: `<div>{{ title }}</div>`
render(h) {
return h(
'div',
{ attrs: { name: 'aaa' } },
[
h('h3', {}, this.title),
h('h3', {
on: {
click: () => {
console.log('click22222', this.title)
}
}
}, '22222'),
h('h3', {}, '3333'),
])
}
});
// 虚拟dom
/*
{
// <div id="1" name="aaa"><h3>aaaa</h3></div>
tag:'div',
attrs:{id:1,name:'aaa'},
level:1
children:[
{
tag:'h3'
attrs:{},
text:'aaaa'
}
]
}
*/
// console.log(cmp)
const vm = new Vue({
el: '#app',
data: {
}
})
</script>
局部组件(最常用的)!!!
在哪里使用,就需要引入并注册
也是工程化后,所谓的单文件组件,一个文件就是一个组件,此文件的名称一般为.vue
局部组件,使用它有3步
// 第1步:定义局部组件
// 第2步:在使用到它的组件中引用
// 第3步:在使用它的组件中通过配置来注册一下
定义
<template>
<div>
</div>
</template>
<script>
export default {
name:'组件名称',
data(){
return {
}
}
}
</script>
<style lang="scss" scoped>
</style>
引入
import 名称 from 路径
注册
// 在使用使用的组件中注册
export default {
components:{
名称
}
}
例子:
【组件传值 / 边界处理】
父传子 -- props(单向数据流)!!!
props: 单向数据流,修改数据只能通过父组件来修改,通知子组件更新
- 父组件以属性的形式绑定值到子组件身上
- 子组件通过使用属性props接收(props是单向绑定的(只读属性):当父组件的属性变化时,将传导给子组件,但是反过来不会)
数组的方案是指给自己去使用 // props: ['age'],
封装一个公用组件给别人用,一定要用对象 类型首字母大写
props: {
// age: Number
age: {
type: Number,
// 多个类型 => 联合类型
// type: [Number, String],
// 此属性必须要存在 true必须值, false可以不传
// required: true,
// 默认值,普通类型直接写,引用类型用回调函数
default: 10,
// 自定义验证器
validator: (v) => {
if (v >= 160) {
return false
}
return true
}
},
user: {
type: Object,
/* default: () => {
return { name: '张三' }
} */
// 返回一个对象
default: () => ({ name: '张三' })
},
setagefn: Function
},
利用父组件传入子的【函数】,修改数据
// 父把【方法】传过去,透传
【改数据这步操作永远要在父操作】!!!
子传父 // this.$emit() !!!
给当前此组件添加一个自定义事件
this.$emit('自定义事件的名称',[...参数])
【改数据这步操作永远要在父操作】!!!
<div id="app">
<child :age="age" @onsetage="setage"></child>
</div>
<script>
// 子组件
const Child = {
data() {
return {
title: '我是一个局部组件'
}
},
props: {
age: Number
},
template: `<div @click="incr">{{title}} --- {{age}}</div>`,
methods: {
incr() {
// props单向数据流
// this.$emit('自定义事件的名称',[...参数])
// 给当前此组件添加一个自定义事件
this.$emit('onsetage', 10)
}
}
}
// 根组件
const vm = new Vue({
el: '#app',
data: {
age: 100
},
// key就是在html中使用的标签名称,value组件对象
components: { child: Child },
methods: {
setage(num) {
this.age += num
}
}
})
</script>
事件总线 eventBus
在Vue中通过单独的事件中心来管理组件间的传值。
就是一个对象,一个往对象里写东西,一个读取对象内的东西。
得到一个事件总线对象
const bus = new Vue();
<div id="app">
<h3 @click='parentsend'>new Vue -- {{msg}}</h3>
<app></app>
</div>
<script>
// 得到一个事件总线对象
const bus = new Vue();
const Child1 = {
data() {
return {
msg: ''
}
},
created() {
// console.log('Child1')
// bus.$on('hello', (msg) => console.log('child1 ---' + msg))
bus.$on('hello', msg => this.msg = msg)
},
/* mounted(){
console.log('mounted -- Child1')
}, */
template: `<div>
<h3>我是Child1 -- {{msg}}</h3>
</div>`
}
const Child2 = {
data() {
return {
world: ''
}
},
created() {
// console.log('Child2')
bus.$on('world', world => this.world = world)
},
/* mounted(){
console.log('mounted -- Child2')
}, */
template: `<div>
<h3 @click="sendhello">我是Child2 -- {{world}}</h3>
</div>`,
methods: {
sendhello() {
bus.$emit('hello', 'child2消息')
}
}
}
const App = {
data() {
return {
}
},
/* created(){
console.log('App')
},
mounted(){
console.log('mounted -- App')
}, */
components: {
Child1,
Child2
},
template: `<div>
<h3>我是App</h3>
<child1></child1>
<child2></child2>
</div>`
}
// new Vue
const vm = new Vue({
el: '#app',
data: {
msg: ''
},
components: { App },
created() {
// 订阅
bus.$on('hello', msg => this.msg = msg)
},
beforeDestroy() {
// 关闭订阅
bus.$off('hello')
},
methods: {
parentsend() {
// 发布
bus.$emit('world', 'new Vue发过来了')
}
}
})
</script>