element-ui 组件分析

582 阅读4分钟

目录结构

  • /element/build 构建目录
  • /element/packages 组件源码
  • /element/src 源码:指令,本地,混入,过渡,

入口文件

位置:/element/src/index.js

  • 导入
import Pagination from '../packages/pagination/index.js'; // 分页组件
import Dialog from '../packages/dialog/index.js'; // 对话框
import Autocomplete from '../packages/autocomplete/index.js'; // 自动完成
import Dropdown from '../packages/dropdown/index.js'; // 下拉
import DropdownMenu from '../packages/dropdown-menu/index.js'; // 下拉菜单
import DropdownItem from '../packages/dropdown-item/index.js'; // 下拉项目
import Menu from '../packages/menu/index.js'; // 菜单
import Submenu from '../packages/submenu/index.js'; // 子菜单
import MenuItem from '../packages/menu-item/index.js'; // 菜单项目
import MenuItemGroup from '../packages/menu-item-group/index.js'; // 项目组
import Input from '../packages/input/index.js'; // 输入框
import InputNumber from '../packages/input-number/index.js'; // 计数器
import Radio from '../packages/radio/index.js'; // 单选
import RadioGroup from '../packages/radio-group/index.js'; // 单选组
import RadioButton from '../packages/radio-button/index.js'; // 单选按钮
import Checkbox from '../packages/checkbox/index.js'; // 多选
import CheckboxButton from '../packages/checkbox-button/index.js'; // 多选按钮
import CheckboxGroup from '../packages/checkbox-group/index.js'; // 多选按钮
import Switch from '../packages/switch/index.js'; // 开关
import Select from '../packages/select/index.js'; // 选择
import Option from '../packages/option/index.js'; // 选项
import OptionGroup from '../packages/option-group/index.js'; // 选项组
import Button from '../packages/button/index.js'; // 按钮
import ButtonGroup from '../packages/button-group/index.js'; // 按钮
import Table from '../packages/table/index.js'; // 表格
import TableColumn from '../packages/table-column/index.js'; //  表格列
import DatePicker from '../packages/date-picker/index.js'; // 日期选择器
import TimeSelect from '../packages/time-select/index.js'; // 时间选择器
import TimePicker from '../packages/time-picker/index.js'; // 时间挑选器
import Popover from '../packages/popover/index.js'; // 弹出框
import Tooltip from '../packages/tooltip/index.js'; // 工具
import MessageBox from '../packages/message-box/index.js'; // 信息盒子
import Breadcrumb from '../packages/breadcrumb/index.js'; // 面包屑组件
import BreadcrumbItem from '../packages/breadcrumb-item/index.js'; // 面包屑组件项目
import Form from '../packages/form/index.js'; // 表单
import FormItem from '../packages/form-item/index.js'; // 表单项
import Tabs from '../packages/tabs/index.js'; // 选项
import TabPane from '../packages/tab-pane/index.js'; // 选项 pane
import Tag from '../packages/tag/index.js'; // 标签
import Tree from '../packages/tree/index.js'; // 树组件
import Alert from '../packages/alert/index.js'; // 提示
import Notification from '../packages/notification/index.js'; // 通知
import Slider from '../packages/slider/index.js'; // 滑动
import Loading from '../packages/loading/index.js'; // 读取
import Icon from '../packages/icon/index.js'; // 图标
import Row from '../packages/row/index.js'; // 行
import Col from '../packages/col/index.js'; // 列
import Upload from '../packages/upload/index.js'; // 上传
import Progress from '../packages/progress/index.js'; // 进度条
import Spinner from '../packages/spinner/index.js'; // 读取中
import Message from '../packages/message/index.js'; // 信息
import Badge from '../packages/badge/index.js'; // 徽章
import Card from '../packages/card/index.js'; // 卡片
import Rate from '../packages/rate/index.js'; // 评分
import Steps from '../packages/steps/index.js'; // 进度
import Step from '../packages/step/index.js'; // 进度
import Carousel from '../packages/carousel/index.js'; // 跑马灯
import Scrollbar from '../packages/scrollbar/index.js'; // 滚动条
import CarouselItem from '../packages/carousel-item/index.js'; // 跑马灯项目
import Collapse from '../packages/collapse/index.js'; // 折叠
import CollapseItem from '../packages/collapse-item/index.js'; // 折叠项目
import Cascader from '../packages/cascader/index.js'; // 级联
import ColorPicker from '../packages/color-picker/index.js'; // 颜色选择器
import Transfer from '../packages/transfer/index.js'; // 穿梭
import Container from '../packages/container/index.js'; // 容器
import Header from '../packages/header/index.js'; // 布局:头
import Aside from '../packages/aside/index.js'; // 布局: 侧边
import Main from '../packages/main/index.js'; // 布局:主体
import Footer from '../packages/footer/index.js'; // 布局:脚
import Timeline from '../packages/timeline/index.js'; // 时间线
import TimelineItem from '../packages/timeline-item/index.js'; // 时间线项目
import Link from '../packages/link/index.js'; // 链接
import Divider from '../packages/divider/index.js'; // 分割线 
import Image from '../packages/image/index.js'; // 图片
import Calendar from '../packages/calendar/index.js'; // 日历
import Backtop from '../packages/backtop/index.js'; // 返回顶部
import InfiniteScroll from '../packages/infinite-scroll/index.js'; // 无限滚动
import PageHeader from '../packages/page-header/index.js'; // 页头
import CascaderPanel from '../packages/cascader-panel/index.js'; // 级联面板
import Avatar from '../packages/avatar/index.js'; // 图像
import Drawer from '../packages/drawer/index.js'; // 抽屉
import Popconfirm from '../packages/popconfirm/index.js'; // 弹出确认
import locale from 'element-ui/src/locale'; // 本地化
import CollapseTransition from 'element-ui/src/transitions/collapse-transition'; // 手风琴过渡
  • 输出
const components = [
  Pagination,
  Dialog,
  Autocomplete,
  Dropdown,
  DropdownMenu,
  DropdownItem,
  Menu,
  Submenu,
  MenuItem,
  MenuItemGroup,
  Input,
  InputNumber,
  Radio,
  RadioGroup,
  RadioButton,
  Checkbox,
  CheckboxButton,
  CheckboxGroup,
  Switch,
  Select,
  Option,
  OptionGroup,
  Button,
  ButtonGroup,
  Table,
  TableColumn,
  DatePicker,
  TimeSelect,
  TimePicker,
  Popover,
  Tooltip,
  Breadcrumb,
  BreadcrumbItem,
  Form,
  FormItem,
  Tabs,
  TabPane,
  Tag,
  Tree,
  Alert,
  Slider,
  Icon,
  Row,
  Col,
  Upload,
  Progress,
  Spinner,
  Badge,
  Card,
  Rate,
  Steps,
  Step,
  Carousel,
  Scrollbar,
  CarouselItem,
  Collapse,
  CollapseItem,
  Cascader,
  ColorPicker,
  Transfer,
  Container,
  Header,
  Aside,
  Main,
  Footer,
  Timeline,
  TimelineItem,
  Link,
  Divider,
  Image,
  Calendar,
  Backtop,
  PageHeader,
  CascaderPanel,
  Avatar,
  Drawer,
  Popconfirm,
  CollapseTransition
];
  • 安装 install 函数
const install = function(Vue, opts = {}) {
  locale.use(opts.locale);
  locale.i18n(opts.i18n);

  components.forEach(component => {
    Vue.component(component.name, component);
  });

  Vue.use(InfiniteScroll);
  Vue.use(Loading.directive);

  Vue.prototype.$ELEMENT = {
    size: opts.size || '',
    zIndex: opts.zIndex || 2000
  };

  Vue.prototype.$loading = Loading.service;
  Vue.prototype.$msgbox = MessageBox;
  Vue.prototype.$alert = MessageBox.alert;
  Vue.prototype.$confirm = MessageBox.confirm;
  Vue.prototype.$prompt = MessageBox.prompt;
  Vue.prototype.$notify = Notification;
  Vue.prototype.$message = Message;

};
  • 输出完整版
export default {
  version: '2.13.0',
  locale: locale.use,
  i18n: locale.i18n,
  install,
  CollapseTransition,
  Loading,
  Pagination,
  Dialog,
  Autocomplete,
  Dropdown,
  DropdownMenu,
  DropdownItem,
  Menu,
  Submenu,
  MenuItem,
  MenuItemGroup,
  Input,
  InputNumber,
  Radio,
  RadioGroup,
  RadioButton,
  Checkbox,
  CheckboxButton,
  CheckboxGroup,
  Switch,
  Select,
  Option,
  OptionGroup,
  Button,
  ButtonGroup,
  Table,
  TableColumn,
  DatePicker,
  TimeSelect,
  TimePicker,
  Popover,
  Tooltip,
  MessageBox,
  Breadcrumb,
  BreadcrumbItem,
  Form,
  FormItem,
  Tabs,
  TabPane,
  Tag,
  Tree,
  Alert,
  Notification,
  Slider,
  Icon,
  Row,
  Col,
  Upload,
  Progress,
  Spinner,
  Message,
  Badge,
  Card,
  Rate,
  Steps,
  Step,
  Carousel,
  Scrollbar,
  CarouselItem,
  Collapse,
  CollapseItem,
  Cascader,
  ColorPicker,
  Transfer,
  Container,
  Header,
  Aside,
  Main,
  Footer,
  Timeline,
  TimelineItem,
  Link,
  Divider,
  Image,
  Calendar,
  Backtop,
  InfiniteScroll,
  PageHeader,
  CascaderPanel,
  Avatar,
  Drawer,
  Popconfirm
};

主要的组件实现的部分放在 packages 目录内:

element 注册全局组件是通过插件的方式来实现的,例如:

  • /element/packages/alert/index.js
import Alert from './src/main';

/* istanbul ignore next */
Alert.install = function(Vue) {
  Vue.component(Alert.name, Alert);
};

export default Alert;
  • /element/packages/alert/src/main.vue
<template>
  <transition name="el-alert-fade">
    <div
      class="el-alert"
      :class="[typeClass, center ? 'is-center' : '', 'is-' + effect]"
      v-show="visible"
      role="alert"
    >
      <i class="el-alert__icon" :class="[ iconClass, isBigIcon ]" v-if="showIcon"></i>
      <div class="el-alert__content">
        <span class="el-alert__title" :class="[ isBoldTitle ]" v-if="title || $slots.title">
          <slot name="title">{{ title }}</slot>
        </span>
        <p class="el-alert__description" v-if="$slots.default && !description"><slot></slot></p>
        <p class="el-alert__description" v-if="description && !$slots.default">{{ description }}</p>
        <i class="el-alert__closebtn" :class="{ 'is-customed': closeText !== '', 'el-icon-close': closeText === '' }" v-show="closable" @click="close()">{{closeText}}</i>
      </div>
    </div>
  </transition>
</template>

<script type="text/babel">
  const TYPE_CLASSES_MAP = {
    'success': 'el-icon-success',
    'warning': 'el-icon-warning',
    'error': 'el-icon-error'
  };
  export default {
    name: 'ElAlert',

    props: {
      title: {
        type: String,
        default: ''
      },
      description: {
        type: String,
        default: ''
      },
      type: {
        type: String,
        default: 'info'
      },
      closable: {
        type: Boolean,
        default: true
      },
      closeText: {
        type: String,
        default: ''
      },
      showIcon: Boolean,
      center: Boolean,
      effect: {
        type: String,
        default: 'light',
        validator: function(value) {
          return ['light', 'dark'].indexOf(value) !== -1;
        }
      }
    },

    data() {
      return {
        visible: true
      };
    },

    methods: {
      close() {
        this.visible = false;
        this.$emit('close');
      }
    },

    computed: {
      typeClass() {
        return `el-alert--${ this.type }`;
      },

      iconClass() {
        return TYPE_CLASSES_MAP[this.type] || 'el-icon-info';
      },

      isBigIcon() {
        return this.description || this.$slots.default ? 'is-big' : '';
      },

      isBoldTitle() {
        return this.description || this.$slots.default ? 'is-bold' : '';
      }
    }
  };
</script>

参考

  • element-ui