We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rubik UI 是一套基于 Vue 2.0 和 Material Design 开发的桌面端、移动端组件库
因为公司内部系统开发的越来越多,而却同事们的要求也越来越高,不仅要好用而且要好看,看惯了 Bootstrap 自然会产生视觉疲劳,因此设计师同学的需求越来越多、后台系统各种体验不统一,因此就自发决定:
因为亲自从零参与并开发了几个后台,发现之前开发的各个业务组件的共性太低,不同后台业务需求差距也比较大,即使开发了通用的业务级组件,后续也跟不上需求的变化速度,因此只专注基础组件,同时也有利于保证组件库的 "轻量级" 特性和后续用于前台移动端的项目。
这一步设计师来主导,制定基础的颜色、字体等规范。
因为决定参照 Material Design 的设计来开发,因此这一步进展的很快很顺利
其中这时候也确认了 LOGO 的设计:一个扁平化的魔方
这是每一个组件库都会做的,我主要参考了 Bootstap 和 materializecss 的组件库,并结合业务中抽象出来的基础组件,最终确认了初期的组件开发任务。
只支持 Vue.js 2.0+
Webpack + ES2015 + stylus 做 js 和 css 构建
Karma + mocha 做单元测试
直接在项目目录下新建一个 example 目录,并结合 Vue-Router 开发成一个单页应用,每个单独 view 作为一个组件的 demo,目录如下:
example
Vue-Router
view
这样就可以在 push master 分支的同时在 GitHub Pages 上作为官网展示了
为了让用户看起来直观,所以文档中就必须存在各种示例,但是用 Markdown 写就无法添加实例。因此只能每个文档都暂时单独当做一个网页来处理。
后续的计划是写一个 Markdown 转 .vue 文件的 loader ,用 webpack 来处理文件转换。
在 Vue 2.0 中的组定义组件上使用 v-on 就能直接监听自定义事件。
v-on
如果要监听原生事件就必须使用修饰符 .native
.native
Vue 组件库 Element 的 Button 组件支持两种事件监听方式
<el-button @click.native="handleClick">Click Me!</el-button> <el-button @click="handleClick">Click Me!</el-button>
我根据尽量保持轻量和不打扰用户的原则,权衡之后决定只让用户自己决定事件的监听:
<r-btn info @click.native="handleClick">Button Click</r-btn>
而且任何自定义的组件都可以用 @click.native="handleClick" 的方式给跟组件添加事件监听
@click.native="handleClick"
组件库中的组件之间肯定会有关联,而且父子组件之间也会通信,所以需要一套事件机制(简单的 pub/sub )来把所有的组件糅合在一起。
因为事件库起到了桥梁的作用,所以我起名叫 util/bridge.js ,其实叫 bus.js 或者 events.js 可能会更清晰点。
util/bridge.js
bus.js
events.js
把 bridge 挂载到 Vue.prototype.$rubik 上,就很容易的通过 this.$rubik.bridge 在每个组件中进行事件的传递了。
bridge
Vue.prototype.$rubik
this.$rubik.bridge
bridge.js 如下:
import EventEmitter from 'events' class Bridge extends EventEmitter { constructor () { super() this.setMaxListeners(500) } sub (event, cb) { const type = typeof event if (type !== 'object' && type !== 'array') { return this.on(event, cb) } event.forEach(i => this.on.apply(this, i)) } unsub (event, cb) { const type = typeof event if (type !== 'object' && type !== 'array') { return this.removeListener(event, cb) } event.forEach(i => this.removeListener.apply(this, i)) } pub () { this.emit.apply(this, arguments) } } export default new Bridge()
当组件被销毁时,注册事件也要执行 unsub,因为有了 Vue 生命周期的 Hook ,所以很简单,只需要写一个 mixin: mixins/event.js
unsub
mixins/event.js
export default { mounted () { this.$rubik.bridge.sub(this.events) }, beforeDestroy () { this.$rubik.bridge.unsub(this.events) } }
因为有时候需要等待 DOM 加载成功后才去执行一些操作,所以在 Vue 的 prototype.$rubik 上添加了 load 方法,方便在各个组件中直接调用:
Vue
prototype.$rubik
load
mounted(){ this.$rubik.load(this.init) }, methods: { init(){ alert('Component ready!') } }
load.js 也很简单
function load (cb) { if (document.readyState === 'complete') { return setTimeout(cb, 0) } if (document.readyState === 'interactive') { return setTimeout(() => load(cb), 150) } document.addEventListener('DOMContentLoaded', cb) } export default load
以 r-input 输入框为例,自定义组件的写法:<r-input v-model="val"></r-input>
r-input
<r-input v-model="val"></r-input>
直接在最外层使用 v-model 指令就可实现对 <input> 标签的双向数据绑定。
<input>
这是因为在组件内部监听了 input 事件
input
<input :value="inputValue" @input="val" />
然后手动触发 'input' 事件
val (e) { this.inputValue = e.target.value this.$emit('input', this.inputValue) }
因为采用12栅格,所以模仿了 Bootstrap 生成栅格的sass写法,改成 stylus 的函数
for size, width in $grid-breakpoints &.{size} flex-grow 1 flex-shrink 1 @media only screen and (min-width: width) for n in (1..$grid-columns) &.{size}{n} flex-basis (n / $grid-columns * 100)% max-width (n / $grid-columns * 100)% &.offset-{size}{n} margin-left (n / $grid-columns * 100)%
根据变量 $grid-breakpoints
$grid-breakpoints := { xs: 0 sm: 576px md: 768px lg: 992px }
只需要17行代码生成四种响应式380行左右的css样式代码
因为一直都是一个人在开发,所以遇到了很多问题都是在社区中寻找到的答案,其中也踩了不少坑,但这也都是自己成长中不可多得的经验,虽然是个个人项目,但还是希望能不断的完善,无论有没有用户在用,至少都是自己的产品,慢慢打磨。
The text was updated successfully, but these errors were encountered:
赞
Sorry, something went wrong.
👍
大兄弟,我想请教下vue-router的滚动行为scrollBehavior方法不起作用是什么原因?
i'm fans of @shouhe
ccforward
No branches or pull requests
Vue.js 组件库 Rubik UI 开发心得总结
Rubik UI 是一套基于 Vue 2.0 和 Material Design 开发的桌面端、移动端组件库
开发目的
因为公司内部系统开发的越来越多,而却同事们的要求也越来越高,不仅要好用而且要好看,看惯了 Bootstrap 自然会产生视觉疲劳,因此设计师同学的需求越来越多、后台系统各种体验不统一,因此就自发决定:
设计、思考阶段
因为亲自从零参与并开发了几个后台,发现之前开发的各个业务组件的共性太低,不同后台业务需求差距也比较大,即使开发了通用的业务级组件,后续也跟不上需求的变化速度,因此只专注基础组件,同时也有利于保证组件库的 "轻量级" 特性和后续用于前台移动端的项目。
开发过程
确认视觉规范
这一步设计师来主导,制定基础的颜色、字体等规范。
因为决定参照 Material Design 的设计来开发,因此这一步进展的很快很顺利
其中这时候也确认了 LOGO 的设计:一个扁平化的魔方
确认基础组件
这是每一个组件库都会做的,我主要参考了 Bootstap 和 materializecss 的组件库,并结合业务中抽象出来的基础组件,最终确认了初期的组件开发任务。
确认技术栈
只支持 Vue.js 2.0+
Webpack + ES2015 + stylus 做 js 和 css 构建
Karma + mocha 做单元测试
组件示例
直接在项目目录下新建一个
example
目录,并结合Vue-Router
开发成一个单页应用,每个单独view
作为一个组件的 demo,目录如下:这样就可以在 push master 分支的同时在 GitHub Pages 上作为官网展示了
文档
为了让用户看起来直观,所以文档中就必须存在各种示例,但是用 Markdown 写就无法添加实例。因此只能每个文档都暂时单独当做一个网页来处理。
后续的计划是写一个 Markdown 转 .vue 文件的 loader ,用 webpack 来处理文件转换。
遇到的问题
自定义组件的原生事件
在 Vue 2.0 中的组定义组件上使用
v-on
就能直接监听自定义事件。如果要监听原生事件就必须使用修饰符
.native
Vue 组件库 Element 的 Button 组件支持两种事件监听方式
我根据尽量保持轻量和不打扰用户的原则,权衡之后决定只让用户自己决定事件的监听:
而且任何自定义的组件都可以用
@click.native="handleClick"
的方式给跟组件添加事件监听事件机制 Event Bus
组件库中的组件之间肯定会有关联,而且父子组件之间也会通信,所以需要一套事件机制(简单的 pub/sub )来把所有的组件糅合在一起。
因为事件库起到了桥梁的作用,所以我起名叫
util/bridge.js
,其实叫bus.js
或者events.js
可能会更清晰点。把
bridge
挂载到Vue.prototype.$rubik
上,就很容易的通过this.$rubik.bridge
在每个组件中进行事件的传递了。bridge.js 如下:
当组件被销毁时,注册事件也要执行
unsub
,因为有了 Vue 生命周期的 Hook ,所以很简单,只需要写一个 mixin:mixins/event.js
onload
因为有时候需要等待 DOM 加载成功后才去执行一些操作,所以在
Vue
的prototype.$rubik
上添加了load
方法,方便在各个组件中直接调用:load.js 也很简单
表单的双向绑定
以
r-input
输入框为例,自定义组件的写法:<r-input v-model="val"></r-input>
直接在最外层使用 v-model 指令就可实现对
<input>
标签的双向数据绑定。这是因为在组件内部监听了
input
事件然后手动触发 'input' 事件
栅格样式
因为采用12栅格,所以模仿了 Bootstrap 生成栅格的sass写法,改成 stylus 的函数
根据变量 $grid-breakpoints
只需要17行代码生成四种响应式380行左右的css样式代码
总结
因为一直都是一个人在开发,所以遇到了很多问题都是在社区中寻找到的答案,其中也踩了不少坑,但这也都是自己成长中不可多得的经验,虽然是个个人项目,但还是希望能不断的完善,无论有没有用户在用,至少都是自己的产品,慢慢打磨。
The text was updated successfully, but these errors were encountered: