Analysis of ElementUI source - source code structure articles

ElementUI as the most widely Vue PC end of the current use of the component library, component library architecture Vue many are referring to ElementUI do. As a front-end with a dream (salted fish), this of course need to learn a lot more mature architecture.

Directory structure analysis

First, let's take a look at the directory structure of ElementUI, in general, ElementUI directory structure with vue-cli2little difference:

  • .github: Guide to store contribution as well as issue, PR template, which is a mature open source project must have.
  • build: There is no doubt, to see to know the name of the folder is stored packaging tool configuration file.
  • examples: Examples of components ElementUI storage.
  • packages: source storage component, but also after the main source of objective analysis.
  • src: file store entrance, and various supporting documents.
  • test: storage unit tests, unit tests is also a qualified mature open source projects necessary.
  • types: declaration file storage, enable the introduction of typescript writing project, it is necessary package.jsonto specify typing in the value declared in the field of import documents to take effect.

Having the folder directory, put aside those common .babelrc, .eslintcand other documents, we look at some of the root directory of the file looks rather strange:

  • .travis.yml: Continuous Integration (CI) profiles, its role is to be submitted at the time of the code, execute the corresponding script According to the document, one mature open source projects necessary.
  • CHANGELOG: update log, Tyrant of ElementUI prepared four different language versions of the update log.
  • components.json: profile denoted by the file path components, to facilitate assembly of the file path acquired when webpack package.
  • element_logo.svg: ElementUI icons, use the svg format, the rational use of svg file, you can greatly reduce the image size.
  • FAQ.md:ElementUI developer answers to frequently asked questions.
  • LICENSE: open-source license, ElementUI using the MIT license, use ElementUI secondary development of the developers recommend pay attention to the file.
  • Makefile: contribution mentioned in the guide .github folder, the first component in the development of norms: by make newcreating a component directory structure contains the test code, import documents, document . Which make newis the makecommand of one. makeEngineering command is a compilation tools, and Makefile defines a set of rules to develop file mutation, students often use Linux should not be unfamiliar to Makefile.

Entrance file parsing

Next, we take a look at the entrance of the project file. As previously mentioned, the file entry is src/index.js:

/* Automatically generated by './build/bin/build-entry.js' */

import Pagination from '../packages/pagination/index.js';
// ...
// 引入组件

const components = [
  Pagination,
  Dialog,
  // ...
  // 组件名称
];

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 原型上挂载方法
  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;

};

/* istanbul ignore if */
if (typeof window !== 'undefined' && window.Vue) {
  install(window.Vue);
}

export default {
  version: '2.9.1',
  locale: locale.use,
  i18n: locale.i18n,
  install,
  CollapseTransition,
  // 导出组件
};

Overall, import documents is very easy to understand. Due to the use of Vue.usethe method when calling plugin will automatically call the installfunction, it is only necessary in the installbatch function globally registered various commands, components, global method to mount.

ElementUI entry documents for two very worthy of our study:

  1. During initialization, providing options to configure global properties, which greatly facilitates the use of components, concrete can refer to my previous article.
  2. Automatic generation entry file

Automatic generation entry file

Let's talk about the entrance to generate automated file, before that, there are several students found the entrance to automate file is generated? Ashamed to say, I was writing this article when it found the entrance is automated file generated.

Let's look at the first sentence entrance file:

/* Automatically generated by './build/bin/build-entry.js' */

This tells us that the file is build/bin/build-entry.jsgenerated, so we came to this file:

var Components = require('../../components.json');
var fs = require('fs');
var render = require('json-templater/string');
var uppercamelcase = require('uppercamelcase');
var path = require('path');
var endOfLine = require('os').EOL;

// 输出地址
var OUTPUT_PATH = path.join(__dirname, '../../src/index.js');
// 导入模板
var IMPORT_TEMPLATE = 'import {{name}} from \'../packages/{{package}}/index.js\';';
// 安装组件模板
var INSTALL_COMPONENT_TEMPLATE = '  {{name}}';
// 模板
var MAIN_TEMPLATE = `/* Automatically generated by './build/bin/build-entry.js' */

{{include}}
import locale from 'element-ui/src/locale';
import CollapseTransition from 'element-ui/src/transitions/collapse-transition';

const components = [
{{install}},
  CollapseTransition
];

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;

};

/* istanbul ignore if */
if (typeof window !== 'undefined' && window.Vue) {
  install(window.Vue);
}

export default {
  version: '{{version}}',
  locale: locale.use,
  i18n: locale.i18n,
  install,
  CollapseTransition,
  Loading,
{{list}}
};
`;

delete Components.font;

var ComponentNames = Object.keys(Components);

var includeComponentTemplate = [];
var installTemplate = [];
var listTemplate = [];

// 根据 components.json 文件批量生成模板所需的参数
ComponentNames.forEach(name => {
  var componentName = uppercamelcase(name);

  includeComponentTemplate.push(render(IMPORT_TEMPLATE, {
    name: componentName,
    package: name
  }));

  if (['Loading', 'MessageBox', 'Notification', 'Message', 'InfiniteScroll'].indexOf(componentName) === -1) {
    installTemplate.push(render(INSTALL_COMPONENT_TEMPLATE, {
      name: componentName,
      component: name
    }));
  }

  if (componentName !== 'Loading') listTemplate.push(`  ${componentName}`);
});

// 传入模板参数
var template = render(MAIN_TEMPLATE, {
  include: includeComponentTemplate.join(endOfLine),
  install: installTemplate.join(',' + endOfLine),
  version: process.env.VERSION || require('../../package.json').version,
  list: listTemplate.join(',' + endOfLine)
});

// 生成入口文件
fs.writeFileSync(OUTPUT_PATH, template);
console.log('[build entry] DONE:', OUTPUT_PATH);

build-entry.jsUse the json-templaterafterlife became entrance file. Here, we are not concerned about the json-templaterusage, just thinking of this research document.

It is through the introduction of components.jsonthis we mentioned earlier that static files, batch production of components introduced registration code. What are the benefits of doing so is? We no longer need each add or remove a component, you make several modifications in the entrance documents, import documents generated after the use of automation, we only need to modify one can be.

In addition, it says a ghost story: the previously mentioned components.jsonfile is generated automation. Due to the limited space available here, then we need to delve into it the students themselves.

to sum up

Bad code is different, but the idea is always the same good code, that is, high performance and easy to maintain, with a growing amount of code project, in many cases, easily maintainable code even more than the high-performance but are difficult to maintain code more popular, thought high cohesion low coupling whenever and never become obsolete.

I've always believed that we learn a variety of sources not to blindly imitate their wording, but to learn from their ideas. After all, the wording of the code will soon be replaced by more outstanding writing, but these ideas will be the most valuable asset.

Guess you like

Origin www.cnblogs.com/karthuslorin/p/11202209.html