VUX 源码:学习其组件通信、样式封装、多端适配的实现。
VUX 作为早期 Vue 生态中专注移动端(尤其是微信小程序)的 UI 组件库,其源码在组件通信、样式封装和多端适配方面有很多值得借鉴的设计思路。虽然 VUX 现在维护较少,但核心实现逻辑对自定义组件库仍有参考价值。以下从这三个维度解析其源码设计:
一、组件通信:灵活的父子 / 跨组件交互设计
VUX 组件间通信主要围绕 “复用性” 和 “低耦合” 设计,常用三种方式:
1. 父子组件:Props + Events 基础通信(最核心)
VUX 几乎所有组件都通过 props 接收父组件参数,通过 $emit 触发事件向父组件传递数据,这是最基础也最常用的方式。示例:XButton 组件
<!-- XButton.vue -->
<template>
<button @click="handleClick">
<slot></slot>
</button>
</template>
<script>
export default {
props: {
disabled: { type: Boolean, default: false }, // 父组件控制禁用状态
loading: { type: Boolean, default: false } // 父组件控制加载状态
},
methods: {
handleClick() {
if (!this.disabled && !this.loading) {
this.$emit('click', '按钮点击事件'); // 向父组件传递事件
}
}
}
}
</script>特点:清晰的单向数据流,父组件通过 props 控制子组件,子组件通过事件反馈,符合 Vue 设计理念。
2. 跨组件通信:EventBus 全局事件总线
对于非父子关系的组件(如 Toast、Dialog 等全局提示组件),VUX 通过 EventBus 实现通信,避免层级嵌套过深导致的传参繁琐。
源码实现:
// src/plugin/event-bus.js import Vue from 'vue' export const bus = new Vue() // 实例化一个空 Vue 实例作为事件总线
使用场景:Toast 组件的全局调用
// src/components/toast/index.js
import { bus } from '../../plugin/event-bus'
// 全局方法 $toast
export function Toast(options) {
bus.$emit('toast', options) // 触发全局事件
}
// 在 Toast 组件内部监听事件
export default {
created() {
bus.$on('toast', (options) => {
this.show = true
this.message = options.message
// ...处理显示逻辑
})
}
}优点:无需引入组件即可通过 this.$vux.toast.show() 调用,简化使用成本。
3. 复杂组件联动:Provide/Inject 依赖注入
对于深层嵌套的组件(如 Form 与 FormItem),VUX 用 provide/inject 传递数据,避免 props 逐层透传。
示例:XForm 与 XFormItem
// XForm.vue(父组件)export default {
provide() {
return {
form: this // 向子组件注入当前 form 实例
}
},
methods: {
validate() { /* 表单验证逻辑 */ }
}}// XFormItem.vue(子组件)export default {
inject: [``'form'``], // 接收父组件注入的 form 实例
methods: {
onBlur() {
this``.form.validate() // 直接调用父组件的验证方法
}
}}适用场景:层级较深的组件树(如表单、导航菜单),减少中间层传参冗余。
二、样式封装:统一风格与可定制性平衡
VUX 的样式设计核心是 “基础变量 + 模块化样式 + 主题定制”,确保组件风格统一且支持个性化配置。
1. 基础变量:SCSS 全局变量统一风格
VUX 定义了一套完整的 SCSS 变量(如颜色、尺寸、圆角),所有组件样式基于这些变量实现,保证风格一致性。
源码位置:src/styles/variable.scss
// 颜色变量 $color-primary: #4fc08d !default; // 主色 $color-danger: #f56c6c !default; // 危险色 // 尺寸变量 $button-height: 44px !default; // 按钮高度 $border-radius: 4px !default; // 圆角尺寸 // 动画变量 $transition-time: 0.3s !default; // 过渡时长
使用方式:组件样式中直接引用变量
// XButton 组件样式
@import '../../styles/variable.scss';
.x-button {
height: $button-height;
border-radius: $border-radius;
background-color: $color-primary;
transition: all $transition-time;
}2. 模块化样式:BEM 命名规范
VUX 采用 BEM(Block-Element-Modifier)命名规范,确保样式类名语义清晰、避免冲突。
示例:XHeader 组件
<!-- 结构 -->
<header class="x-header">
<div class="x-header__left">返回</div>
<div class="x-header__title x-header__title--large">标题</div>
</header>
<!-- 样式 -->
.x-header { /* Block:组件根元素 */ }
.x-header__left { /* Element:子元素 */ }
.x-header__title--large { /* Modifier:变体(大标题) */ }优点:样式层级明确,避免使用复杂嵌套选择器,提高复用性。
3. 主题定制:覆盖变量实现个性化
VUX 支持通过 “覆盖默认变量” 自定义主题,无需修改组件源码。
使用方式:
// 项目中新建 custom-theme.scss $color-primary: #007aff; // 覆盖主色为微信蓝 $button-height: 50px; // 覆盖按钮高度 @import 'vux/src/styles/index.scss'; // 引入 VUX 源码样式,使覆盖生效
原理:SCSS 变量的 !default 标记允许被重新赋值,从而覆盖默认值。
三、多端适配:微信小程序与 H5 的兼容处理
VUX 早期主要针对微信小程序和 H5 适配,其多端兼容思路基于 条件编译 和 平台特性判断。
1. 条件编译:针对不同平台编写差异化代码
VUX 利用 Webpack 或 Vue Loader 的条件编译能力,为不同平台生成对应代码。
示例:平台特定样式
<style scoped>
/* 通用样式 */
.x-button { padding: 0 15px; }
/* 仅微信小程序生效 */
/* #ifdef MP-WEIXIN */
.x-button { font-size: 14px; }
/* #endif */
/* 仅 H5 生效 */
/* #ifdef H5 */
.x-button { font-size: 16px; }
/* #endif */
</style>逻辑层条件编译:
methods: {
handleClick() {
// #ifdef MP-WEIXIN
wx.showToast({ title: '小程序点击' }) // 微信小程序 API
// #endif
// #ifdef H5
alert('H5 点击') // H5 方法
// #endif
}
}2. 平台特性抽象:统一 API 调用
对于平台差异较大的功能(如弹窗、导航),VUX 封装了统一的 API 层,屏蔽底层差异。
示例:导航跳转
// src/utils/navigator.js
export function go(path) {
if (isWeixinMiniProgram()) {
wx.navigateTo({ url: path }) // 小程序导航 API
} else {
window.location.href = path // H5 导航
}
}
// 组件中直接调用统一方法
import { go } from '../../utils/navigator'
go('/page/detail')3. 样式适配:响应式与平台特有样式
响应式:使用
rem或px结合媒体查询适配不同屏幕。小程序特有样式:利用微信小程序的
rpx单位实现自适应(VUX 早期对rpx有兼容处理)。H5 滚动处理:针对 H5 浏览器滚动特性,在组件中添加
overflow: auto等样式兼容。
总结:VUX 源码的可借鉴点
组件通信:根据场景选择 Props/Events、EventBus、Provide/Inject,兼顾简单性和灵活性。
样式封装:通过 SCSS 变量 + BEM 规范保证一致性,用
!default支持主题定制。多端适配:条件编译分离平台代码,抽象统一 API 屏蔽底层差异。
