Element
Element,是由饿了么UED设计一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库
今天我要分享的就是在使用 Element 的一些心得。
官网: http://element.eleme.io/#/
github: https://github.com/ElemeFE/element
在线讨论社区: https://gitter.im/ElemeFE/element
设计原则
一致性:
- 与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
- 在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
反馈
- 控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;
- 页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。
效率
- 简化流程:设计简洁直观的操作流程
- 清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;
- 帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。
可控
- 用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;
- 结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。
设计目的
项目起源于业务方的需求,随着公司业务发展,需求的增多,对于后台系统的要求也就越来越多,因此在有限的设计资源下支持绝大部分的业务线是很难的,更何况市场上的各类后台产品用户体验也不是很好,因此 element 设计并开发了一套框架,提升后台系统的可用性和一致性。套用此框架,能大幅度提升开发者的开发效率,且便于后期维护。
设计阶段
下面简单说一下Element 设计经历的几个阶段。
了解业务并熟悉公司内各后台产品,寻找业务上的共性问题
设计的目的是为了业务服务。从内部系统开始入手,了解公司内部在使用的各种后台系统,将其组件抽象剥离,寻找共性特征。
专注业务组件设计
总结了公司不同系统不同组件的使用情况后,业务组件入手,因为这部份是由公司特殊需求衍生的解决方案,解决了这些棘手的问题,才能给其他后台产品带来好的设计引导。
寻求开发支持
前端框架,有 Vue、React、Angular 等等。
组件交互完成,进行视觉封装,并搭建主体网站
前期的设计工作主要是由交互设计师进行设计,等确认完所有组件的功能和交互后,开始进行视觉阶段,这中间包括制定颜色、字体等各类规范,也同时进行主体网站的设计。
准备工作
先看看element-ui的主要的工程目录结构。
+-- build 工程脚手架配置文件
|
+-- examples 工程文档目录,也就是element-ui官网
|
+-- lib 执行打包后的文件
|
+-- packages 各个组件所在的目录,也是接下来开发的重点
|
+-- src element-ui工程中各个公用文件,包含了入口文件
|
+-- test 测试用例文件目录
|
+-- types typescript声明文件目录
开发步骤
安装官方推荐使用 npm 安装,这是为了更好地和 webpack 打包工具配合使用。
npm i element-ui -S
CDN
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
安装完成后在 main.js 里引入
import 'element-ui/lib/theme-chalk/index.css';
import ElementUI from 'element-ui';
Vue.use(ElementUI)
也可以只引入需要的组件,以减小项目的体积
布局组件
目前做的项目上的话主要用了 element 的以下几个组件:
-
icon 图标
-
button 按钮
-
input 输入框
-
dialog 对话框
-
Popover 弹出窗
在某些组件使用频率比较高且不适用 element 自身属性情况下,可以全局修改其样式,这样在使用该组件时就不用一个个去修改它的属性。举例来说 全局配置下 element-ui dialog 组件 的 closeOnClickModal 属性 可以直接在 main.js 里去修改element.js引用代码,在引用组件前修改默认属性:
import Vue from 'vue'
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
//全局修改弹窗黑幕点击关闭弹窗默认组件的配置
Element.Dialog.props.closeOnClickModal.default=false;
console.info(Element.Dialog);
Vue.use(Element)
- icon 图标
提供了一套常用的图标集合。
使用方法
直接通过设置类名为 el-icon-iconName 来使用即可。常用的一些图表 element 都有,但有少数的图表没有也没有关系,可以使用引入第三方的 icon 如阿里的 icon库。
- 在阿里icon上创建一个给element扩展的项目
- 添加icon到项目中
在图标库中找到想要的icon后,加入购物车,然后点击右上角的购物车,把icon添加到你的element扩展项目
- 生成icon的在线css链接
4.在Vue项目中,引用在线css链接和新建css样式文件。在Vue项目中创建iconfont.css文件,当然名字自定义
[class^="el-icon-ali"], [class*="el-icon-ali"]
{
font-family:"iconfont" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
5.在 mian.js 里引用后就可以使用了
6.后期更新的话也简单,在阿里icon的项目里,拿到更新后的icon在线css链接,复制到index.html的link标签替换旧的链接即可。
- button 按钮
el-button组件是一个原生button,里面有三部分,分别是loading 加载、icon 图标以及$slots.default 按钮文本这三部分组成
<template>
<button
class="el-button"
:disabled="disabled"
:autofocus="autofocus"
:type="nativeType"
:class="[
type ? 'el-button--' + type : '',
size ? 'el-button--' + size : '',
{
'is-disabled': disabled,
'is-loading': loading,
'is-plain': plain
}
]"
@click="handleClick"
>
<i class="el-icon-loading" v-if="loading"></i>
<i :class="'el-icon-' + icon" v-if="icon && !loading"></i>
<span v-if="$slots.default">
<slot></slot>
</span>
</button>
</template>
button包裹:
最外层是一个button,用来包裹整个组件
disabled:
首先是一个disabled的prop,这是一个Boolean类型的属性,用来控制按钮是否可用。
props: {
disabled: Boolean
}
autofocus:
是一个autofocus的prop,和disabled类似,也是Boolean类型的,用来控制是否自动聚焦。
props: {
autofocus: Boolean
}
type:
type被赋值为nativeType的prop,这是一个String类型的prop,这是用来设置原生button的type的。而另一个type的prop是用来设置相关按钮样式的。
props: {
type: {
type: String,
default: 'default'
},
nativeType: {
type: String,
default: 'button'
}
动态class:
根据type,size,disabled,loading,plain五个属性,分别设置了不同的类,他们都是prop,一次列举如下:
props: {
type: {
type: String,
default: 'default'
},
size: String,
loading: Boolean,
disabled: Boolean,
plain: Boolean,
}
点击事件:
click事件绑定了handleClick回调函数,它会向父组件发一个click事件。
methods: {
handleClick(evt) {
this.$emit('click', evt);
}
}
- input 输入框
输入框enter提交请求
<!-- @keyup.enter.native -->
<el-input @keyup.enter.native="query()"></el-input>
如果不是 el-input 组件,可以直接使用@keyup.enter
- dialog 对话框
做项目的时候遇到一个问题,在一个弹出层的内容区做处理打开另一个弹出层时,第二个弹出层会被遮罩层遮住,后来发现,是element 的dialog嵌套问题,之所以第二次弹出的会被遮住,是因为没有给定 append-to-body。
正常情况下,不建议使用嵌套的 Dialog,如果需要在页面上同时显示多个 Dialog,可以将它们平级放置。对于确实需要嵌套 Dialog 的场景,提供了append-to-body属性。将内层 Dialog 的该属性设置为 true,它就会插入至 body 元素上,从而保证内外层 Dialog 和遮罩层级关系的正确。
- Popover 弹出窗
el-popover的class也是el-popover,比较特别的是,el-popover 生成的 div 不在当前组件之内,甚至不在App.vue组件的 div 内,与 App.vue 组件的 div 平级,所以需要设置全局style。
这里也不能用穿透符 >>> 因为 el-popover 不在当前组件之内
解决方法:如果设置全局样式,则会导致全局的样式污染
所以在全局设置样式时,针对每一个popover-class的名字修改样式即可解决!
其他
/deep/和>>>和::v-deep
在style经常用scoped属性实现组件的私有化时,要改变element-ui某个深层元素(eg:.el-input__inner)或其他深层样式时,需要使用/deep/,如
.conBox /deep/ .el-input__inner{
padding:0 10px;
}
注意,/deep/在vue 3.0会报错
如果/deep/报错,可采用::v-deep。
.conBox ::v-deep .el-input__inner{
padding:0 10px;
}
深度作用选择器 >>>
(注意,只作用于css)
但如果是sass/less的话可能无法识别,这时候需要使用 /deep/和::v-deep 选择器。
想修改element-ui某个深层元素也有其他方式解决;
表格加按钮产生的问题
由于浏览器的处理方式不同,在表格内嵌套文字按钮,当文字过长时,可能出现两种情况:
1 按钮将表格撑开,表格无法对齐。
2 按钮只能显示表格宽度的内容,超过部分被隐藏。
解决办法:加上一个属性show-overflow-tooltip,这样显示的效果就会统一成“当内容过长被隐藏时显示 tooltip”。
鼠标移出事件
在最近做的项目中,一开始有个点击弹出框是手写的div,但是有个问题就是在鼠标移出这个div点击后,这个div不会消失,后来想使用 vue-clickaway 这个插件来隐藏,效果不是太好,最后就用了 element 组件写了一个。后来发现 element源码中有一个很实用的指令叫做clickoutside。
该指令的源码在 src/utils 下的 clickoutside.js。它功能是指令需要接收一个函数,当用户鼠标点击的区域在绑定指令的元素之外时,会触发该函数。使用这个指令很简单,只需要引入这个文件注册指令就好了。
// main.js
import Vue from 'vue'
import clickoutside from 'element-ui/src/utils/clickoutside'
Vue.directive('clickoutside', clickoutside)
使用
html
<div v-show="show" v-clickoutside="handler"><div>
js
export default {
data() {
return {
show: true
}
},
methods: {
handler() {
this.show = false
}
}
}
最后
给大家推荐两个浏览器插件一个是 fehelper 也叫 web前端助手 。是国人开发的一款功能强大的插件,包含多个独立小应用,比如:Json工具、代码美化、代码压缩、二维码、Postman、markdown、网页油猴、便签笔记、信息加密与解密、随机密码生成、Crontab等等!
另一个是 Octotree 可以将GitHub中的项目进行树结构化,非常方便浏览GitHub上的项目。