业务开发的过程中,经常会进行一些组件化的开发,组件常处理的一般有以下几种
- 全局组件
- 局部组件
- 动态组件
- 递归组件
全局组件
一般很多地方都会用到的一些功能我们一般封装成全局组件去使用,常规的建立一个全局组件的方法是,公共组件放到components 目录文件下使用Vue.component去注册组件,然后在main.js 中去导入这个公共文件夹
// demo | |
import Vue from "vue"; | |
import layoutDemo from "./layoutDemo" | |
Vue.component("tao-layout-demo", layoutDemo); | |
// main.js 中导入components文件夹 | |
然后页面中就可以直接使用这个组件了 | |
<tao-layout-demo><tao-layout-demo | |
组件少的时候这样使用没啥意见,如果声明的组件多了每个都要这样去导入注册代码就有点不简洁了,我们可以使用require.context 去遍历文件自动注册
require.context 遍历
通过require.context 遍历目录下component.vue 或者component.js 的文件,根据组件name 属性作为组件名称,动态注册,当然了如果不规矩文件名为component 可以扫描所有的.vue文件,require.context这个还挺实用的,很多场景会遇到如注册遍历api、全局过滤器等
局部组件
一些只服务当前页面的功能,一般拆分成局部组件去使用,至于什么样的功能需要拆分组件使用,可根据功能结构拆分,比如你的页面整体结构有上中下三层每层中有会有其他的功能交互,这样的建议拆分,如果页面单一也没有业务交互,没必要拆分。
import designPage from "./designPage" | |
export default { | |
components: { | |
designPage | |
} | |
} | |
// 或者 | |
export default { | |
components: { | |
designPage: () => import('./designPage') | |
} | |
} |
动态组件
常见的在列表界面中有增删改查详情的功能操作,不同操作对于不同的组件,这个时候如果普通组件加载的话你要在界面中每个组件都加入还要加if判断要操作的相应的那个组件就比较复杂繁琐了
<template><div> | |
.... 业务 | |
<demo1 v-if="1"/> | |
.... | |
</div></template> |
动态组件就比较爽了,根据你is 指定的名称渲染组件
<component is="page-one"></component>
根据不同的域名显示不同的登录页
递归组件
这个的场景在后台管理软件中最常见,如侧边栏菜单渲染的时候,递归就是根据一个条件自己掉自己,vue中每个页面都可以作为自身的组件调用,组件名称就是name 属性指定的名字,需要注意name 属性一定要加,不然没作用,下面示例渲染侧边菜单
渲染侧边菜单
组件通讯及事件处理
父子组件通讯
-简单一句话就是:父组件v-bing 绑定子组件props接收 this.$emit 触发时间父组件v-on 接收
- 父组件传递
// 传递所有属性 | |
<button v-bind:="value"></button> | |
// 传递指定参数 | |
<button :name="value"></button> | |
// 也可以通过ref 直接赋值 | |
<button ref="demo"></button> | |
this.$refs.demo.name ="xxx" // 前提是子组件中 一定有name 这个字段属性 |
- 子组件接收
子组件通过pops 接收父组件传递过来的值,props 有两种方式数组和对象
export default { | |
props: { | |
name: { | |
type: String , | |
default:"默认值" | |
} | |
} | |
} |
- 子组件传值给父组件
export default { | |
methods: { | |
handleAdd() { | |
this.$emit('click','add') | |
} | |
} | |
} |
其他组件传值处理一般采用事件总线或者vuex,事件总线一般就是说是一个所有组件共用的事件中心,所有组件你要发还是接收数据都平行的通过我去处理
怎样使用事件总线
- 创建eventBus.js 文件
import Vue from 'vue' | |
export const eventBus = new Vue() |
- 把这个js 挂载到原型链上
Vue.prototype.$eventBus = new Vue()
- 使用: 我们一个组件触发了add方法,另一个组件中需要得到这个值//
// 发送 | |
handleAdd(data) { | |
this.$eventBus.$emit('add', data) | |
} | |
// 接收 | |
mounted() { | |
this.$eventBus.$on('add', val => { | |
console.log(val, 'val') | |
}) | |
} |
vuex后面计划单独拿出来写一篇文章,本文不写了
混入(mixins)和继承(extends)
这两个几乎相同,又有点不同,混入可以多个,继承只能一个,都能把公共的一些属性及方法提取出来
mixins: [ initData ] | |
----------------------------- | |
extends: initData |
比如你好几个组件都要用到v-model 绑定参数,可以新建个extends-config.js
import vueJsonEditor from "vue-json-editor"; | |
export default { | |
props: { | |
value: {} | |
}, | |
components: { | |
vueJsonEditor | |
}, | |
computed: { | |
schemaConfig: { | |
get() { | |
return this.value; | |
}, | |
set(val) { | |
this.$emit("input", val); | |
} | |
}, | |
options() { | |
return this.$attrs.options; | |
} | |
}, | |
methods: { | |
event(type, value) { | |
this.$emit(type, value); | |
} | |
} | |
}; |
这样在组件中就可以继承这个文件了,不用单独的定义变量和函数方法了
<template> | |
<div style="width:100%"> | |
<input v-model="schemaConfig" @input="event('input'schemaConfig, /> | |
</div> | |
<script> | |
import settingExtend from '../extends/setting.js' | |
export default { | |
name: 'base-config', | |
extends: settingExtend | |
} | |
</script> |
最后再说下组件生命周期执行顺序吧
- 父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
- 父beforeUpdate->子beforeUpdate->子updated->父updated
- 影响到子组件: - 父beforeUpdate -> 子beforeUpdate->子updated -> 父updted
- 不影响子组件: - 父beforeUpdate -> 父updated
- 父beforeDestroy->子beforeDestroy->子destroyed->父destroyed