Due to the needs of the interview, first of several sources of element source learning blog. Vue source code will also continue to update.
OK, now we're starting to learn element--'s most popular Vue UI framework. Package.json
I think that to see a front-end project, you must first look at Package.json this file. Compile Entry
Let's look at the compiled portal.
"Scripts": {
# Install dependent
"bootstrap": "yarn | | NPM i ",
# Build file
" Build:file ":" Node Build/bin/iconinit.js & node Build/bin/build-entry.js & node build/ Bin/i18n.js & Node Build/bin/version.js ",
# Build Style
" Build:theme ":" Node Build/bin/gen-cssfile && Gulp Build--gulpfile packages/theme-chalk/gulpfile.js && cp-cli packages/theme-chalk/lib lib/theme-chalk ",
# Build Tool
"Build:utils": "cross-env babel_env=utils BABEL src--out-dir lib--ignore src/index.js",
# Build umd< c12/> "BUILD:UMD": "Node Build/bin/build-locale.js"
}
Here we look at the source of the point of view, first understand the build file command. In fact, node executes a few JS scripts. Let's take a closer look at the script files Iconinit, Build-entry, i18n, version.
Build/bin/build-all.js
' use strict ';
Const COMPONENTS = require ('.. /.. /components.json ');
Const EXECSYNC = require (' child_process '). Execsync;
Const EXISTSSYNC = require (' FS '). Existssync;
Const PATH = require (' path ');
Let componentpaths = [];
Delete Components.index;
Delete Components.font;
Traverses the components key, finds the corresponding component path, and saves the path to the componentpaths array
object.keys (components). ForEach (Key => {
Const FILEPATH = Path.join (__dirname, ' ... /.. /packages/${key}/cooking.conf.js ');
if (Existssync (FilePath)) {
Componentpaths.push (' packages/${key}/cooking.conf.js ');
}
});
PATHA,PATHB,PATHC
Const paths = Componentpaths.join (', ');
Stitching the shell command and invoking the Execsync method execution.
Const CLI = path.join (' Node_modules ', '. bin ', ' cooking ') + ' build-c ${paths}-P ';
Execsync (CLI, {
stdio: ' Inherit '
});
The above method is mainly to get all the component names, and then stitching the shell command, execute the shell command to build.
Build/bin/iconinit.js
' use strict ';
var postcss = require (' postcss ');
var fs = require (' FS ');
var path = require (' path ');
var fontfile = Fs.readfilesync (Path.resolve (__dirname, ' ...) /.. /packages/theme-chalk/src/icon.scss '), ' UTF8 ');
var nodes = Postcss.parse (fontfile). nodes;
var classlist = [];
Traversal matches the regular, the conformance is passed into the array
Nodes.foreach (node) => {
var selector = Node.selector | | '';
var reg = new RegExp (/\.el-icon-([^:]+): before/); Regular:. el-icon-(multiple non: characters): Before
var arr = Selector.match (reg);
if (arr && arr[1]) {
classlist.push (arr[1]);
}
);
Export Icon.json file
fs.writefile (path.resolve (__dirname, '.. /.. /examples/icon.json '), Json.stringify (classlist));
The above method icon.scss the final export of Icon.json files by parsing the file, which holds various icons.
//build/bin/i18n.js ' use strict ';
var fs = require (' FS ');
var path = require (' path '); Get page.json var langconfig = require ('.. /..
/examples/i18n/page.json '); Langconfig.foreach (lang => {try {//Get file Information Fs.statsync (path.resolve) (__dirname, '.. /..
/examples/pages/${Lang.lang} ')); catch (E) {//Create folder Fs.mkdirsync (Path.resolve (__dirname, ' ...) /..
/examples/pages/${Lang.lang} ')); //Traversal Write file Object.keys (lang.pages). ForEach (page => {var templatepath = path.resolve (__dirname, '.. /..
/examples/pages/template/${page}.tpl '); var OutputPath = path.resolve (__dirname, '. /..
/examples/pages/${Lang.lang}/${page}.vue ');
var content = Fs.readfilesync (TemplatePath, ' UTF8 ');
var pairs = Lang.pages[page]; Object.keys (Pairs). ForEach (key => {content = Content.replace (new RegExp (' <%=\\s*${key}\\s*> ', ' G '), pair
S[key]);
});
Fs.writefilesync (OutputPath, content);
}); });
The above code is an internationalized process that will eventually generate content in different languages in the examples/pages/directory. Internationalization specific content please refer to internationalization.
Build/bin/version.js
var fs = require (' FS ');
var path = require (' path ');
var version = Process.env.VERSION | | Require ('.. /.. /package.json '). Version;
var content = {' 1.4.13 ': ' 1.4 ', ' 2.0.11 ': ' 2.0 ', ' 2.1.0 ': ' 2.1 '};
if (!content[version]) content[version] = ' 2.2 ';
Fs.writefilesync (Path.resolve) (__dirname, ' ... /.. /examples/versions.json '), json.stringify (content));
Get version, which defines a content, and if the current version is not in the content, add a copy of the data. Since my version of the study is 2.2.1, the resulting results are:
{"1.4.13": "1.4", "2.0.11": "2.0", "2.1.0": "2.1", "2.2.1": "2.2"}
There are several versions of the reason, see descend net can find clues, should be several important stable version.
Look at the Build-entry.js file.
build/bin/build-entry.js var components = require ('.. /.. /components.json '); Component data var fs = require (' FS ');
Node file system var render = require (' json-templater/string '); var uppercamelcase = require (' uppercamelcase '); Hump Case Write var path = require (' path '); Node path system var EndOfLine = require (' OS ').
EOL; Export path var Output_path = Path.join (__dirname, ' ... /..
/src/index.js '); Import TEMPLATE, install component TEMPLATE, main TEMPLATE 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 ' Elemen
T-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.map (Component => {vue.component (component.name, ComponenT);
});
Vue.use (loading.directive);
Const ELEMENT = {}; Element.size = Opts.size | |
'';
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;
Vue.prototype. $ELEMENT = ELEMENT;
}; /* Istanbul Ignore if */if (typeof window!== ' undefined ' && window. Vue) {Install (window).
Vue); } module.exports = {version: ' {{version}} ', Locale:locale.use, i18n:locale.i18n, install, collapsetransition
, Loading, {{list}}};
Module.exports.default = Module.exports;
`;
Delete Components.font;
Component name var componentnames = Object.keys (components);
var includecomponenttemplate = [];
var installtemplate = [];
var listtemplate = []; Traverse Component Name resolution template Componentnames.foreach (name => {var componentname = uppercamelcase (name);//HumpName Includecomponenttemplate.push (Render (Import_template, {name:componentname, package:name})); if ([' Loading ', ' MessageBox ', ' Notification ', ' message '].indexof (componentname) = = 1) {Installtemplate.push (
Install_component_template, {name:componentname, component:name}));
} if (componentname!== ' Loading ') Listtemplate.push (' ${componentname} ');
}); Main template var template = render (Main_template, {include:includeComponentTemplate.join (endofline), Install:insta Lltemplate.join (', ' + endofline), Version:process.env.VERSION | | Require ('.. /..
/package.json '). Version, List:listTemplate.join (', ' + EndOfLine)});
Export File Fs.writefilesync (Output_path, template); Console.log (' [Build entry] Done: ', output_path);
In the above code, you first define three template, and then use the Render method to render the template. Finally, a primary template is generated to be exported as a file. The second parameter in the render function is the data for {{name}} in template.
This render method comes from the Json-templater library, which compiles strings into JS code. Dependency Relationships
See what the element is depend. The following is a comment on the dependencies of the element.
"Dependencies": {///Asynchronous Validator "Async-validator": "~1.8.1",//Vue and JSX syntax translators for merging parameters.
"Babel-helper-vue-jsx-merge-props": "^2.0.0",//Deep merge "Deepmerge": "^1.2.0",//mouse wheel standardization between multiple browsers. "Normalize-wheel": "^1.0.1",//method of Throttle/debounce. Https://www.npmjs.com/package/throttle-debounce "throttle-debounce": "^1.0.1"}, "Peerdependencies": {//Vue core
Heart Source "Vue": "^2.5.2"}, "Devdependencies": {//A hosted Full-text, digital and faceted search engine that can provide real-time results at the first keystroke. "Algoliasearch": "^3.24.5",//Babel "BABEL-CLI": "^6.14.0", "Babel-core": "^6.14.0", "Babel-loader": "^6." 2.5 "," Babel-plugin-add-module-exports ":" ^0.2.1 "," Babel-plugin-module-resolver ":" ^2.2.0 "," Babel-plugin-syn
Tax-jsx ":" ^6.8.0 "," BABEL-PLUGIN-TRANSFORM-VUE-JSX ":" ^3.3.0 "," babel-preset-es2015 ":" ^6.14.0 ",//Chai Assertion Library
"Chai": "^3.5.0",//for the server specifically designed for the core of jquery's fast, flexible, lean implementation. "Cheerio": "^0.18.0",//Node FS tool "Chokidar": "^1.7.0",//Cooking Front-End constructionBuild Tool "Cooking": "^1.5.4", "Cooking-lint": "0.1.3",//Inheritance vue2 configuration item Cooking plugin "cooking-vue2": "^0.3.3",// Replication Webpack Plugin "Copy-webpack-plugin": "^4.1.1",//Code test Coverage "Coveralls": "^2.11.14",//Cross-platform support UNIX command "CP-CL
I ":" ^1.0.2 ",//Run scripts to set up and use environment variables on the platform. "Cross-env": "^3.1.3",//CSS Loader "Css-loader": "^0.28.7",//ES6 Promise Support "es6-promise": "^4.0.5",/ /Eslint Grammar Detection "eslint": "4.14.0", "Eslint-config-elemefe": "0.1.1", "Eslint-loader": "^1.9.0", "Eslint-plug In-html ":" ^4.0.1 "," Eslint-plugin-json ":" ^1.2.0 "," Extract-text-webpack-plugin ":" ^3.0.1 ",//file loading and saving" F " Ile-loader ":" ^1.1.5 "," File-save ":" ^0.2.0 ",//Publish file to GitHub gh-pages branch" gh-pages ":" ^0.11.0 ",//Gulp dozen
Package "Gulp": "^3.9.1", "Gulp-autoprefixer": "^4.0.0", "Gulp-cssmin": "^0.1.7", "Gulp-postcss": "^6.1.1", "Gulp-sass": "^3.1.0",//JS Highlight "Highlight.js": "^9.3.0",//HTML Loader "Html-loader": "^0.5.1 ",//HTML Webpack plugin" Html-webpack-plugin ":" ^2.30.1 ",//A Webpack loader for injecting code into Modul Es via their dependencies "Inject-loader": "^3.0.1",//Isparta Instrumenter, loader for webpack, used for testing "isparta- Loader ": ^2.0.0",//JSON loader "Json-loader": "^0.5.7",//JSON and JS template generation Tool "Json-templater": "^1.0.4",/ /Karma Test Library "karma": "^1.3.0", "Karma-chrome-launcher": "^2.2.0", "Karma-coverage": "^1.1.1", "Karma-mocha"
: "^1.2.0", "Karma-sinon-chai": "^1.2.4", "Karma-sourcemap-loader": "^0.3.7", "Karma-spec-reporter": "0.0.26",
"Karma-webpack": "^1.8.0",//tools for managing JavaScript projects with multiple packages. "Lerna": "^2.0.0-beta.32",//Analog Time Tool "Lolex": "^1.5.1",//markdown Parser "markdown-it": "^6.1.1", "markd Own-it-anchor ":" ^2.5.0 "," Markdown-it-container ":" ^2.0.0 ",//Mocha Test Library" Mocha ":" ^3.1.1 ",//Node.js s Ass "Node-sass": "^4.5.3",//Parallax scrolling https://perspective.js.org/#/zh-cn/"Perspective.js": "^1.0.0",//Postcss "postcss": "^5.1.2", "Postcss-loader": "0.11.1", "Postcss-sa
Lad ": ^1.0.8",//Node depth removal module "Rimraf": "^2.5.4",//Sass Loader "Sass-loader": "^6.0.6",//Sinon test framework "Sinon": "^1.17.6", "Sinon-chai": "^2.8.0",//Style loader "Style-loader": "^0.19.0",//Utf-8 character conversion "transl" Iteration ":" ^1.1.11 ",//Hump writing" Uppercamelcase ":" ^1.1.0 "," Url-loader ":" ^0.6.2 ",//Vue" vue ":" ^2.5 .2 "," Vue-loader ":" ^13.3.0 "," Vue-markdown-loader ":" 1 "," Vue-router ":" 2.7.0 "," Vue-template-compiler ": "^2.5.2", "Vue-template-es2015-compiler": "^1.6.0",//Webpack "Webpack": "^3.7.1", "Webpack-dev-server": "^2.9.1", "webpack-node-externals": "^1.6.0"}
Athey, this rely on the library really much ~ ~ I do not know how they found so many libraries. src directory
Take a look at the project structure section again. According to common sense source must be placed in the SRC directory, we find Src/index.js. The code is a bit long, and only the Install Method section is posted. What do you do next: Import all components, define installation methods, judge the environment to perform install methods, and finally export the whole.
const install = function (Vue, opts = {}) {Locale.use (Opts.locale);
locale.i18n (opts.i18n);
Components.map (Component => {//traversal will add components to Vue vue.component (component.name, component);
});
Loading of Vue.use (loading.directive);
Const ELEMENT = {}; Element.size = Opts.size | |
'';
Defines the prototype of the Vue prototype 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;
Vue.prototype. $ELEMENT = ELEMENT;
}; /* Istanbul Ignore if */if (typeof window!== ' undefined ' && window. Vue) {Install (window).
Vue); }
Import Button from ' ... /packages/button/index.js '; You can see that all components are in the packages directory. In this part we will focus on learning later.
So the problem is, now that the components are in the packages, then what are the SRC directories doing? Look at the functions of each directory: directive to achieve wheel optimization and avoid repetitive clicks. Locale is used to i18n internationalization features. Mixins looks like it should be used to mix the options in the Vue instance. Transition in rendering is the operation style to do the transition effect processing. Utils Tool folder.
The main purpose is the project structure, which is not carried out in depth. If necessary, talk later. Other Catalogs
As mentioned above, the code for all component components is stored in the package directory. It also stores the component's style. scss file.
For the type directory, the. ts file is stored. are typescript files. But there's a problem, I'm not quite sure where the TS are used. Also, typescript libraries are not imported in Package.json, except for the addition of a new typescript type declaration in the update log. There is some doubt about this.
The test directory is a unit testing case for each component, which is a good reference code for Learning unit tests (which I learned from the test framework). You need to learn unit tests to get a closer look.
The example directory is a sample project for the element. Our goal is to learn the source code, so this part of the first to ignore the last
A simple understanding of the project's compilation, the project's dependency on the library, the project's organization. The next article begins to learn about the implementation of some components. Gradually penetrate the mysterious veil of element.