├── FileSaver.js ├── LICENSE ├── README.md ├── axios ├── adapters │ ├── README.md │ ├── http.js │ └── xhr.js ├── axios.js ├── cancel │ ├── Cancel.js │ ├── CancelToken.js │ └── isCancel.js ├── core │ ├── Axios.js │ ├── InterceptorManager.js │ ├── README.md │ ├── createError.js │ ├── dispatchRequest.js │ ├── enhanceError.js │ ├── mergeConfig.js │ ├── settle.js │ └── transformData.js ├── defaults.js ├── helpers │ ├── README.md │ ├── bind.js │ ├── btoa.js │ ├── buildURL.js │ ├── combineURLs.js │ ├── cookies.js │ ├── deprecatedMethod.js │ ├── isAbsoluteURL.js │ ├── isURLSameOrigin.js │ ├── normalizeHeaderName.js │ ├── parseHeaders.js │ └── spread.js └── utils.js ├── layer ├── layer.js └── layer.png ├── layerMobile └── layer.js ├── layui ├── demo │ ├── streamLoading │ │ ├── css │ │ │ ├── font-awesome.min.css │ │ │ └── streamLoading.css │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ │ ├── index.html │ │ ├── js │ │ │ └── streamLoading.js │ │ └── lazyLoading.html │ ├── template │ │ ├── index.html │ │ └── js │ │ │ └── template.js │ ├── tree │ │ ├── css │ │ │ ├── font-awesome.min.css │ │ │ └── tree.css │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ │ ├── index.html │ │ └── js │ │ │ └── tree.js │ ├── ueditor │ │ ├── css │ │ │ ├── font-awesome.css │ │ │ ├── font-awesome.min.css │ │ │ └── ueditor.css │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ │ ├── images │ │ │ └── face │ │ │ │ ├── 0.gif │ │ │ │ ├── 1.gif │ │ │ │ ├── 10.gif │ │ │ │ ├── 11.gif │ │ │ │ ├── 12.gif │ │ │ │ ├── 13.gif │ │ │ │ ├── 14.gif │ │ │ │ ├── 15.gif │ │ │ │ ├── 16.gif │ │ │ │ ├── 17.gif │ │ │ │ ├── 18.gif │ │ │ │ ├── 19.gif │ │ │ │ ├── 2.gif │ │ │ │ ├── 20.gif │ │ │ │ ├── 21.gif │ │ │ │ ├── 22.gif │ │ │ │ ├── 23.gif │ │ │ │ ├── 24.gif │ │ │ │ ├── 25.gif │ │ │ │ ├── 26.gif │ │ │ │ ├── 27.gif │ │ │ │ ├── 28.gif │ │ │ │ ├── 29.gif │ │ │ │ ├── 3.gif │ │ │ │ ├── 30.gif │ │ │ │ ├── 31.gif │ │ │ │ ├── 32.gif │ │ │ │ ├── 33.gif │ │ │ │ ├── 34.gif │ │ │ │ ├── 35.gif │ │ │ │ ├── 36.gif │ │ │ │ ├── 37.gif │ │ │ │ ├── 38.gif │ │ │ │ ├── 39.gif │ │ │ │ ├── 4.gif │ │ │ │ ├── 40.gif │ │ │ │ ├── 41.gif │ │ │ │ ├── 42.gif │ │ │ │ ├── 43.gif │ │ │ │ ├── 44.gif │ │ │ │ ├── 45.gif │ │ │ │ ├── 46.gif │ │ │ │ ├── 47.gif │ │ │ │ ├── 48.gif │ │ │ │ ├── 49.gif │ │ │ │ ├── 5.gif │ │ │ │ ├── 50.gif │ │ │ │ ├── 51.gif │ │ │ │ ├── 52.gif │ │ │ │ ├── 53.gif │ │ │ │ ├── 54.gif │ │ │ │ ├── 55.gif │ │ │ │ ├── 56.gif │ │ │ │ ├── 57.gif │ │ │ │ ├── 58.gif │ │ │ │ ├── 59.gif │ │ │ │ ├── 6.gif │ │ │ │ ├── 60.gif │ │ │ │ ├── 61.gif │ │ │ │ ├── 62.gif │ │ │ │ ├── 63.gif │ │ │ │ ├── 64.gif │ │ │ │ ├── 65.gif │ │ │ │ ├── 66.gif │ │ │ │ ├── 67.gif │ │ │ │ ├── 68.gif │ │ │ │ ├── 69.gif │ │ │ │ ├── 7.gif │ │ │ │ ├── 70.gif │ │ │ │ ├── 71.gif │ │ │ │ ├── 8.gif │ │ │ │ └── 9.gif │ │ ├── index.html │ │ └── js │ │ │ └── ueditor.js │ └── upload │ │ ├── css │ │ └── upload.css │ │ ├── index.html │ │ └── js │ │ └── upload.js ├── images │ ├── define.png │ ├── element.js.png │ ├── laydate-detail.png │ ├── laydate.png │ ├── laydate函数.png │ ├── layui-main.png │ ├── tab事件流程.png │ └── use.png ├── lay │ ├── element.js │ ├── flow.js │ ├── laydate.js │ ├── layedit.js │ ├── laytpl.js │ ├── tree.js │ └── upload.js └── layui.js ├── monx └── monx.js ├── moon-cli ├── .gitignore ├── .gitkeep ├── LICENSE ├── README.md ├── bin │ └── moon ├── package.json └── src │ └── loader.js ├── moon ├── index.html └── moon.js ├── nprogress └── nprogress.js ├── requirejs ├── require.js ├── requireJs-define.xmind ├── requireJs.xmind └── requireJs实例流程.xmind ├── vue-cli-webpack-config ├── build │ ├── build.js │ ├── check-versions.js │ ├── utils.js │ ├── vue-loader.conf.js │ ├── webpack.base.conf.js │ ├── webpack.dev.conf.js │ └── webpack.prod.conf.js └── config │ ├── dev.env.js │ ├── index.js │ └── prod.env.js └── vue └── vue.js /FileSaver.js: -------------------------------------------------------------------------------- 1 | (function(global, factory) { 2 | if (typeof define === "function" && define.amd) { 3 | define(["exports"], factory); 4 | } else if (typeof exports !== "undefined") { 5 | factory(exports); 6 | } else { 7 | var mod = { 8 | exports: {} 9 | }; 10 | factory(mod.exports); 11 | global.FileSaver = mod.exports; 12 | } 13 | })(this, function(exports) { 14 | "use strict"; 15 | 16 | Object.defineProperty(exports, "__esModule", { 17 | value: true 18 | }); 19 | /* FileSaver.js 20 | * A saveAs() FileSaver implementation. 21 | * 1.3.8 22 | * 2018-03-22 14:03:47 23 | * 24 | * By Eli Grey, https://eligrey.com 25 | * License: MIT 26 | * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md 27 | */ 28 | 29 | /*global self */ 30 | /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ 31 | 32 | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/src/FileSaver.js */ 33 | 34 | var saveAs = exports.saveAs = saveAs || function(view) { 35 | "use strict"; 36 | // 不支持IE10以下的浏览器 37 | 38 | if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { 39 | return; 40 | } 41 | var doc = view.document 42 | // only get URL when necessary in case Blob.js hasn't overridden it yet 43 | 44 | , 45 | get_URL = function get_URL() { 46 | return view.URL || view.webkitURL || view; 47 | }, 48 | 49 | // 创建a标签,判断是否支持download 50 | save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"), 51 | can_use_save_link = "download" in save_link, 52 | 53 | // 创建click事件并触发 54 | click = function click(node) { 55 | var event = new MouseEvent("click"); 56 | node.dispatchEvent(event); 57 | }, 58 | // safari浏览器 59 | is_safari = /constructor/i.test(view.HTMLElement) || view.safari, 60 | // ISO下Chrome 61 | is_chrome_ios = /CriOS\/[\d]+/.test(navigator.userAgent), 62 | setImmediate = view.setImmediate || view.setTimeout, 63 | throw_outside = function throw_outside(ex) { 64 | setImmediate(function() { 65 | throw ex; 66 | }, 0); 67 | }, 68 | 69 | // 流下载的数据内容格式 70 | force_saveable_type = "application/octet-stream", 71 | 72 | // 超时 73 | arbitrary_revoke_timeout = 1000 * 40 // in ms 74 | 75 | , 76 | revoke = function revoke(file) { 77 | var revoker = function revoker() { 78 | if (typeof file === "string") { 79 | // file is an object URL 80 | get_URL().revokeObjectURL(file); 81 | } else { 82 | // file is a File 83 | file.remove(); 84 | } 85 | }; 86 | setTimeout(revoker, arbitrary_revoke_timeout); 87 | }, 88 | // 分别处理writestart progress write writeend事件 89 | dispatch = function dispatch(filesaver, event_types, event) { 90 | event_types = [].concat(event_types); 91 | var i = event_types.length; 92 | while (i--) { 93 | var listener = filesaver["on" + event_types[i]]; 94 | if (typeof listener === "function") { 95 | try { 96 | listener.call(filesaver, event || filesaver); 97 | } catch (ex) { 98 | throw_outside(ex); 99 | } 100 | } 101 | } 102 | }, 103 | 104 | // 设置了UTF-8格式的,添加BOM 0xFEFF就是BOM的十六进制表示 105 | auto_bom = function auto_bom(blob) { 106 | // prepend BOM for UTF-8 XML and text/* types (including HTML) 107 | // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF 108 | if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { 109 | return new Blob([String.fromCharCode(0xFEFF), blob], { type: blob.type }); 110 | } 111 | return blob; 112 | }, 113 | FileSaver = function FileSaver(blob, name, no_auto_bom) { 114 | if (!no_auto_bom) { 115 | blob = auto_bom(blob); 116 | } 117 | 118 | var filesaver = this, 119 | type = blob.type, 120 | force = type === force_saveable_type, 121 | object_url, 122 | dispatch_all = function dispatch_all() { 123 | dispatch(filesaver, "writestart progress write writeend".split(" ")); 124 | } 125 | // on any filesys errors revert to saving with object URLs 126 | 127 | , 128 | fs_error = function fs_error() { 129 | // Safari不支持使用URL对象下载,使用FileReader对象来实现 130 | if ((is_chrome_ios || force && is_safari) && view.FileReader) { 131 | // 132 | var reader = new FileReader(); 133 | // 异步读取文件结束后 134 | reader.onloadend = function() { 135 | var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;'); 136 | // 使用window.open或location.href来实现下载 137 | var popup = view.open(url, '_blank'); 138 | if (!popup) view.location.href = url; 139 | url = undefined; // release reference before dispatching 140 | filesaver.readyState = filesaver.DONE; 141 | dispatch_all(); 142 | }; 143 | // 读取blob中的文件内容 144 | reader.readAsDataURL(blob); 145 | filesaver.readyState = filesaver.INIT; 146 | return; 147 | } 148 | // 非Safari和ios下的浏览器处理,还是使用window.open来实现下载 149 | if (!object_url) { 150 | object_url = get_URL().createObjectURL(blob); 151 | } 152 | // 流内容格式下载 153 | if (force) { 154 | view.location.href = object_url; 155 | } else { 156 | var opened = view.open(object_url, "_blank"); 157 | // 浏览器内置了弹出窗口屏蔽程序,如果被阻止就会返回null 158 | if (!opened) { 159 | // Apple不支持window.open下载 160 | view.location.href = object_url; 161 | } 162 | } 163 | filesaver.readyState = filesaver.DONE; 164 | dispatch_all(); 165 | revoke(object_url); 166 | }; 167 | 168 | filesaver.readyState = filesaver.INIT; 169 | 170 | // 支持download属性就使用a标签实现下载 171 | if (can_use_save_link) { 172 | // 根据blob创建URL对象 173 | object_url = get_URL().createObjectURL(blob); 174 | setImmediate(function() { 175 | save_link.href = object_url; 176 | save_link.download = name; 177 | // 触发click事件 178 | click(save_link); 179 | // 处理暴露到外面的事件 180 | dispatch_all(); 181 | // 释放URL对象 182 | revoke(object_url); 183 | filesaver.readyState = filesaver.DONE; 184 | }, 0); 185 | return; 186 | } 187 | 188 | fs_error(); 189 | }, 190 | FS_proto = FileSaver.prototype, 191 | saveAs = function saveAs(blob, name, no_auto_bom) { 192 | return new FileSaver(blob, name || blob.name || "download", no_auto_bom); 193 | }; 194 | 195 | // IE10以上的使用浏览器本身的msSaveOrOpenBlob实现下载 196 | if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { 197 | return function(blob, name, no_auto_bom) { 198 | name = name || blob.name || "download"; 199 | 200 | if (!no_auto_bom) { 201 | blob = auto_bom(blob); 202 | } 203 | return navigator.msSaveOrOpenBlob(blob, name); 204 | }; 205 | } 206 | 207 | // todo: detect chrome extensions & packaged apps 208 | //save_link.target = "_blank"; 209 | 210 | FS_proto.abort = function() {}; 211 | FS_proto.readyState = FS_proto.INIT = 0; 212 | FS_proto.WRITING = 1; 213 | FS_proto.DONE = 2; 214 | 215 | FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null; 216 | 217 | return saveAs; 218 | }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || undefined); 219 | }); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 quyinggang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # js-sourceCode 2 | #### layer.js源码分析 3 | - [layer.js博客文章](http://blog.csdn.net/s1879046/article/details/76034784) 4 | #### layui源码分析 5 | - [流模块博客文章](http://blog.csdn.net/s1879046/article/details/76856015) 6 | - [模板引擎博客文章](http://blog.csdn.net/s1879046/article/details/76942044) 7 | - [树形菜单博客文章](http://blog.csdn.net/s1879046/article/details/77071940) 8 | - [富文本编辑器博客文章](http://blog.csdn.net/s1879046/article/details/76595590) 9 | - [上传博客文章](http://blog.csdn.net/s1879046/article/details/76279668) 10 | - [自定义事件博客文章](http://blog.csdn.net/s1879046/article/details/76216485) 11 | #### nprogress源码分析 12 | #### require源码分析 13 | - [require博客文章](http://blog.csdn.net/s1879046/article/details/78133725) 14 | #### moon源码分析 15 | - [moon博客文章](http://blog.csdn.net/s1879046/article/category/7338380) 16 | #### Axios相关 17 | - [Axios博客文章](https://blog.csdn.net/s1879046/article/category/7294206) 18 | 19 | -------------------------------------------------------------------------------- /axios/adapters/README.md: -------------------------------------------------------------------------------- 1 | # axios // adapters 2 | 3 | The modules under `adapters/` are modules that handle dispatching a request and settling a returned `Promise` once a response is received. 4 | 5 | ## Example 6 | 7 | ```js 8 | var settle = require('./../core/settle'); 9 | 10 | module.exports = function myAdapter(config) { 11 | // At this point: 12 | // - config has been merged with defaults 13 | // - request transformers have already run 14 | // - request interceptors have already run 15 | 16 | // Make the request using config provided 17 | // Upon response settle the Promise 18 | 19 | return new Promise(function(resolve, reject) { 20 | 21 | var response = { 22 | data: responseData, 23 | status: request.status, 24 | statusText: request.statusText, 25 | headers: responseHeaders, 26 | config: config, 27 | request: request 28 | }; 29 | 30 | settle(resolve, reject, response); 31 | 32 | // From here: 33 | // - response transformers will run 34 | // - response interceptors will run 35 | }); 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /axios/adapters/http.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | var settle = require('./../core/settle'); 5 | var buildURL = require('./../helpers/buildURL'); 6 | var http = require('http'); 7 | var https = require('https'); 8 | var httpFollow = require('follow-redirects').http; 9 | var httpsFollow = require('follow-redirects').https; 10 | var url = require('url'); 11 | var zlib = require('zlib'); 12 | var pkg = require('./../../package.json'); 13 | var createError = require('../core/createError'); 14 | var enhanceError = require('../core/enhanceError'); 15 | 16 | var isHttps = /https:?/; 17 | 18 | /*eslint consistent-return:0*/ 19 | module.exports = function httpAdapter(config) { 20 | return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) { 21 | var timer; 22 | var resolve = function resolve(value) { 23 | clearTimeout(timer); 24 | resolvePromise(value); 25 | }; 26 | var reject = function reject(value) { 27 | clearTimeout(timer); 28 | rejectPromise(value); 29 | }; 30 | var data = config.data; 31 | var headers = config.headers; 32 | 33 | // Set User-Agent (required by some servers) 34 | // Only set header if it hasn't been set in config 35 | // See https://github.com/axios/axios/issues/69 36 | if (!headers['User-Agent'] && !headers['user-agent']) { 37 | headers['User-Agent'] = 'axios/' + pkg.version; 38 | } 39 | 40 | if (data && !utils.isStream(data)) { 41 | if (Buffer.isBuffer(data)) { 42 | // Nothing to do... 43 | } else if (utils.isArrayBuffer(data)) { 44 | data = Buffer.from(new Uint8Array(data)); 45 | } else if (utils.isString(data)) { 46 | data = Buffer.from(data, 'utf-8'); 47 | } else { 48 | return reject(createError( 49 | 'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream', 50 | config 51 | )); 52 | } 53 | 54 | // Add Content-Length header if data exists 55 | headers['Content-Length'] = data.length; 56 | } 57 | 58 | // HTTP basic authentication 59 | var auth = undefined; 60 | if (config.auth) { 61 | var username = config.auth.username || ''; 62 | var password = config.auth.password || ''; 63 | auth = username + ':' + password; 64 | } 65 | 66 | // Parse url 67 | var parsed = url.parse(config.url); 68 | var protocol = parsed.protocol || 'http:'; 69 | 70 | if (!auth && parsed.auth) { 71 | var urlAuth = parsed.auth.split(':'); 72 | var urlUsername = urlAuth[0] || ''; 73 | var urlPassword = urlAuth[1] || ''; 74 | auth = urlUsername + ':' + urlPassword; 75 | } 76 | 77 | if (auth) { 78 | delete headers.Authorization; 79 | } 80 | 81 | var isHttpsRequest = isHttps.test(protocol); 82 | var agent = isHttpsRequest ? config.httpsAgent : config.httpAgent; 83 | 84 | var options = { 85 | path: buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''), 86 | method: config.method, 87 | headers: headers, 88 | agent: agent, 89 | auth: auth 90 | }; 91 | 92 | if (config.socketPath) { 93 | options.socketPath = config.socketPath; 94 | } else { 95 | options.hostname = parsed.hostname; 96 | options.port = parsed.port; 97 | } 98 | 99 | var proxy = config.proxy; 100 | if (!proxy && proxy !== false) { 101 | var proxyEnv = protocol.slice(0, -1) + '_proxy'; 102 | var proxyUrl = process.env[proxyEnv] || process.env[proxyEnv.toUpperCase()]; 103 | if (proxyUrl) { 104 | var parsedProxyUrl = url.parse(proxyUrl); 105 | proxy = { 106 | host: parsedProxyUrl.hostname, 107 | port: parsedProxyUrl.port 108 | }; 109 | 110 | if (parsedProxyUrl.auth) { 111 | var proxyUrlAuth = parsedProxyUrl.auth.split(':'); 112 | proxy.auth = { 113 | username: proxyUrlAuth[0], 114 | password: proxyUrlAuth[1] 115 | }; 116 | } 117 | } 118 | } 119 | 120 | if (proxy) { 121 | options.hostname = proxy.host; 122 | options.host = proxy.host; 123 | options.headers.host = parsed.hostname + (parsed.port ? ':' + parsed.port : ''); 124 | options.port = proxy.port; 125 | options.path = protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path; 126 | 127 | // Basic proxy authorization 128 | if (proxy.auth) { 129 | var base64 = Buffer.from(proxy.auth.username + ':' + proxy.auth.password, 'utf8').toString('base64'); 130 | options.headers['Proxy-Authorization'] = 'Basic ' + base64; 131 | } 132 | } 133 | 134 | var transport; 135 | var isHttpsProxy = isHttpsRequest && (proxy ? isHttps.test(proxy.protocol) : true); 136 | if (config.transport) { 137 | transport = config.transport; 138 | } else if (config.maxRedirects === 0) { 139 | transport = isHttpsProxy ? https : http; 140 | } else { 141 | if (config.maxRedirects) { 142 | options.maxRedirects = config.maxRedirects; 143 | } 144 | transport = isHttpsProxy ? httpsFollow : httpFollow; 145 | } 146 | 147 | if (config.maxContentLength && config.maxContentLength > -1) { 148 | options.maxBodyLength = config.maxContentLength; 149 | } 150 | 151 | // Create the request 152 | var req = transport.request(options, function handleResponse(res) { 153 | if (req.aborted) return; 154 | 155 | // uncompress the response body transparently if required 156 | var stream = res; 157 | switch (res.headers['content-encoding']) { 158 | /*eslint default-case:0*/ 159 | case 'gzip': 160 | case 'compress': 161 | case 'deflate': 162 | // add the unzipper to the body stream processing pipeline 163 | stream = stream.pipe(zlib.createUnzip()); 164 | 165 | // remove the content-encoding in order to not confuse downstream operations 166 | delete res.headers['content-encoding']; 167 | break; 168 | } 169 | 170 | // return the last request in case of redirects 171 | var lastRequest = res.req || req; 172 | 173 | var response = { 174 | status: res.statusCode, 175 | statusText: res.statusMessage, 176 | headers: res.headers, 177 | config: config, 178 | request: lastRequest 179 | }; 180 | 181 | if (config.responseType === 'stream') { 182 | response.data = stream; 183 | settle(resolve, reject, response); 184 | } else { 185 | var responseBuffer = []; 186 | stream.on('data', function handleStreamData(chunk) { 187 | responseBuffer.push(chunk); 188 | 189 | // make sure the content length is not over the maxContentLength if specified 190 | if (config.maxContentLength > -1 && Buffer.concat(responseBuffer).length > config.maxContentLength) { 191 | reject(createError('maxContentLength size of ' + config.maxContentLength + ' exceeded', 192 | config, null, lastRequest)); 193 | } 194 | }); 195 | 196 | stream.on('error', function handleStreamError(err) { 197 | if (req.aborted) return; 198 | reject(enhanceError(err, config, null, lastRequest)); 199 | }); 200 | 201 | stream.on('end', function handleStreamEnd() { 202 | var responseData = Buffer.concat(responseBuffer); 203 | if (config.responseType !== 'arraybuffer') { 204 | responseData = responseData.toString(config.responseEncoding); 205 | } 206 | 207 | response.data = responseData; 208 | settle(resolve, reject, response); 209 | }); 210 | } 211 | }); 212 | 213 | // Handle errors 214 | req.on('error', function handleRequestError(err) { 215 | if (req.aborted) return; 216 | reject(enhanceError(err, config, null, req)); 217 | }); 218 | 219 | // Handle request timeout 220 | if (config.timeout) { 221 | timer = setTimeout(function handleRequestTimeout() { 222 | req.abort(); 223 | reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', req)); 224 | }, config.timeout); 225 | } 226 | 227 | if (config.cancelToken) { 228 | // Handle cancellation 229 | config.cancelToken.promise.then(function onCanceled(cancel) { 230 | if (req.aborted) return; 231 | 232 | req.abort(); 233 | reject(cancel); 234 | }); 235 | } 236 | 237 | // Send the request 238 | if (utils.isStream(data)) { 239 | data.on('error', function handleStreamError(err) { 240 | reject(enhanceError(err, config, null, req)); 241 | }).pipe(req); 242 | } else { 243 | req.end(data); 244 | } 245 | }); 246 | }; 247 | -------------------------------------------------------------------------------- /axios/adapters/xhr.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | var settle = require('./../core/settle'); 5 | var buildURL = require('./../helpers/buildURL'); 6 | var parseHeaders = require('./../helpers/parseHeaders'); 7 | var isURLSameOrigin = require('./../helpers/isURLSameOrigin'); 8 | var createError = require('../core/createError'); 9 | var btoa = (typeof window !== 'undefined' && window.btoa && window.btoa.bind(window)) || require('./../helpers/btoa'); 10 | 11 | module.exports = function xhrAdapter(config) { 12 | return new Promise(function dispatchXhrRequest(resolve, reject) { 13 | var requestData = config.data; 14 | var requestHeaders = config.headers; 15 | 16 | if (utils.isFormData(requestData)) { 17 | delete requestHeaders['Content-Type']; // Let the browser set it 18 | } 19 | 20 | var request = new XMLHttpRequest(); 21 | var loadEvent = 'onreadystatechange'; 22 | var xDomain = false; 23 | 24 | // For IE 8/9 CORS support 25 | // Only supports POST and GET calls and doesn't returns the response headers. 26 | // DON'T do this for testing b/c XMLHttpRequest is mocked, not XDomainRequest. 27 | if (process.env.NODE_ENV !== 'test' && 28 | typeof window !== 'undefined' && 29 | window.XDomainRequest && !('withCredentials' in request) && 30 | !isURLSameOrigin(config.url)) { 31 | request = new window.XDomainRequest(); 32 | loadEvent = 'onload'; 33 | xDomain = true; 34 | request.onprogress = function handleProgress() {}; 35 | request.ontimeout = function handleTimeout() {}; 36 | } 37 | 38 | // HTTP basic authentication 39 | if (config.auth) { 40 | var username = config.auth.username || ''; 41 | var password = config.auth.password || ''; 42 | requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password); 43 | } 44 | 45 | request.open(config.method.toUpperCase(), buildURL(config.url, config.params, config.paramsSerializer), true); 46 | 47 | // Set the request timeout in MS 48 | request.timeout = config.timeout; 49 | 50 | // Listen for ready state 51 | request[loadEvent] = function handleLoad() { 52 | if (!request || (request.readyState !== 4 && !xDomain)) { 53 | return; 54 | } 55 | 56 | // The request errored out and we didn't get a response, this will be 57 | // handled by onerror instead 58 | // With one exception: request that using file: protocol, most browsers 59 | // will return status as 0 even though it's a successful request 60 | if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) { 61 | return; 62 | } 63 | 64 | // Prepare the response 65 | var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null; 66 | var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response; 67 | var response = { 68 | data: responseData, 69 | // IE sends 1223 instead of 204 (https://github.com/axios/axios/issues/201) 70 | status: request.status === 1223 ? 204 : request.status, 71 | statusText: request.status === 1223 ? 'No Content' : request.statusText, 72 | headers: responseHeaders, 73 | config: config, 74 | request: request 75 | }; 76 | 77 | settle(resolve, reject, response); 78 | 79 | // Clean up request 80 | request = null; 81 | }; 82 | 83 | // Handle browser request cancellation (as opposed to a manual cancellation) 84 | request.onabort = function handleAbort() { 85 | if (!request) { 86 | return; 87 | } 88 | 89 | reject(createError('Request aborted', config, 'ECONNABORTED', request)); 90 | 91 | // Clean up request 92 | request = null; 93 | }; 94 | 95 | // Handle low level network errors 96 | request.onerror = function handleError() { 97 | // Real errors are hidden from us by the browser 98 | // onerror should only fire if it's a network error 99 | reject(createError('Network Error', config, null, request)); 100 | 101 | // Clean up request 102 | request = null; 103 | }; 104 | 105 | // Handle timeout 106 | request.ontimeout = function handleTimeout() { 107 | reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', 108 | request)); 109 | 110 | // Clean up request 111 | request = null; 112 | }; 113 | 114 | // Add xsrf header 115 | // This is only done if running in a standard browser environment. 116 | // Specifically not if we're in a web worker, or react-native. 117 | if (utils.isStandardBrowserEnv()) { 118 | var cookies = require('./../helpers/cookies'); 119 | 120 | // Add xsrf header 121 | var xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ? 122 | cookies.read(config.xsrfCookieName) : 123 | undefined; 124 | 125 | if (xsrfValue) { 126 | requestHeaders[config.xsrfHeaderName] = xsrfValue; 127 | } 128 | } 129 | 130 | // Add headers to the request 131 | if ('setRequestHeader' in request) { 132 | utils.forEach(requestHeaders, function setRequestHeader(val, key) { 133 | if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') { 134 | // Remove Content-Type if data is undefined 135 | delete requestHeaders[key]; 136 | } else { 137 | // Otherwise add header to the request 138 | request.setRequestHeader(key, val); 139 | } 140 | }); 141 | } 142 | 143 | // Add withCredentials to request if needed 144 | if (config.withCredentials) { 145 | request.withCredentials = true; 146 | } 147 | 148 | // Add responseType to request if needed 149 | if (config.responseType) { 150 | try { 151 | request.responseType = config.responseType; 152 | } catch (e) { 153 | // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2. 154 | // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function. 155 | if (config.responseType !== 'json') { 156 | throw e; 157 | } 158 | } 159 | } 160 | 161 | // Handle progress if needed 162 | if (typeof config.onDownloadProgress === 'function') { 163 | request.addEventListener('progress', config.onDownloadProgress); 164 | } 165 | 166 | // Not all browsers support upload events 167 | if (typeof config.onUploadProgress === 'function' && request.upload) { 168 | request.upload.addEventListener('progress', config.onUploadProgress); 169 | } 170 | 171 | if (config.cancelToken) { 172 | // Handle cancellation 173 | config.cancelToken.promise.then(function onCanceled(cancel) { 174 | if (!request) { 175 | return; 176 | } 177 | 178 | request.abort(); 179 | reject(cancel); 180 | // Clean up request 181 | request = null; 182 | }); 183 | } 184 | 185 | if (requestData === undefined) { 186 | requestData = null; 187 | } 188 | 189 | // Send the request 190 | request.send(requestData); 191 | }); 192 | }; 193 | -------------------------------------------------------------------------------- /axios/axios.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./utils'); 4 | var bind = require('./helpers/bind'); 5 | var Axios = require('./core/Axios'); 6 | var mergeConfig = require('./core/mergeConfig'); 7 | var defaults = require('./defaults'); 8 | 9 | /** 10 | * 创建axios实例,工厂模式 11 | */ 12 | function createInstance(defaultConfig) { 13 | // Axios构造函数 14 | var context = new Axios(defaultConfig); 15 | 16 | /* 17 | 实际上是调用request方法 18 | instance = function wrap() { 19 | return Axios.prototype.request.apply(context, [...arguments]); 20 | } 21 | */ 22 | var instance = bind(Axios.prototype.request, context); 23 | 24 | // 将Axios.prototype实例上的方法复制到instance函数上,并改变this指向为axios实例 25 | utils.extend(instance, Axios.prototype, context); 26 | 27 | // 将axios实例上的方法复制到isntance上 28 | utils.extend(instance, context); 29 | 30 | return instance; 31 | } 32 | 33 | // 默认配置对象是defaults.js暴露出来的对象 34 | /* 35 | var axios = function wrap(defaults) { 36 | return Axios.prototype.request.apply(context, [...defaults]); 37 | } 38 | */ 39 | var axios = createInstance(defaults); 40 | 41 | // 暴露Axios构造函数 42 | axios.Axios = Axios; 43 | 44 | // 暴露create方法,用于创建axios实例 45 | axios.create = function create(instanceConfig) { 46 | return createInstance(mergeConfig(axios.defaults, instanceConfig)); 47 | }; 48 | 49 | // 暴露 Cancel & CancelToken 50 | axios.Cancel = require('./cancel/Cancel'); 51 | axios.CancelToken = require('./cancel/CancelToken'); 52 | axios.isCancel = require('./cancel/isCancel'); 53 | 54 | // 暴露all方法,该方法是并行处理多个请求 55 | axios.all = function all(promises) { 56 | return Promise.all(promises); 57 | }; 58 | // 暴露spread 59 | axios.spread = require('./helpers/spread'); 60 | 61 | // 暴露axios实例 62 | module.exports = axios; 63 | 64 | // Allow use of default import syntax in TypeScript 65 | module.exports.default = axios; 66 | -------------------------------------------------------------------------------- /axios/cancel/Cancel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * A `Cancel` is an object that is thrown when an operation is canceled. 5 | * 6 | * @class 7 | * @param {string=} message The message. 8 | */ 9 | function Cancel(message) { 10 | this.message = message; 11 | } 12 | 13 | Cancel.prototype.toString = function toString() { 14 | return 'Cancel' + (this.message ? ': ' + this.message : ''); 15 | }; 16 | 17 | Cancel.prototype.__CANCEL__ = true; 18 | 19 | module.exports = Cancel; 20 | -------------------------------------------------------------------------------- /axios/cancel/CancelToken.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Cancel = require('./Cancel'); 4 | 5 | /** 6 | * A `CancelToken` is an object that can be used to request cancellation of an operation. 7 | * 8 | * @class 9 | * @param {Function} executor The executor function. 10 | */ 11 | function CancelToken(executor) { 12 | if (typeof executor !== 'function') { 13 | throw new TypeError('executor must be a function.'); 14 | } 15 | 16 | var resolvePromise; 17 | this.promise = new Promise(function promiseExecutor(resolve) { 18 | resolvePromise = resolve; 19 | }); 20 | 21 | var token = this; 22 | executor(function cancel(message) { 23 | if (token.reason) { 24 | // Cancellation has already been requested 25 | return; 26 | } 27 | 28 | token.reason = new Cancel(message); 29 | resolvePromise(token.reason); 30 | }); 31 | } 32 | 33 | /** 34 | * Throws a `Cancel` if cancellation has been requested. 35 | */ 36 | CancelToken.prototype.throwIfRequested = function throwIfRequested() { 37 | if (this.reason) { 38 | throw this.reason; 39 | } 40 | }; 41 | 42 | /** 43 | * Returns an object that contains a new `CancelToken` and a function that, when called, 44 | * cancels the `CancelToken`. 45 | */ 46 | CancelToken.source = function source() { 47 | var cancel; 48 | var token = new CancelToken(function executor(c) { 49 | cancel = c; 50 | }); 51 | return { 52 | token: token, 53 | cancel: cancel 54 | }; 55 | }; 56 | 57 | module.exports = CancelToken; 58 | -------------------------------------------------------------------------------- /axios/cancel/isCancel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function isCancel(value) { 4 | return !!(value && value.__CANCEL__); 5 | }; 6 | -------------------------------------------------------------------------------- /axios/core/Axios.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | var InterceptorManager = require('./InterceptorManager'); 5 | var dispatchRequest = require('./dispatchRequest'); 6 | var mergeConfig = require('./mergeConfig'); 7 | 8 | /** 9 | * Axios实例创建 10 | * - axios({})形式 11 | * 12 | * - defaults: 用户传递的配置对象 13 | * - interceptors:默认拦截器,定义了请求和响应的拦截器 14 | */ 15 | function Axios(instanceConfig) { 16 | this.defaults = instanceConfig; 17 | this.interceptors = { 18 | request: new InterceptorManager(), 19 | response: new InterceptorManager() 20 | }; 21 | } 22 | 23 | /** 24 | * axios的实际调用函数 25 | */ 26 | Axios.prototype.request = function request(config) { 27 | // 支持axios(url, config) 28 | if (typeof config === 'string') { 29 | config = arguments[1] || {}; 30 | config.url = arguments[0]; 31 | } else { 32 | config = config || {}; 33 | } 34 | 35 | // 应用自定义配置 36 | config = mergeConfig(this.defaults, config); 37 | // 如果method不存在,则默认get请求 38 | config.method = config.method ? config.method.toLowerCase() : 'get'; 39 | 40 | // dispatchRequest核心,包含发出请求 41 | var chain = [dispatchRequest, undefined]; 42 | var promise = Promise.resolve(config); 43 | 44 | // 多个请求拦截器的处理 45 | // [拦截器,...,dispatchRequest, undefined] 46 | this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { 47 | chain.unshift(interceptor.fulfilled, interceptor.rejected); 48 | }); 49 | 50 | // 多个响应拦截器的处理 51 | // [dispatchRequest, undefined, 拦截器] 52 | this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { 53 | chain.push(interceptor.fulfilled, interceptor.rejected); 54 | }); 55 | 56 | // 执行请求,包含拦截器的处理,通过上面数组保证请求拦截器和响应拦截器在请求前和请求完成执行 57 | // 这里实际上形成一个链式,下一次依赖上一次的promise值 58 | while (chain.length) { 59 | promise = promise.then(chain.shift(), chain.shift()); 60 | } 61 | 62 | // 返回执行结果 63 | return promise; 64 | }; 65 | 66 | // Provide aliases for supported request methods 67 | utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { 68 | /*eslint func-names:0*/ 69 | Axios.prototype[method] = function(url, config) { 70 | return this.request(utils.merge(config || {}, { 71 | method: method, 72 | url: url 73 | })); 74 | }; 75 | }); 76 | 77 | utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { 78 | /*eslint func-names:0*/ 79 | Axios.prototype[method] = function(url, data, config) { 80 | return this.request(utils.merge(config || {}, { 81 | method: method, 82 | url: url, 83 | data: data 84 | })); 85 | }; 86 | }); 87 | 88 | module.exports = Axios; 89 | -------------------------------------------------------------------------------- /axios/core/InterceptorManager.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | // 拦截器管理对象 6 | function InterceptorManager() { 7 | this.handlers = []; 8 | } 9 | 10 | /** 11 | * 添加拦截器:fulfilled处理resolve状态,rejected处理reject状态 12 | */ 13 | InterceptorManager.prototype.use = function use(fulfilled, rejected) { 14 | this.handlers.push({ 15 | fulfilled: fulfilled, 16 | rejected: rejected 17 | }); 18 | // 返回当前下标 19 | return this.handlers.length - 1; 20 | }; 21 | 22 | /** 23 | * 移除已定义的拦截器 24 | */ 25 | InterceptorManager.prototype.eject = function eject(id) { 26 | if (this.handlers[id]) { 27 | this.handlers[id] = null; 28 | } 29 | }; 30 | 31 | /** 32 | * 遍历处理拦截器 33 | */ 34 | InterceptorManager.prototype.forEach = function forEach(fn) { 35 | utils.forEach(this.handlers, function forEachHandler(h) { 36 | if (h !== null) { 37 | fn(h); 38 | } 39 | }); 40 | }; 41 | 42 | module.exports = InterceptorManager; 43 | -------------------------------------------------------------------------------- /axios/core/README.md: -------------------------------------------------------------------------------- 1 | # axios // core 2 | 3 | The modules found in `core/` should be modules that are specific to the domain logic of axios. These modules would most likely not make sense to be consumed outside of the axios module, as their logic is too specific. Some examples of core modules are: 4 | 5 | - Dispatching requests 6 | - Managing interceptors 7 | - Handling config 8 | -------------------------------------------------------------------------------- /axios/core/createError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var enhanceError = require('./enhanceError'); 4 | 5 | /** 6 | * Create an Error with the specified message, config, error code, request and response. 7 | * 8 | * @param {string} message The error message. 9 | * @param {Object} config The config. 10 | * @param {string} [code] The error code (for example, 'ECONNABORTED'). 11 | * @param {Object} [request] The request. 12 | * @param {Object} [response] The response. 13 | * @returns {Error} The created error. 14 | */ 15 | module.exports = function createError(message, config, code, request, response) { 16 | var error = new Error(message); 17 | return enhanceError(error, config, code, request, response); 18 | }; 19 | -------------------------------------------------------------------------------- /axios/core/dispatchRequest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | var transformData = require('./transformData'); 5 | var isCancel = require('../cancel/isCancel'); 6 | var defaults = require('../defaults'); 7 | var isAbsoluteURL = require('./../helpers/isAbsoluteURL'); 8 | var combineURLs = require('./../helpers/combineURLs'); 9 | 10 | /** 11 | * Throws a `Cancel` if cancellation has been requested. 12 | */ 13 | function throwIfCancellationRequested(config) { 14 | if (config.cancelToken) { 15 | config.cancelToken.throwIfRequested(); 16 | } 17 | } 18 | 19 | /** 20 | * 发送请求 21 | */ 22 | module.exports = function dispatchRequest(config) { 23 | throwIfCancellationRequested(config); 24 | 25 | // Support baseURL config 26 | if (config.baseURL && !isAbsoluteURL(config.url)) { 27 | config.url = combineURLs(config.baseURL, config.url); 28 | } 29 | 30 | config.headers = config.headers || {}; 31 | 32 | // 处理请求参数,应用transformRequest配置 33 | config.data = transformData( 34 | config.data, 35 | config.headers, 36 | config.transformRequest 37 | ); 38 | 39 | // Flatten headers 40 | config.headers = utils.merge( 41 | config.headers.common || {}, 42 | config.headers[config.method] || {}, 43 | config.headers || {} 44 | ); 45 | 46 | utils.forEach( 47 | ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], 48 | function cleanHeaderConfig(method) { 49 | delete config.headers[method]; 50 | } 51 | ); 52 | 53 | var adapter = config.adapter || defaults.adapter; 54 | 55 | // 发送请求,可以看出实际上是调用配置的HTTP适配器或xhr适配器 56 | return adapter(config).then(function onAdapterResolution(response) { 57 | throwIfCancellationRequested(config); 58 | 59 | // 请求成功处理响应参数,应用transformResponse处理参数 60 | response.data = transformData( 61 | response.data, 62 | response.headers, 63 | config.transformResponse 64 | ); 65 | 66 | return response; 67 | }, function onAdapterRejection(reason) { 68 | if (!isCancel(reason)) { 69 | throwIfCancellationRequested(config); 70 | 71 | // Transform response data 72 | if (reason && reason.response) { 73 | reason.response.data = transformData( 74 | reason.response.data, 75 | reason.response.headers, 76 | config.transformResponse 77 | ); 78 | } 79 | } 80 | 81 | return Promise.reject(reason); 82 | }); 83 | }; 84 | -------------------------------------------------------------------------------- /axios/core/enhanceError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Update an Error with the specified config, error code, and response. 5 | * 6 | * @param {Error} error The error to update. 7 | * @param {Object} config The config. 8 | * @param {string} [code] The error code (for example, 'ECONNABORTED'). 9 | * @param {Object} [request] The request. 10 | * @param {Object} [response] The response. 11 | * @returns {Error} The error. 12 | */ 13 | module.exports = function enhanceError(error, config, code, request, response) { 14 | error.config = config; 15 | if (code) { 16 | error.code = code; 17 | } 18 | error.request = request; 19 | error.response = response; 20 | return error; 21 | }; 22 | -------------------------------------------------------------------------------- /axios/core/mergeConfig.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('../utils'); 4 | 5 | /** 6 | * Config-specific merge-function which creates a new config-object 7 | * by merging two configuration objects together. 8 | * 9 | * @param {Object} config1 10 | * @param {Object} config2 11 | * @returns {Object} New object resulting from merging config2 to config1 12 | */ 13 | module.exports = function mergeConfig(config1, config2) { 14 | // eslint-disable-next-line no-param-reassign 15 | config2 = config2 || {}; 16 | var config = {}; 17 | 18 | utils.forEach(['url', 'method', 'params', 'data'], function valueFromConfig2(prop) { 19 | if (typeof config2[prop] !== 'undefined') { 20 | config[prop] = config2[prop]; 21 | } 22 | }); 23 | 24 | utils.forEach(['headers', 'auth', 'proxy'], function mergeDeepProperties(prop) { 25 | if (utils.isObject(config2[prop])) { 26 | config[prop] = utils.deepMerge(config1[prop], config2[prop]); 27 | } else if (typeof config2[prop] !== 'undefined') { 28 | config[prop] = config2[prop]; 29 | } else if (utils.isObject(config1[prop])) { 30 | config[prop] = utils.deepMerge(config1[prop]); 31 | } else if (typeof config1[prop] !== 'undefined') { 32 | config[prop] = config1[prop]; 33 | } 34 | }); 35 | 36 | utils.forEach([ 37 | 'baseURL', 'transformRequest', 'transformResponse', 'paramsSerializer', 38 | 'timeout', 'withCredentials', 'adapter', 'responseType', 'xsrfCookieName', 39 | 'xsrfHeaderName', 'onUploadProgress', 'onDownloadProgress', 'maxContentLength', 40 | 'validateStatus', 'maxRedirects', 'httpAgent', 'httpsAgent', 'cancelToken', 41 | 'socketPath' 42 | ], function defaultToConfig2(prop) { 43 | if (typeof config2[prop] !== 'undefined') { 44 | config[prop] = config2[prop]; 45 | } else if (typeof config1[prop] !== 'undefined') { 46 | config[prop] = config1[prop]; 47 | } 48 | }); 49 | 50 | return config; 51 | }; 52 | -------------------------------------------------------------------------------- /axios/core/settle.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var createError = require('./createError'); 4 | 5 | /** 6 | * Resolve or reject a Promise based on response status. 7 | * 8 | * @param {Function} resolve A function that resolves the promise. 9 | * @param {Function} reject A function that rejects the promise. 10 | * @param {object} response The response. 11 | */ 12 | module.exports = function settle(resolve, reject, response) { 13 | var validateStatus = response.config.validateStatus; 14 | // Note: status is not exposed by XDomainRequest 15 | if (!response.status || !validateStatus || validateStatus(response.status)) { 16 | resolve(response); 17 | } else { 18 | reject(createError( 19 | 'Request failed with status code ' + response.status, 20 | response.config, 21 | null, 22 | response.request, 23 | response 24 | )); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /axios/core/transformData.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | /** 6 | * Transform the data for a request or a response 7 | * 8 | * @param {Object|String} data The data to be transformed 9 | * @param {Array} headers The headers for the request or response 10 | * @param {Array|Function} fns A single function or Array of functions 11 | * @returns {*} The resulting transformed data 12 | */ 13 | module.exports = function transformData(data, headers, fns) { 14 | /*eslint no-param-reassign:0*/ 15 | utils.forEach(fns, function transform(fn) { 16 | data = fn(data, headers); 17 | }); 18 | 19 | return data; 20 | }; 21 | -------------------------------------------------------------------------------- /axios/defaults.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./utils'); 4 | var normalizeHeaderName = require('./helpers/normalizeHeaderName'); 5 | 6 | // 默认MIME,默认是按照表单形式提交 7 | var DEFAULT_CONTENT_TYPE = { 8 | 'Content-Type': 'application/x-www-form-urlencoded' 9 | }; 10 | 11 | function setContentTypeIfUnset(headers, value) { 12 | if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) { 13 | headers['Content-Type'] = value; 14 | } 15 | } 16 | 17 | // 判断使用哪种形式请求,Node.js http、Brower xhr 18 | function getDefaultAdapter() { 19 | var adapter; 20 | // Only Node.JS has a process variable that is of [[Class]] process 21 | if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') { 22 | // For node use HTTP adapter 23 | adapter = require('./adapters/http'); 24 | } else if (typeof XMLHttpRequest !== 'undefined') { 25 | // For browsers use XHR adapter 26 | adapter = require('./adapters/xhr'); 27 | } 28 | return adapter; 29 | } 30 | 31 | var defaults = { 32 | // 请求适配器 33 | adapter: getDefaultAdapter(), 34 | // 处理请求的参数,格式化参数形式 35 | transformRequest: [function transformRequest(data, headers) { 36 | normalizeHeaderName(headers, 'Content-Type'); 37 | if (utils.isFormData(data) || 38 | utils.isArrayBuffer(data) || 39 | utils.isBuffer(data) || 40 | utils.isStream(data) || 41 | utils.isFile(data) || 42 | utils.isBlob(data) 43 | ) { 44 | return data; 45 | } 46 | if (utils.isArrayBufferView(data)) { 47 | return data.buffer; 48 | } 49 | if (utils.isURLSearchParams(data)) { 50 | setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8'); 51 | return data.toString(); 52 | } 53 | if (utils.isObject(data)) { 54 | setContentTypeIfUnset(headers, 'application/json;charset=utf-8'); 55 | return JSON.stringify(data); 56 | } 57 | return data; 58 | }], 59 | // 允许处理请求后数据数据格式 60 | transformResponse: [function transformResponse(data) { 61 | /*eslint no-param-reassign:0*/ 62 | if (typeof data === 'string') { 63 | try { 64 | data = JSON.parse(data); 65 | } catch (e) { /* Ignore */ } 66 | } 67 | return data; 68 | }], 69 | 70 | /** 71 | * A timeout in milliseconds to abort a request. If set to 0 (default) a 72 | * timeout is not created. 73 | * 请求超时设置 74 | */ 75 | timeout: 0, 76 | 77 | // 跨站请求伪造攻击处理 78 | xsrfCookieName: 'XSRF-TOKEN', 79 | xsrfHeaderName: 'X-XSRF-TOKEN', 80 | 81 | // 最大内容长度 82 | maxContentLength: -1, 83 | 84 | validateStatus: function validateStatus(status) { 85 | return status >= 200 && status < 300; 86 | } 87 | }; 88 | 89 | // headers 90 | defaults.headers = { 91 | common: { 92 | 'Accept': 'application/json, text/plain, */*' 93 | } 94 | }; 95 | 96 | utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) { 97 | defaults.headers[method] = {}; 98 | }); 99 | 100 | utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { 101 | defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE); 102 | }); 103 | 104 | module.exports = defaults; 105 | -------------------------------------------------------------------------------- /axios/helpers/README.md: -------------------------------------------------------------------------------- 1 | # axios // helpers 2 | 3 | The modules found in `helpers/` should be generic modules that are _not_ specific to the domain logic of axios. These modules could theoretically be published to npm on their own and consumed by other modules or apps. Some examples of generic modules are things like: 4 | 5 | - Browser polyfills 6 | - Managing cookies 7 | - Parsing HTTP headers 8 | -------------------------------------------------------------------------------- /axios/helpers/bind.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function bind(fn, thisArg) { 4 | return function wrap() { 5 | var args = new Array(arguments.length); 6 | for (var i = 0; i < args.length; i++) { 7 | args[i] = arguments[i]; 8 | } 9 | return fn.apply(thisArg, args); 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /axios/helpers/btoa.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // btoa polyfill for IE<10 courtesy https://github.com/davidchambers/Base64.js 4 | 5 | var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; 6 | 7 | function E() { 8 | this.message = 'String contains an invalid character'; 9 | } 10 | E.prototype = new Error; 11 | E.prototype.code = 5; 12 | E.prototype.name = 'InvalidCharacterError'; 13 | 14 | function btoa(input) { 15 | var str = String(input); 16 | var output = ''; 17 | for ( 18 | // initialize result and counter 19 | var block, charCode, idx = 0, map = chars; 20 | // if the next str index does not exist: 21 | // change the mapping table to "=" 22 | // check if d has no fractional digits 23 | str.charAt(idx | 0) || (map = '=', idx % 1); 24 | // "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8 25 | output += map.charAt(63 & block >> 8 - idx % 1 * 8) 26 | ) { 27 | charCode = str.charCodeAt(idx += 3 / 4); 28 | if (charCode > 0xFF) { 29 | throw new E(); 30 | } 31 | block = block << 8 | charCode; 32 | } 33 | return output; 34 | } 35 | 36 | module.exports = btoa; 37 | -------------------------------------------------------------------------------- /axios/helpers/buildURL.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | function encode(val) { 6 | return encodeURIComponent(val). 7 | replace(/%40/gi, '@'). 8 | replace(/%3A/gi, ':'). 9 | replace(/%24/g, '$'). 10 | replace(/%2C/gi, ','). 11 | replace(/%20/g, '+'). 12 | replace(/%5B/gi, '['). 13 | replace(/%5D/gi, ']'); 14 | } 15 | 16 | /** 17 | * Build a URL by appending params to the end 18 | * 19 | * @param {string} url The base of the url (e.g., http://www.google.com) 20 | * @param {object} [params] The params to be appended 21 | * @returns {string} The formatted url 22 | */ 23 | module.exports = function buildURL(url, params, paramsSerializer) { 24 | /*eslint no-param-reassign:0*/ 25 | if (!params) { 26 | return url; 27 | } 28 | 29 | var serializedParams; 30 | if (paramsSerializer) { 31 | serializedParams = paramsSerializer(params); 32 | } else if (utils.isURLSearchParams(params)) { 33 | serializedParams = params.toString(); 34 | } else { 35 | var parts = []; 36 | 37 | utils.forEach(params, function serialize(val, key) { 38 | if (val === null || typeof val === 'undefined') { 39 | return; 40 | } 41 | 42 | if (utils.isArray(val)) { 43 | key = key + '[]'; 44 | } else { 45 | val = [val]; 46 | } 47 | 48 | utils.forEach(val, function parseValue(v) { 49 | if (utils.isDate(v)) { 50 | v = v.toISOString(); 51 | } else if (utils.isObject(v)) { 52 | v = JSON.stringify(v); 53 | } 54 | parts.push(encode(key) + '=' + encode(v)); 55 | }); 56 | }); 57 | 58 | serializedParams = parts.join('&'); 59 | } 60 | 61 | if (serializedParams) { 62 | url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams; 63 | } 64 | 65 | return url; 66 | }; 67 | -------------------------------------------------------------------------------- /axios/helpers/combineURLs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Creates a new URL by combining the specified URLs 5 | * 6 | * @param {string} baseURL The base URL 7 | * @param {string} relativeURL The relative URL 8 | * @returns {string} The combined URL 9 | */ 10 | module.exports = function combineURLs(baseURL, relativeURL) { 11 | return relativeURL 12 | ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') 13 | : baseURL; 14 | }; 15 | -------------------------------------------------------------------------------- /axios/helpers/cookies.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | module.exports = ( 6 | utils.isStandardBrowserEnv() ? 7 | 8 | // Standard browser envs support document.cookie 9 | (function standardBrowserEnv() { 10 | return { 11 | write: function write(name, value, expires, path, domain, secure) { 12 | var cookie = []; 13 | cookie.push(name + '=' + encodeURIComponent(value)); 14 | 15 | if (utils.isNumber(expires)) { 16 | cookie.push('expires=' + new Date(expires).toGMTString()); 17 | } 18 | 19 | if (utils.isString(path)) { 20 | cookie.push('path=' + path); 21 | } 22 | 23 | if (utils.isString(domain)) { 24 | cookie.push('domain=' + domain); 25 | } 26 | 27 | if (secure === true) { 28 | cookie.push('secure'); 29 | } 30 | 31 | document.cookie = cookie.join('; '); 32 | }, 33 | 34 | read: function read(name) { 35 | var match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)')); 36 | return (match ? decodeURIComponent(match[3]) : null); 37 | }, 38 | 39 | remove: function remove(name) { 40 | this.write(name, '', Date.now() - 86400000); 41 | } 42 | }; 43 | })() : 44 | 45 | // Non standard browser env (web workers, react-native) lack needed support. 46 | (function nonStandardBrowserEnv() { 47 | return { 48 | write: function write() {}, 49 | read: function read() { return null; }, 50 | remove: function remove() {} 51 | }; 52 | })() 53 | ); 54 | -------------------------------------------------------------------------------- /axios/helpers/deprecatedMethod.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /*eslint no-console:0*/ 4 | 5 | /** 6 | * Supply a warning to the developer that a method they are using 7 | * has been deprecated. 8 | * 9 | * @param {string} method The name of the deprecated method 10 | * @param {string} [instead] The alternate method to use if applicable 11 | * @param {string} [docs] The documentation URL to get further details 12 | */ 13 | module.exports = function deprecatedMethod(method, instead, docs) { 14 | try { 15 | console.warn( 16 | 'DEPRECATED method `' + method + '`.' + 17 | (instead ? ' Use `' + instead + '` instead.' : '') + 18 | ' This method will be removed in a future release.'); 19 | 20 | if (docs) { 21 | console.warn('For more information about usage see ' + docs); 22 | } 23 | } catch (e) { /* Ignore */ } 24 | }; 25 | -------------------------------------------------------------------------------- /axios/helpers/isAbsoluteURL.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Determines whether the specified URL is absolute 5 | * 6 | * @param {string} url The URL to test 7 | * @returns {boolean} True if the specified URL is absolute, otherwise false 8 | */ 9 | module.exports = function isAbsoluteURL(url) { 10 | // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL). 11 | // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed 12 | // by any combination of letters, digits, plus, period, or hyphen. 13 | return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url); 14 | }; 15 | -------------------------------------------------------------------------------- /axios/helpers/isURLSameOrigin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | module.exports = ( 6 | utils.isStandardBrowserEnv() ? 7 | 8 | // Standard browser envs have full support of the APIs needed to test 9 | // whether the request URL is of the same origin as current location. 10 | (function standardBrowserEnv() { 11 | var msie = /(msie|trident)/i.test(navigator.userAgent); 12 | var urlParsingNode = document.createElement('a'); 13 | var originURL; 14 | 15 | /** 16 | * Parse a URL to discover it's components 17 | * 18 | * @param {String} url The URL to be parsed 19 | * @returns {Object} 20 | */ 21 | function resolveURL(url) { 22 | var href = url; 23 | 24 | if (msie) { 25 | // IE needs attribute set twice to normalize properties 26 | urlParsingNode.setAttribute('href', href); 27 | href = urlParsingNode.href; 28 | } 29 | 30 | urlParsingNode.setAttribute('href', href); 31 | 32 | // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils 33 | return { 34 | href: urlParsingNode.href, 35 | protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', 36 | host: urlParsingNode.host, 37 | search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', 38 | hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', 39 | hostname: urlParsingNode.hostname, 40 | port: urlParsingNode.port, 41 | pathname: (urlParsingNode.pathname.charAt(0) === '/') ? 42 | urlParsingNode.pathname : 43 | '/' + urlParsingNode.pathname 44 | }; 45 | } 46 | 47 | originURL = resolveURL(window.location.href); 48 | 49 | /** 50 | * Determine if a URL shares the same origin as the current location 51 | * 52 | * @param {String} requestURL The URL to test 53 | * @returns {boolean} True if URL shares the same origin, otherwise false 54 | */ 55 | return function isURLSameOrigin(requestURL) { 56 | var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL; 57 | return (parsed.protocol === originURL.protocol && 58 | parsed.host === originURL.host); 59 | }; 60 | })() : 61 | 62 | // Non standard browser envs (web workers, react-native) lack needed support. 63 | (function nonStandardBrowserEnv() { 64 | return function isURLSameOrigin() { 65 | return true; 66 | }; 67 | })() 68 | ); 69 | -------------------------------------------------------------------------------- /axios/helpers/normalizeHeaderName.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('../utils'); 4 | 5 | module.exports = function normalizeHeaderName(headers, normalizedName) { 6 | utils.forEach(headers, function processHeader(value, name) { 7 | if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) { 8 | headers[normalizedName] = value; 9 | delete headers[name]; 10 | } 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /axios/helpers/parseHeaders.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | // Headers whose duplicates are ignored by node 6 | // c.f. https://nodejs.org/api/http.html#http_message_headers 7 | var ignoreDuplicateOf = [ 8 | 'age', 'authorization', 'content-length', 'content-type', 'etag', 9 | 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since', 10 | 'last-modified', 'location', 'max-forwards', 'proxy-authorization', 11 | 'referer', 'retry-after', 'user-agent' 12 | ]; 13 | 14 | /** 15 | * Parse headers into an object 16 | * 17 | * ``` 18 | * Date: Wed, 27 Aug 2014 08:58:49 GMT 19 | * Content-Type: application/json 20 | * Connection: keep-alive 21 | * Transfer-Encoding: chunked 22 | * ``` 23 | * 24 | * @param {String} headers Headers needing to be parsed 25 | * @returns {Object} Headers parsed into an object 26 | */ 27 | module.exports = function parseHeaders(headers) { 28 | var parsed = {}; 29 | var key; 30 | var val; 31 | var i; 32 | 33 | if (!headers) { return parsed; } 34 | 35 | utils.forEach(headers.split('\n'), function parser(line) { 36 | i = line.indexOf(':'); 37 | key = utils.trim(line.substr(0, i)).toLowerCase(); 38 | val = utils.trim(line.substr(i + 1)); 39 | 40 | if (key) { 41 | if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) { 42 | return; 43 | } 44 | if (key === 'set-cookie') { 45 | parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]); 46 | } else { 47 | parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; 48 | } 49 | } 50 | }); 51 | 52 | return parsed; 53 | }; 54 | -------------------------------------------------------------------------------- /axios/helpers/spread.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Syntactic sugar for invoking a function and expanding an array for arguments. 5 | * 6 | * Common use case would be to use `Function.prototype.apply`. 7 | * 8 | * ```js 9 | * function f(x, y, z) {} 10 | * var args = [1, 2, 3]; 11 | * f.apply(null, args); 12 | * ``` 13 | * 14 | * With `spread` this example can be re-written. 15 | * 16 | * ```js 17 | * spread(function(x, y, z) {})([1, 2, 3]); 18 | * ``` 19 | * 20 | * @param {Function} callback 21 | * @returns {Function} 22 | */ 23 | module.exports = function spread(callback) { 24 | return function wrap(arr) { 25 | return callback.apply(null, arr); 26 | }; 27 | }; 28 | -------------------------------------------------------------------------------- /axios/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var bind = require('./helpers/bind'); 4 | var isBuffer = require('is-buffer'); 5 | 6 | /*global toString:true*/ 7 | 8 | // utils is a library of generic helper functions non-specific to axios 9 | 10 | var toString = Object.prototype.toString; 11 | 12 | /** 13 | * Determine if a value is an Array 14 | * 15 | * @param {Object} val The value to test 16 | * @returns {boolean} True if value is an Array, otherwise false 17 | */ 18 | function isArray(val) { 19 | return toString.call(val) === '[object Array]'; 20 | } 21 | 22 | /** 23 | * Determine if a value is an ArrayBuffer 24 | * 25 | * @param {Object} val The value to test 26 | * @returns {boolean} True if value is an ArrayBuffer, otherwise false 27 | */ 28 | function isArrayBuffer(val) { 29 | return toString.call(val) === '[object ArrayBuffer]'; 30 | } 31 | 32 | /** 33 | * Determine if a value is a FormData 34 | * 35 | * @param {Object} val The value to test 36 | * @returns {boolean} True if value is an FormData, otherwise false 37 | */ 38 | function isFormData(val) { 39 | return (typeof FormData !== 'undefined') && (val instanceof FormData); 40 | } 41 | 42 | /** 43 | * Determine if a value is a view on an ArrayBuffer 44 | * 45 | * @param {Object} val The value to test 46 | * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false 47 | */ 48 | function isArrayBufferView(val) { 49 | var result; 50 | if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) { 51 | result = ArrayBuffer.isView(val); 52 | } else { 53 | result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer); 54 | } 55 | return result; 56 | } 57 | 58 | /** 59 | * Determine if a value is a String 60 | * 61 | * @param {Object} val The value to test 62 | * @returns {boolean} True if value is a String, otherwise false 63 | */ 64 | function isString(val) { 65 | return typeof val === 'string'; 66 | } 67 | 68 | /** 69 | * Determine if a value is a Number 70 | * 71 | * @param {Object} val The value to test 72 | * @returns {boolean} True if value is a Number, otherwise false 73 | */ 74 | function isNumber(val) { 75 | return typeof val === 'number'; 76 | } 77 | 78 | /** 79 | * Determine if a value is undefined 80 | * 81 | * @param {Object} val The value to test 82 | * @returns {boolean} True if the value is undefined, otherwise false 83 | */ 84 | function isUndefined(val) { 85 | return typeof val === 'undefined'; 86 | } 87 | 88 | /** 89 | * Determine if a value is an Object 90 | * 91 | * @param {Object} val The value to test 92 | * @returns {boolean} True if value is an Object, otherwise false 93 | */ 94 | function isObject(val) { 95 | return val !== null && typeof val === 'object'; 96 | } 97 | 98 | /** 99 | * Determine if a value is a Date 100 | * 101 | * @param {Object} val The value to test 102 | * @returns {boolean} True if value is a Date, otherwise false 103 | */ 104 | function isDate(val) { 105 | return toString.call(val) === '[object Date]'; 106 | } 107 | 108 | /** 109 | * Determine if a value is a File 110 | * 111 | * @param {Object} val The value to test 112 | * @returns {boolean} True if value is a File, otherwise false 113 | */ 114 | function isFile(val) { 115 | return toString.call(val) === '[object File]'; 116 | } 117 | 118 | /** 119 | * Determine if a value is a Blob 120 | * 121 | * @param {Object} val The value to test 122 | * @returns {boolean} True if value is a Blob, otherwise false 123 | */ 124 | function isBlob(val) { 125 | return toString.call(val) === '[object Blob]'; 126 | } 127 | 128 | /** 129 | * Determine if a value is a Function 130 | * 131 | * @param {Object} val The value to test 132 | * @returns {boolean} True if value is a Function, otherwise false 133 | */ 134 | function isFunction(val) { 135 | return toString.call(val) === '[object Function]'; 136 | } 137 | 138 | /** 139 | * Determine if a value is a Stream 140 | * 141 | * @param {Object} val The value to test 142 | * @returns {boolean} True if value is a Stream, otherwise false 143 | */ 144 | function isStream(val) { 145 | return isObject(val) && isFunction(val.pipe); 146 | } 147 | 148 | /** 149 | * Determine if a value is a URLSearchParams object 150 | * 151 | * @param {Object} val The value to test 152 | * @returns {boolean} True if value is a URLSearchParams object, otherwise false 153 | */ 154 | function isURLSearchParams(val) { 155 | return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams; 156 | } 157 | 158 | /** 159 | * Trim excess whitespace off the beginning and end of a string 160 | * 161 | * @param {String} str The String to trim 162 | * @returns {String} The String freed of excess whitespace 163 | */ 164 | function trim(str) { 165 | return str.replace(/^\s*/, '').replace(/\s*$/, ''); 166 | } 167 | 168 | /** 169 | * Determine if we're running in a standard browser environment 170 | * 171 | * This allows axios to run in a web worker, and react-native. 172 | * Both environments support XMLHttpRequest, but not fully standard globals. 173 | * 174 | * web workers: 175 | * typeof window -> undefined 176 | * typeof document -> undefined 177 | * 178 | * react-native: 179 | * navigator.product -> 'ReactNative' 180 | * nativescript 181 | * navigator.product -> 'NativeScript' or 'NS' 182 | */ 183 | function isStandardBrowserEnv() { 184 | if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' || 185 | navigator.product === 'NativeScript' || 186 | navigator.product === 'NS')) { 187 | return false; 188 | } 189 | return ( 190 | typeof window !== 'undefined' && 191 | typeof document !== 'undefined' 192 | ); 193 | } 194 | 195 | /** 196 | * Iterate over an Array or an Object invoking a function for each item. 197 | * 198 | * If `obj` is an Array callback will be called passing 199 | * the value, index, and complete array for each item. 200 | * 201 | * If 'obj' is an Object callback will be called passing 202 | * the value, key, and complete object for each property. 203 | * 204 | * @param {Object|Array} obj The object to iterate 205 | * @param {Function} fn The callback to invoke for each item 206 | */ 207 | function forEach(obj, fn) { 208 | // Don't bother if no value provided 209 | if (obj === null || typeof obj === 'undefined') { 210 | return; 211 | } 212 | 213 | // Force an array if not already something iterable 214 | if (typeof obj !== 'object') { 215 | /*eslint no-param-reassign:0*/ 216 | obj = [obj]; 217 | } 218 | 219 | if (isArray(obj)) { 220 | // Iterate over array values 221 | for (var i = 0, l = obj.length; i < l; i++) { 222 | fn.call(null, obj[i], i, obj); 223 | } 224 | } else { 225 | // Iterate over object keys 226 | for (var key in obj) { 227 | if (Object.prototype.hasOwnProperty.call(obj, key)) { 228 | fn.call(null, obj[key], key, obj); 229 | } 230 | } 231 | } 232 | } 233 | 234 | /** 235 | * Accepts varargs expecting each argument to be an object, then 236 | * immutably merges the properties of each object and returns result. 237 | * 238 | * When multiple objects contain the same key the later object in 239 | * the arguments list will take precedence. 240 | * 241 | * Example: 242 | * 243 | * ```js 244 | * var result = merge({foo: 123}, {foo: 456}); 245 | * console.log(result.foo); // outputs 456 246 | * ``` 247 | * 248 | * @param {Object} obj1 Object to merge 249 | * @returns {Object} Result of all merge properties 250 | */ 251 | function merge(/* obj1, obj2, obj3, ... */) { 252 | var result = {}; 253 | function assignValue(val, key) { 254 | if (typeof result[key] === 'object' && typeof val === 'object') { 255 | result[key] = merge(result[key], val); 256 | } else { 257 | result[key] = val; 258 | } 259 | } 260 | 261 | for (var i = 0, l = arguments.length; i < l; i++) { 262 | forEach(arguments[i], assignValue); 263 | } 264 | return result; 265 | } 266 | 267 | /** 268 | * Function equal to merge with the difference being that no reference 269 | * to original objects is kept. 270 | * 271 | * @see merge 272 | * @param {Object} obj1 Object to merge 273 | * @returns {Object} Result of all merge properties 274 | */ 275 | function deepMerge(/* obj1, obj2, obj3, ... */) { 276 | var result = {}; 277 | function assignValue(val, key) { 278 | if (typeof result[key] === 'object' && typeof val === 'object') { 279 | result[key] = deepMerge(result[key], val); 280 | } else if (typeof val === 'object') { 281 | result[key] = deepMerge({}, val); 282 | } else { 283 | result[key] = val; 284 | } 285 | } 286 | 287 | for (var i = 0, l = arguments.length; i < l; i++) { 288 | forEach(arguments[i], assignValue); 289 | } 290 | return result; 291 | } 292 | 293 | /** 294 | * Extends object a by mutably adding to it the properties of object b. 295 | * 296 | * @param {Object} a The object to be extended 297 | * @param {Object} b The object to copy properties from 298 | * @param {Object} thisArg The object to bind function to 299 | * @return {Object} The resulting value of object a 300 | */ 301 | function extend(a, b, thisArg) { 302 | forEach(b, function assignValue(val, key) { 303 | if (thisArg && typeof val === 'function') { 304 | a[key] = bind(val, thisArg); 305 | } else { 306 | a[key] = val; 307 | } 308 | }); 309 | return a; 310 | } 311 | 312 | module.exports = { 313 | isArray: isArray, 314 | isArrayBuffer: isArrayBuffer, 315 | isBuffer: isBuffer, 316 | isFormData: isFormData, 317 | isArrayBufferView: isArrayBufferView, 318 | isString: isString, 319 | isNumber: isNumber, 320 | isObject: isObject, 321 | isUndefined: isUndefined, 322 | isDate: isDate, 323 | isFile: isFile, 324 | isBlob: isBlob, 325 | isFunction: isFunction, 326 | isStream: isStream, 327 | isURLSearchParams: isURLSearchParams, 328 | isStandardBrowserEnv: isStandardBrowserEnv, 329 | forEach: forEach, 330 | merge: merge, 331 | deepMerge: deepMerge, 332 | extend: extend, 333 | trim: trim 334 | }; 335 | -------------------------------------------------------------------------------- /layer/layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layer/layer.png -------------------------------------------------------------------------------- /layerMobile/layer.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layerMobile/layer.js -------------------------------------------------------------------------------- /layui/demo/streamLoading/css/streamLoading.css: -------------------------------------------------------------------------------- 1 | @charset 'utf-8'; 2 | * { 3 | padding: 0; 4 | margin: 0; 5 | } 6 | 7 | #streaming-loading { 8 | position: absolute; 9 | top: 50%; 10 | left: 50%; 11 | width: 800px; 12 | height: 600px; 13 | margin: -300px 0 0 -400px; 14 | border: 1px solid #ddd; 15 | box-shadow: 0 0 2px rgba(0, 0, 0, .5); 16 | overflow: auto; 17 | } 18 | 19 | #streaming-loading span.loading { 20 | display: block; 21 | width: 100%; 22 | height: 60px; 23 | text-align: center; 24 | color: rgba(0, 0, 0, .6); 25 | } 26 | 27 | #streaming-loading span.loading .loading-icon { 28 | font-size: 25px; 29 | } 30 | 31 | #streaming-loading span.loading .sl-button { 32 | width: 80px; 33 | height: 40px; 34 | background: #fff; 35 | border: 1px solid rgba(0, 0, 0, .3); 36 | cursor: pointer; 37 | outline: none; 38 | } 39 | #streaming-loading span.loading .sl-button:active { 40 | background: rgba(0, 0, 0, .1); 41 | } 42 | 43 | #streaming-loading figure { 44 | display: inline-block; 45 | height: 200px; 46 | margin: 6px; 47 | } 48 | 49 | #streaming-loading figure img { 50 | width: 100%; 51 | height: 100%; 52 | } 53 | -------------------------------------------------------------------------------- /layui/demo/streamLoading/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/streamLoading/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /layui/demo/streamLoading/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/streamLoading/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /layui/demo/streamLoading/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/streamLoading/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /layui/demo/streamLoading/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/streamLoading/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /layui/demo/streamLoading/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/streamLoading/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /layui/demo/streamLoading/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 流加载 8 | 9 | 10 | 11 | 12 |
13 |
14 | 15 | 36 | 37 | -------------------------------------------------------------------------------- /layui/demo/streamLoading/js/streamLoading.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 流加载 3 | * quyinggang 4 | * 2017-08-03 09:34 5 | */ 6 | 7 | (function(window, undefined) { 8 | // column: 内容区共分为几列展示,images:数据,type:加载类型, isAuto:是否自动滚动 9 | let doc = document, 10 | utils = {}, 11 | config = { 12 | column: 3, 13 | images: [], 14 | type: 'iconAuto', 15 | isAuto: true 16 | }; 17 | 18 | // 配置参数合并 19 | utils.extend = function(config, options) { 20 | let extend = {}; 21 | let keys = []; 22 | config = config || {}; 23 | options = options || {}; 24 | keys = Object.keys(config); 25 | if (!options) return config; 26 | keys.forEach(function(item, index) { 27 | extend[item] = item && item in options ? options[item] : config[item]; 28 | }); 29 | return extend; 30 | }; 31 | 32 | // 获取元素DOM节点 33 | utils.getElement = function(type, targetName) { 34 | if (!type || !targetName) return; 35 | return doc[type](targetName); 36 | }; 37 | 38 | // 动态计算每列元素的宽度 39 | utils.setFigureWidth = function(scrollWidth, clientWidth, settings) { 40 | let columnWidth = 0; 41 | scrollWidth = 0 || scrollWidth || parseFloat(scrollWidth); 42 | if (settings.column > 0) { 43 | let column = parseInt(settings.column); 44 | columnWidth = Math.floor((clientWidth - column * 12 - scrollWidth) / column); 45 | } 46 | return columnWidth; 47 | }; 48 | 49 | // 图标区域的外部容器的创建 50 | utils.createLoadingContainer = function(streamLoading) { 51 | if (!streamLoading || !streamLoading.nodeName) return; 52 | let container = utils.getElement('getElementsByClassName', 'loading'), 53 | node = null; 54 | if (container.length === 0) { 55 | let span = doc.createElement('span'); 56 | span.className = 'loading'; 57 | streamLoading.appendChild(span); 58 | node = span; 59 | } 60 | return node; 61 | }; 62 | 63 | // 添加figure元素并设置其样式等 64 | utils.setFigure = function(options) { 65 | let FIGURE = 'figure', 66 | IMG = 'img', 67 | tagName = 'getElementsByTagName', 68 | { streamLoading: streamLoading, settings: settings, start: start, end: end } = options, 69 | clientWidth = streamLoading.clientWidth, 70 | columnWidth = utils.setFigureWidth(0, clientWidth, settings); 71 | 72 | // 动态添加元素 73 | for (let index = start; index < end; index++) { 74 | let item = settings.images[index]; 75 | let figure = doc.createElement(FIGURE); 76 | let img = doc.createElement(IMG); 77 | if (item) { 78 | img.src = item; 79 | } 80 | img.alt = index + 1; 81 | figure.style.width = columnWidth + 'px'; 82 | figure.appendChild(img); 83 | streamLoading.appendChild(figure); 84 | } 85 | // 获取滚动条宽度重新设置figure的宽度 86 | let nowClientWidth = streamLoading.clientWidth; 87 | if (nowClientWidth <= clientWidth) { 88 | cWidth = nowClientWidth < clientWidth ? clientWidth : nowClientWidth; 89 | let figures = utils.getElement(tagName, FIGURE); 90 | for (let i = start; i < end; i++) { 91 | let figure = figures[i]; 92 | if (figure) { 93 | figure.style.width = utils.setFigureWidth(clientWidth - nowClientWidth, cWidth, settings) + 'px'; 94 | } 95 | } 96 | } 97 | }; 98 | 99 | // 加载图标创建以及回调函数的指定 100 | var createIcon = function(streamLoading, container, callback) { 101 | let icon = doc.createElement('i'); 102 | icon.className = 'fa fa-spinner fa-pulse loading-icon'; 103 | container.appendChild(icon); 104 | setTimeout(function() { 105 | streamLoading.removeChild(container); 106 | typeof callback === 'function' ? callback() : ''; 107 | }, 2000); 108 | }; 109 | // 定义二种加载方式 110 | /** 111 | * 第一种: 带图标自动加载 112 | * 第二种: 手动点击加载 113 | */ 114 | // 加载图标构建 115 | utils.addLoading = function(options) { 116 | let [streamLoading, isDown, callback, type, isOver] = options; 117 | let container = utils.createLoadingContainer(streamLoading); 118 | if (!container) return; 119 | if (isDown && !isOver) { 120 | switch (type) { 121 | case 'iconAuto': 122 | createIcon(streamLoading, container, callback); 123 | break; 124 | case 'click': 125 | (function() { 126 | let button = doc.createElement('button'); 127 | button.className = 'sl-button'; 128 | button.innerText = '点击加载'; 129 | container.appendChild(button); 130 | button.addEventListener('click', function() { 131 | container.removeChild(button); 132 | createIcon(streamLoading, container, callback); 133 | }); 134 | })(); 135 | } 136 | } else if (isOver) { 137 | container.appendChild(doc.createTextNode('没有多余的数据了')); 138 | } 139 | }; 140 | 141 | // 加载内容区数据 142 | utils.autoLoad = function(streamLoading, settings, start, end) { 143 | let parames = { 144 | streamLoading: streamLoading, 145 | settings: settings, 146 | start: start, 147 | end: end 148 | }; 149 | utils.setFigure(parames); 150 | }; 151 | 152 | // 构造函数 153 | let SLoading = function(options) { 154 | this.options = utils.extend(config, options); 155 | }; 156 | 157 | // 原型对象 158 | SLoading.fn = SLoading.prototype; 159 | 160 | // 配置参数合并对外API 161 | SLoading.fn.set = function(options) { 162 | this.options = utils.extend(config, options); 163 | }; 164 | 165 | // 开始执行流加载程序,绑定相关事件 166 | SLoading.fn.start = function(id) { 167 | let streamLoading = utils.getElement('getElementById', id), 168 | settings = this.options, 169 | column = settings.column, 170 | initCount = column * 2, 171 | length = settings.images.length, 172 | end = length, 173 | clientHeight = streamLoading.clientHeight, 174 | record = [0], 175 | timer = null; 176 | if (settings.images) { 177 | // 初始化时加载initCount条数据, 178 | initCount = initCount > length ? length : 179 | ((clientHeight - 200 * 2 + 18) >= 0 ? initCount + column : initCount); 180 | utils.autoLoad(streamLoading, settings, 0, initCount); 181 | } 182 | // 处理自动滚动 183 | if (settings.isAuto) { 184 | setInterval(function() { 185 | streamLoading.scrollTop += 1; 186 | settings.type = 'auto'; 187 | }, 1000 / 60); 188 | } 189 | 190 | // 对内容区进行scroll事件监听 191 | streamLoading.addEventListener('scroll', function() { 192 | // 获取scrollTop、scrollHeight等 193 | let scrollTop = this.scrollTop, 194 | scrollHeight = this.scrollHeight; 195 | clientHeight = this.clientHeight, currentScrollPosition = clientHeight + scrollTop, 196 | figures = utils.getElement('getElementsByTagName', 'figure'), figuresLength = figures.length, 197 | compareTarget = record[record.length - 1]; 198 | 199 | // 为了处理向上滚动带来的重复加载的问题 200 | if (scrollTop > compareTarget) { 201 | record.shift(); 202 | record.push(scrollTop); 203 | } 204 | // 每次向下滚动需要加载的数据的结束下标, 在数据范围内, 每次加载2 * column条 205 | let end = figuresLength + column * 2 < length ? figuresLength + column * 2 : length; 206 | // 判断滚动到底部:scrollTop + clientHeigt === scrollHeight, 并且还有数据需要加载 207 | if (currentScrollPosition === scrollHeight && end <= length) { 208 | let callback = function() { 209 | utils.autoLoad(streamLoading, settings, figuresLength, end); 210 | }, 211 | isOver = figures.length >= length ? true : false, 212 | isDown = scrollTop >= record[0] ? true : false; 213 | utils.addLoading([this, isDown, callback, settings.type, isOver]); 214 | } 215 | }); 216 | }; 217 | 218 | window.StreamingLoading = SLoading; 219 | })(window); -------------------------------------------------------------------------------- /layui/demo/streamLoading/lazyLoading.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 图片懒加载 8 | 35 | 36 | 37 |
38 |
image
39 |
image
40 |
image
41 |
image
42 |
image
43 |
image
44 |
image
45 |
image
46 |
image
47 |
image
48 |
image
49 |
image
50 |
image
51 |
image
52 |
image
53 |
image
54 |
image
55 |
image
56 |
image
57 |
image
58 |
59 | 122 | 123 | -------------------------------------------------------------------------------- /layui/demo/template/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 模板引擎 8 | 9 | 10 |
11 | 16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /layui/demo/template/js/template.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 模板引擎和指令 3 | * 玉案轩窗 4 | * 2017-08-08 10:16 5 | */ 6 | (function(window, undefined) { 7 | let doc = document, directives = ['v-if', 'v-for', 'v-text'], 8 | templateRegex = /{{.+}}/g, data = { 9 | isShow: true, 10 | message: '模板引擎', 11 | data: [ 12 | '数据1', '数据2' 13 | ] 14 | }; 15 | 16 | let searchTemplateAndDire = function(childNodes, data) { 17 | if (!childNodes) return; 18 | for (let index = 0; index < childNodes.length; index++) { 19 | let childNode = childNodes[index]; 20 | if (childNode.nodeName != 'SCRIPT' && childNode.nodeType === 1) { 21 | searchTemplateAndDire(childNode.childNodes, data); 22 | // 元素节点 23 | if (childNode.nodeType === 1) { 24 | if (childNode.hasAttribute('v-if')) { 25 | // 处理v-if指令, 支持单运算符! 26 | let isShow = false, content = '', 27 | value = childNode.getAttribute('v-if'); 28 | if (value && value.indexOf('!') >= 0) { 29 | values = value.substring(value.indexOf('!')); 30 | } else { 31 | values = value; 32 | } 33 | if (data.hasOwnProperty(values)) { 34 | isShow = data[values]; 35 | } 36 | isShow ? '' : childNode.style.display = 'none'; 37 | childNode.removeAttribute('v-if'); 38 | } else if (childNode.hasAttribute('v-text')) { 39 | // 处理指令v-text 40 | let value = childNode.getAttribute('v-text'), text = value; 41 | if (value && data.hasOwnProperty(value)) { 42 | text = data[value]; 43 | } 44 | childNode.innerText = text; 45 | childNode.removeAttribute('v-text'); 46 | } 47 | } 48 | } else if (childNode.nodeType === 3) { 49 | let text = childNode.textContent; 50 | if (templateRegex.test(text)) { 51 | let value = text.replace(/{{|}}/g, ''); 52 | if (value && data.hasOwnProperty(value)) { 53 | childNode.textContent = data[value]; 54 | } 55 | } 56 | } 57 | } 58 | } 59 | searchTemplateAndDire(document.body.childNodes, data); 60 | })(window); -------------------------------------------------------------------------------- /layui/demo/tree/css/tree.css: -------------------------------------------------------------------------------- 1 | @charset 'utf-8'; 2 | * { 3 | padding: 0; 4 | margin: 0; 5 | } 6 | 7 | html, body { 8 | width: 100%; 9 | height: 100%; 10 | } 11 | 12 | 13 | #tree { 14 | display: inline-block; 15 | width: 220px; 16 | height: 100%; 17 | background: #fff; 18 | } 19 | 20 | #tree ul { 21 | width: 100%; 22 | font-size: 14px; 23 | list-style: none; 24 | box-sizing: border-box; 25 | } 26 | 27 | #tree ul ul { 28 | display: none; 29 | height: 0; 30 | padding: 0 0 0 2em; 31 | box-sizing: border-box; 32 | transition: all .3s ease-in-out; 33 | } 34 | 35 | #tree > ul li { 36 | width: 100%; 37 | height: 30px; 38 | line-height: 30px; 39 | padding: 0 0 0 2em; 40 | box-sizing: border-box; 41 | cursor: pointer; 42 | } 43 | 44 | #tree ul ul.show { 45 | display: inline-block; 46 | height: 100%; 47 | } 48 | 49 | #tree .active { 50 | background: #e4e8f1; 51 | } 52 | 53 | #tree ul li i, #tree ul li span { 54 | display: inline-block; 55 | text-align: left; 56 | } 57 | #tree ul li span { 58 | width: 90%; 59 | } 60 | 61 | #tree ul li i { 62 | width: 10%; 63 | height: 30px; 64 | line-height: 30px; 65 | font-size: 12px; 66 | color: #97A8BE; 67 | } 68 | 69 | #tree > ul li i { 70 | transform: rotate(0deg); 71 | transform-origin: 25% center; 72 | transition: transform .3s ease-in-out; 73 | } 74 | 75 | #tree > ul li .rotate { 76 | transform: rotate(90deg); 77 | } -------------------------------------------------------------------------------- /layui/demo/tree/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/tree/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /layui/demo/tree/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/tree/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /layui/demo/tree/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/tree/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /layui/demo/tree/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/tree/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /layui/demo/tree/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/tree/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /layui/demo/tree/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 树状菜单 8 | 9 | 10 | 11 | 12 |
13 | 14 | 54 | 55 | -------------------------------------------------------------------------------- /layui/demo/tree/js/tree.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 树形菜单 3 | * 玉案轩窗 4 | * 2017-08-09 11:11 5 | */ 6 | !(function(window, undefined) { 7 | let doc = document, tool = {}, SHOW = 'show', ACTIVE = 'active', ROTATE = 'rotate'; 8 | 9 | // 构建菜单html结构(子菜单不在父菜单中) 10 | tool.menuView = function(parentNode, menu) { 11 | if (!parentNode || parentNode.nodeType !== 1 || !Array.isArray(menu)) return; 12 | for (let i = 0; i < menu.length; i++) { 13 | let option = menu[i], name = option.name; 14 | if (option.children && option.children.length > 0) { 15 | let ulNode = tool.createElement('ul'); 16 | tool.menuView(ulNode, option.children); 17 | let [menuNode, iNode, spanNode] = tool.createElement(['li', 'i', 'span']) 18 | spanNode.innerText = name; 19 | iNode.className = 'fa fa-play'; 20 | tool.append([menuNode, parentNode], [[iNode, spanNode], [menuNode, ulNode]]); 21 | } else { 22 | let menuNode = tool.createElement('li'); 23 | menuNode.innerText = name; 24 | tool.append(parentNode, menuNode); 25 | } 26 | } 27 | }; 28 | 29 | // 将ul构建在父菜单li中 30 | // tool.menuView = function(parentNode, menu) { 31 | // if (!parentNode || parentNode.nodeType !== 1 || !Array.isArray(menu)) return; 32 | // for (let i = 0; i < menu.length; i++) { 33 | // let option = menu[i], name = option.name, liNode = tool.createElement('li'); 34 | // tool.append(parentNode, liNode); 35 | // if (option.children && option.children.length > 0) { 36 | // let ulNode = tool.createElement('ul'); 37 | // tool.menuView(ulNode, option.children); 38 | // let [iNode, spanNode] = tool.createElement(['i', 'span']) 39 | // spanNode.innerText = name; 40 | // iNode.className = 'fa fa-play'; 41 | // tool.append([liNode, parentNode, liNode], [[iNode, spanNode], [liNode], [ulNode]]); 42 | // } else { 43 | // liNode.innerText = name; 44 | // } 45 | // } 46 | // }; 47 | 48 | // 清除所有菜单的active类 49 | tool.clearActive = function(boot) { 50 | if (!boot || boot.nodeType !== 1) return; 51 | let children = boot.children; 52 | if (children && children.length > 0) { 53 | for (let index = 0; index < children.length; index++) { 54 | tool.clearActive(children[index]); 55 | } 56 | } else { 57 | if (String(boot.className).indexOf(ACTIVE) >= 0) { 58 | boot.className = (boot.className.replace(new RegExp(ACTIVE, 'g'), '')).trim(); 59 | } 60 | } 61 | 62 | }; 63 | 64 | // 遍历 65 | tool.each = function(arr, callback, options) { 66 | if (!Array.isArray(arr) || typeof callback !== 'function') return; 67 | arr.forEach(function(elem, index) { 68 | callback(elem, index, options); 69 | }); 70 | }; 71 | 72 | // 创建节点,支持批量 73 | tool.createElement = function(nodeNames) { 74 | if (!nodeNames) return; 75 | let nodes = []; 76 | if (Array.isArray(nodeNames)) { 77 | tool.each(nodeNames, function(nodeName, index, options) { 78 | options.nodes.push(doc.createElement(nodeName)); 79 | }, {nodes: nodes}); 80 | } else { 81 | nodes = doc.createElement(nodeNames); 82 | } 83 | return nodes; 84 | }; 85 | 86 | // 添加节点,支持批量 87 | tool.append = function(parentNodes, childNodes) { 88 | if (!parentNodes || !childNodes) return; 89 | let isArrayOfP = Array.isArray(parentNodes), isArrayOfC = Array.isArray(childNodes); 90 | if (isArrayOfP && isArrayOfC) { 91 | tool.each(parentNodes, function(node, index, options) { 92 | let child = options.childNodes[index]; 93 | if (Array.isArray(child)) { 94 | child.forEach(function(children) { 95 | node.appendChild(children); 96 | }); 97 | } else { 98 | node.appendChild(child); 99 | } 100 | }, {childNodes: childNodes}); 101 | } else if (isArrayOfP && !isArrayOfC) { 102 | tool.each(parentNodes, function(node, index, options) { 103 | node.appendChild(options.childNodes); 104 | }, {childNodes: childNodes}); 105 | } else if (!isArrayOfP && isArrayOfC) { 106 | tool.each(childNodes, function(node, index, options) { 107 | let parentNode = options.parentNodes; 108 | if (Array.isArray(node)) { 109 | node.forEach(function(child) { 110 | parentNode.appendChild(child); 111 | }); 112 | } else { 113 | parentNode.appendChild(node); 114 | } 115 | }, {parentNodes: parentNodes}) 116 | } else if (!isArrayOfP && !isArrayOfC) { 117 | parentNodes.appendChild(childNodes); 118 | } 119 | }; 120 | // 事件绑定 121 | tool.onEvents = function(boot) { 122 | if (!boot || boot.nodeType !== 1) return; 123 | boot.addEventListener('click', function(e) { 124 | let currentNode = e.target || e.srcElement; 125 | if (currentNode.nodeName.toLowerCase() !== 'li') currentNode = currentNode.parentNode; 126 | // 获取当前点击列的下一个兄弟元素是否是ul,判断会否是菜单有层次结构 127 | let traggleNode = currentNode.nextSibling, isLevelsMenu = traggleNode ? (traggleNode.nodeName.toLowerCase() 128 | === 'ul' ? true : false) : false; 129 | if (isLevelsMenu) { 130 | let iNode = currentNode.firstChild, tClassName = traggleNode.className, 131 | iClassName = iNode.className; 132 | if (tClassName.indexOf(SHOW) >= 0) { 133 | iNode.className = (iClassName.replace(new RegExp(ROTATE, 'g'), '')).trim(); 134 | traggleNode.className = tClassName.replace(new RegExp(SHOW, 'g'), '').trim(); 135 | } else { 136 | iNode.className = (iClassName + ' ' + ROTATE).trim(); 137 | traggleNode.className = (tClassName + ' ' + SHOW).trim(); 138 | } 139 | 140 | } else { 141 | tool.clearActive(boot); 142 | currentNode.className = (currentNode.className + ' ' + ACTIVE).trim(); 143 | } 144 | console.log(currentNode.innerText); 145 | }); 146 | }; 147 | // 创建菜单结构并绑定事件 148 | tool.createMenu = function(data, id) { 149 | if (!data || !id) return; 150 | let ulNode = doc.createElement('ul'), containerNode = doc.getElementById(id); 151 | // 构建菜单结构 152 | tool.menuView(ulNode, data); 153 | containerNode && containerNode.nodeType === 1 ? containerNode.appendChild(ulNode) : ''; 154 | // 绑定点击事件 155 | tool.onEvents(ulNode); 156 | }; 157 | 158 | let Tree = function(data, id) { 159 | tool.createMenu(data, id); 160 | }; 161 | window.Tree = Tree; 162 | })(window); -------------------------------------------------------------------------------- /layui/demo/ueditor/css/ueditor.css: -------------------------------------------------------------------------------- 1 | @charset 'utf-8'; 2 | * { 3 | padding: 0; 4 | height: 0; 5 | } 6 | 7 | .ueditor-bold { 8 | font-weight: bold; 9 | } 10 | 11 | .ueditor-italic { 12 | font-style: italic; 13 | } 14 | 15 | .ueditor-left, .ueditor-right { 16 | display: inline-block; 17 | width: calc(100% - 2.5em); 18 | } 19 | 20 | .ueditor-left { 21 | text-align: left; 22 | } 23 | 24 | .ueditor-center { 25 | display: inline-block; 26 | width: calc(100% - 6em); 27 | text-align: center; 28 | } 29 | 30 | .ueditor-right { 31 | text-align: right; 32 | } 33 | 34 | .ueditor-hide { 35 | display: none; 36 | } 37 | 38 | .ueditor-show { 39 | display: block; 40 | } 41 | .ueditor-shadow { 42 | position: absolute; 43 | top: 0; 44 | left: 0; 45 | width: 100%; 46 | height: 100%; 47 | background: rgba(0, 0, 0, .6); 48 | z-index: 100; 49 | } 50 | .ueditor-toolsbar_link { 51 | position: absolute; 52 | top: 50%; 53 | left: 50%; 54 | width: 600px; 55 | height: 180px; 56 | margin: -60px 0 0 -300px; 57 | background: #fff; 58 | box-shadow: 0 0 1px rgba(0, 0, 0, .5); 59 | z-index: 1998; 60 | transition: display 1s ease; 61 | } 62 | 63 | .ueditor-toolsbar_link .toolsbar_link_title { 64 | height: 30px; 65 | line-height: 30px; 66 | padding: 0; 67 | margin: 0; 68 | text-indent: 2em; 69 | } 70 | 71 | .ueditor-toolsbar_link .toolsbar_link_content { 72 | display: table-cell; 73 | height: 120px; 74 | vertical-align: middle; 75 | } 76 | 77 | .ueditor-toolsbar_link .toolsbar_link_content label { 78 | display: inline-block; 79 | width: 100px; 80 | height: 24px; 81 | line-height: 24px; 82 | padding: 0 10px 0 2em; 83 | text-align: right; 84 | } 85 | 86 | .ueditor-toolsbar_link .toolsbar_link_content input{ 87 | width: 400px; 88 | height: 20px; 89 | margin: 10px 0; 90 | } 91 | 92 | .ueditor-toolsbar_link .toolsbar_link_buttons i { 93 | float: right; 94 | width: 20px; 95 | height: 30px; 96 | line-height: 30px; 97 | font-size: 1.2em; 98 | margin: 0 20px; 99 | color: rgba(49, 126, 243, 1); 100 | cursor: pointer; 101 | } 102 | 103 | .ueditor-toolsbar_link .toolsbar_link_buttons i:hover { 104 | opacity: .8; 105 | } 106 | 107 | .ueditor-toolsbar_gif { 108 | position: absolute; 109 | top: 38px; 110 | right: 0; 111 | width: 360px; 112 | height: 200px; 113 | padding: 5px; 114 | text-align: left; 115 | border: 1px solid #ccc; 116 | box-shadow: 0 0 2px rgba(0, 0, 0, .5); 117 | background: #fff; 118 | z-index: 2000; 119 | } 120 | 121 | .ueditor-toolsbar_gif div { 122 | display: inline-block; 123 | width: 25px; 124 | height: 25px; 125 | text-align: center; 126 | line-height: 25px; 127 | margin: 2px; 128 | cursor: pointer; 129 | } 130 | 131 | .ueditor-toolsbar_gif div img { 132 | width: 22px; 133 | height: 22px; 134 | } 135 | 136 | .ueditor-toolsbar_gif div:hover { 137 | background: rgba(169, 169, 169, .5); 138 | } 139 | 140 | #ueditor { 141 | position: absolute; 142 | top: 50%; 143 | left: 50%; 144 | width: 560px; 145 | height: 400px; 146 | margin: -200px 0 0 -280px; 147 | border: 1px solid rgba(169, 169, 169, 1); 148 | } 149 | 150 | #ueditor .ueditor-toolsbar { 151 | width: 100%; 152 | height: 30px; 153 | border-bottom: 1px solid rgba(169, 169, 169, 1); 154 | } 155 | 156 | #ueditor .ueditor-toolsbar span { 157 | position: relative; 158 | display: inline-block; 159 | width: 80px; 160 | height: 30px; 161 | line-height: 30px; 162 | text-align: center; 163 | } 164 | 165 | #ueditor .ueditor-toolsbar span i { 166 | opacity: .5; 167 | cursor: pointer; 168 | } 169 | #ueditor .ueditor-toolsbar span:hover i { 170 | opacity: 1; 171 | } 172 | 173 | #ueditor .ueditor-content { 174 | width: 100%; 175 | height: 341px; 176 | font: normal normal 14px sans-serif; 177 | padding: 1em 0; 178 | text-indent: 2em; 179 | border: none; 180 | outline: none; 181 | vertical-align: middle; 182 | } 183 | 184 | #ueditor .ueditor-content img { 185 | position: relative; 186 | width: 22px; 187 | height: 22px; 188 | } 189 | 190 | #ueditor .ueditor-content a { 191 | color: rgba(48, 167, 226, .6); 192 | text-decoration: none; 193 | cursor: pointer; 194 | } 195 | 196 | #ueditor .ueditor-content a:hover { 197 | color: rgba(48, 167, 226, 1); 198 | } 199 | 200 | 201 | 202 | -------------------------------------------------------------------------------- /layui/demo/ueditor/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /layui/demo/ueditor/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /layui/demo/ueditor/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /layui/demo/ueditor/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /layui/demo/ueditor/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/0.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/1.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/10.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/10.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/11.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/11.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/12.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/12.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/13.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/13.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/14.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/14.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/15.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/15.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/16.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/17.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/17.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/18.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/18.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/19.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/19.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/2.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/20.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/20.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/21.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/21.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/22.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/22.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/23.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/23.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/24.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/24.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/25.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/25.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/26.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/26.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/27.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/27.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/28.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/28.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/29.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/29.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/3.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/30.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/30.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/31.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/31.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/32.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/32.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/33.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/33.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/34.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/34.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/35.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/35.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/36.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/36.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/37.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/37.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/38.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/38.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/39.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/39.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/4.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/40.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/40.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/41.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/41.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/42.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/42.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/43.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/43.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/44.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/44.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/45.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/45.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/46.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/46.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/47.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/47.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/48.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/48.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/49.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/49.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/5.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/50.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/50.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/51.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/51.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/52.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/52.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/53.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/53.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/54.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/54.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/55.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/55.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/56.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/56.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/57.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/57.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/58.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/58.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/59.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/59.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/6.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/60.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/60.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/61.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/61.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/62.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/62.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/63.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/63.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/64.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/64.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/65.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/65.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/66.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/66.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/67.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/67.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/68.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/68.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/69.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/69.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/7.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/7.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/70.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/70.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/71.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/71.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/8.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/8.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/images/face/9.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/demo/ueditor/images/face/9.gif -------------------------------------------------------------------------------- /layui/demo/ueditor/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 富文本编辑器 8 | 9 | 10 | 11 | 12 |
13 |
14 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /layui/demo/upload/css/upload.css: -------------------------------------------------------------------------------- 1 | @charset 'utf-8'; 2 | 3 | .layui-upload { 4 | display: inline-block; 5 | width: 111px; 6 | height: 36px; 7 | border: 1px solid #DFDFDF; 8 | font-size: 14px; 9 | background: #fff; 10 | color: #000; 11 | cursor: pointer; 12 | } 13 | 14 | .layui-upload:visited { 15 | border: 1px solid #ddd; 16 | } 17 | .layui-hide { 18 | display: none; 19 | } 20 | -------------------------------------------------------------------------------- /layui/demo/upload/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 文件上传 8 | 9 | 10 | 11 | 12 | 13 | 14 | 21 | 22 | -------------------------------------------------------------------------------- /layui/demo/upload/js/upload.js: -------------------------------------------------------------------------------- 1 | /** 2 | * upload.js 3 | * @author: quyinggang 4 | */ 5 | 6 | (function(w) { 7 | // 保存常用变量、定义内置配置参数对象 8 | var doc = document, call = {}, HIDE = 'layui-hide', 9 | UPLOAD = 'layui-upload-file', config = { 10 | element: 'upload', 11 | url: '', 12 | method: 'post', 13 | before: function() { 14 | console.log('开始上传...'); 15 | }, 16 | success: function() { 17 | console.log('上传成功'); 18 | }, 19 | error: function() { 20 | console.log('上传失败'); 21 | }, 22 | isChange: true 23 | }; 24 | 25 | // 配置参数合并 26 | call.extend = function(config, options) { 27 | var extend = {}; 28 | var keys = []; 29 | config = config || {}; 30 | options = options || {}; 31 | keys = Object.keys(config); 32 | if (!options) return config; 33 | keys.forEach(function(item, index) { 34 | extend[item] = item && item in options ? options[item] : config[item]; 35 | }); 36 | return extend; 37 | }; 38 | 39 | // 事件监听 40 | call.on = function(element, event, callback) { 41 | if(!element) return; 42 | typeof callback === 'function' || (callback = this.options.success); 43 | w.addEventListener ? element.addEventListener(event, callback) : element.attachEvent(event, callback); 44 | }; 45 | 46 | // 添加class类 47 | call.addClass = function(element, className) { 48 | // 判断指定元素是否存在,不存在就添加 49 | Sting(element.className).lastIndexOf(className) < 0 ? element.className += className : ''; 50 | }; 51 | 52 | // 根据参数来配置是否改变上传按钮的样式以及上传需要的表单(通过表单实现上传) 53 | call.view = function(options) { 54 | // 根据配置参数isChange来设置按钮的样式 55 | var element = doc.getElementsByTagName(options.element)[0]; 56 | element ? (options.isChange ? call.addClass(element, UPLOAD) : '') : (function() { 57 | var input = doc.createElement('input'); 58 | input.type = 'file'; 59 | input.id = 'file'; 60 | input.className = 'upload layui-hide'; 61 | input.name = 'file'; 62 | doc.body.appendChild(input); 63 | element = input; 64 | })(); 65 | 66 | // 创建iframe用于表单提交后无刷新页面 67 | var iframe = doc.createElement('iframe'); 68 | iframe.name = 'data'; 69 | iframe.className = ''; 70 | iframe.id = 'myFrame'; 71 | doc.body.appendChild(iframe); 72 | 73 | // 创建form表单用于提交(也可以采用ajax来实现上传) 74 | var form = doc.getElementById('upload'); 75 | if (!form) { 76 | var form = doc.createElement('form'); 77 | form.method = options.method; 78 | form.action = options.url; 79 | form.enctype = 'multipart/form-data'; 80 | form.id = 'upload'; 81 | form.className = 'layui-hide'; 82 | doc.body.appendChild(form); 83 | } else { 84 | form.method = options.method; 85 | form.action = options.url; 86 | } 87 | 88 | // 设置form的target属性值 89 | form.target = iframe.name; 90 | // 设置input的所属form 91 | element.form = 'upload'; 92 | }; 93 | 94 | // 定义构造函数 95 | var Upload = function(options) { 96 | // 参数合并 97 | this.options = call.extend(config, options); 98 | // 构建上传需要的form表单 99 | call.view(this.options); 100 | }; 101 | 102 | // 将构造函数的原型对象保存在fn属性中 103 | Upload.fn = Upload.prototype; 104 | 105 | // 上传,并且依据配置参数来进行上传前以及上传后的处理配置 106 | Upload.fn.Upload = function() { 107 | this.options.before(); 108 | var element = doc.getElementsByClassName(this.options.element)[0]; 109 | call.on(element, 'click', function() { 110 | var input = doc.getElementsByClassName('upload')[0]; 111 | input.click(); 112 | call.on(input, 'change', function() { 113 | var form = document.getElementById('upload'); 114 | form.submit(); 115 | }); 116 | }); 117 | 118 | var frame = doc.getElementById('myFrame'); 119 | // 获取iframe中返回的数据 120 | setInterval(function() { 121 | var text = null; 122 | try { 123 | text = frame.contextDocument.body.innerText; 124 | } catch(e) { 125 | this.options.error(); 126 | } 127 | if (text) { 128 | this.options.success(); 129 | } 130 | }, 300); 131 | }; 132 | 133 | // 暴露出去 134 | window.Upload = Upload; 135 | })(window); -------------------------------------------------------------------------------- /layui/images/define.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/images/define.png -------------------------------------------------------------------------------- /layui/images/element.js.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/images/element.js.png -------------------------------------------------------------------------------- /layui/images/laydate-detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/images/laydate-detail.png -------------------------------------------------------------------------------- /layui/images/laydate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/images/laydate.png -------------------------------------------------------------------------------- /layui/images/laydate函数.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/images/laydate函数.png -------------------------------------------------------------------------------- /layui/images/layui-main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/images/layui-main.png -------------------------------------------------------------------------------- /layui/images/tab事件流程.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/images/tab事件流程.png -------------------------------------------------------------------------------- /layui/images/use.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/layui/images/use.png -------------------------------------------------------------------------------- /layui/lay/flow.js: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | @Name:layui.flow 流加载 4 | @Author:贤心 5 | @License:MIT 6 | 7 | */ 8 | 9 | 10 | layui.define('jquery', function(exports){ 11 | "use strict"; 12 | 13 | // 定义构造函数Flow 14 | var $ = layui.jquery, Flow = function(options){} 15 | // 加载容器的css类 16 | ,ELEM_MORE = 'layui-flow-more' 17 | // 动态加载的图标 18 | ,ELEM_LOAD = ''; 19 | 20 | //主方法 21 | Flow.prototype.load = function(options){ 22 | // page代码当前页,流加载一定数量的资源形成一页 23 | // isOver:资源是否已加载完毕 24 | // lazyimg:图片懒加载 25 | // timer:定时器 26 | var that = this, page = 0, lock, isOver, lazyimg, timer; 27 | options = options || {}; 28 | 29 | // elem:包裹资源的容器节点 30 | var elem = $(options.elem); if(!elem[0]) return; 31 | // 滚动条所在的元素 32 | var scrollElem = $(options.scrollElem || document); 33 | // 自动滚动时,触发点(与底部的临界距离) 34 | var mb = options.mb || 50; 35 | // 是否自动滚动加载 36 | var isAuto = 'isAuto' in options ? options.isAuto : true; 37 | // “末页”显示文案 38 | var end = options.end || '没有更多了'; 39 | 40 | // 滚动条所在元素是否为document 41 | var notDocment = options.scrollElem && options.scrollElem !== document; 42 | 43 | // 加载更多,按钮方式的DOM节点 44 | var ELEM_TEXT = '加载更多' 45 | ,more = $('
'+ ELEM_TEXT +'
'); 46 | 47 | // 处理加载loading节点的重复性 48 | if(!elem.find('.layui-flow-more')[0]){ 49 | elem.append(more); 50 | } 51 | 52 | //加载下一个元素 53 | var next = function(html, over){ 54 | // 创建指定的元素节点 55 | html = $(html); 56 | // 在加载节点前插入创建的节点 57 | more.before(html); 58 | // 判断是否结束 59 | over = over == 0 ? true : null; 60 | // 如果资源已全部加载, 就添加结束提示文本,否则设置文本为加载更多 61 | over ? more.html(end) : more.find('a').html(ELEM_TEXT); 62 | isOver = over; 63 | lock = null; 64 | // 如果需要图片懒加载,就调用lazyimg来实现 65 | lazyimg && lazyimg(); 66 | }; 67 | 68 | //触发请求 69 | var done = function(){ 70 | lock = true; 71 | // 改变加载形式是动态加载图标 72 | more.find('a').html(ELEM_LOAD); 73 | // 判断传入的参数done是否是函数,是则执行options中done函数, 并传入page以及next函数 74 | typeof options.done === 'function' && options.done(++page, next); 75 | }; 76 | 77 | done(); 78 | 79 | //不自动滚动加载, 按钮形式绑定click事件 80 | more.find('a').on('click', function(){ 81 | var othis = $(this); 82 | if(isOver) return; 83 | lock || done(); 84 | }); 85 | 86 | //如果允许图片懒加载 87 | if(options.isLazyimg){ 88 | var lazyimg = that.lazyimg({ 89 | elem: options.elem + ' img' 90 | ,scrollElem: options.scrollElem 91 | }); 92 | } 93 | 94 | // 不自动加载 95 | if(!isAuto) return that; 96 | 97 | // 滚动事件监听 98 | scrollElem.on('scroll', function(){ 99 | // 获取当前容器, 并获取scrollTop值 100 | var othis = $(this), top = othis.scrollTop(); 101 | 102 | // 如果存在定时器,则清除 103 | if(timer) clearTimeout(timer); 104 | // 资源加载完毕就退出 105 | if(isOver) return; 106 | 107 | timer = setTimeout(function(){ 108 | //计算滚动所在容器的可视高度 109 | var height = notDocment ? othis.height() : $(window).height(); 110 | 111 | //计算滚动所在容器的实际高度 112 | var scrollHeight = notDocment 113 | ? othis.prop('scrollHeight') 114 | : document.documentElement.scrollHeight; 115 | 116 | //临界点,当距离底部mb像素时,执行done()函数 117 | if(scrollHeight - top - height <= mb){ 118 | lock || done(); 119 | } 120 | }, 100); 121 | }); 122 | return that; 123 | }; 124 | 125 | //图片懒加载 126 | Flow.prototype.lazyimg = function(options){ 127 | var that = this, index = 0, haveScroll; 128 | options = options || {}; 129 | 130 | var scrollElem = $(options.scrollElem || document); //滚动条所在元素 131 | var elem = options.elem || 'img'; 132 | 133 | //滚动条所在元素是否为document 134 | var notDocment = options.scrollElem && options.scrollElem !== document; 135 | 136 | //显示图片 137 | var show = function(item, height){ 138 | // 获取scrollTop值 139 | // end: 表示当前滚动条距离底部的距离 end = scrollTop + clientHeight(或offsetHeight); 140 | var start = scrollElem.scrollTop(), end = start + height; 141 | var elemTop = notDocment ? function(){ 142 | return item.offset().top - scrollElem.offset().top + start; 143 | }() : item.offset().top; 144 | 145 | /* 始终只加载在当前屏范围内的图片 */ 146 | if(elemTop >= start && elemTop <= end){ 147 | if(!item.attr('src')){ 148 | var src = item.attr('lay-src'); 149 | layui.img(src, function(){ 150 | var next = that.lazyimg.elem.eq(index); 151 | item.attr('src', src).removeAttr('lay-src'); 152 | 153 | /* 当前图片加载就绪后,检测下一个图片是否在当前屏 */ 154 | next[0] && render(next); 155 | index++; 156 | }); 157 | } 158 | } 159 | }, render = function(othis, scroll){ 160 | 161 | //计算滚动所在容器的可视高度clientWidth 162 | var height = notDocment ? (scroll||scrollElem).height() : $(window).height(); 163 | // start === scrollTop, end表示当前滚动条位置距离底部的距离 164 | var start = scrollElem.scrollTop(), end = start + height; 165 | 166 | // 获取所有的图片 167 | that.lazyimg.elem = $(elem); 168 | 169 | if(othis){ 170 | show(othis, height); 171 | } else { 172 | //计算未加载过的图片 173 | for(var i = 0; i < that.lazyimg.elem.length; i++){ 174 | // 如果滚动条所在元素不是document, 就用img图片元素的偏移值 - 图片容器的偏移值 + 当前的scrollTop值 175 | // 否则就是图片自身的偏移值 176 | var item = that.lazyimg.elem.eq(i), elemTop = notDocment ? function(){ 177 | return item.offset().top - scrollElem.offset().top + start; 178 | }() : item.offset().top; 179 | 180 | show(item, height); 181 | index = i; 182 | 183 | //如果图片的top坐标,超出了当前屏,则终止后续图片的遍历 184 | if(elemTop > end) break; 185 | } 186 | } 187 | }; 188 | 189 | render(); 190 | 191 | if(!haveScroll){ 192 | var timer; 193 | scrollElem.on('scroll', function(){ 194 | var othis = $(this); 195 | if(timer) clearTimeout(timer) 196 | timer = setTimeout(function(){ 197 | render(null, othis); 198 | }, 50); 199 | }); 200 | haveScroll = true; 201 | } 202 | return render; 203 | }; 204 | 205 | //暴露接口 206 | exports('flow', new Flow()); 207 | }); 208 | -------------------------------------------------------------------------------- /layui/lay/laytpl.js: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | @Name : layui.laytpl 模板引擎 4 | @Author:贤心 5 | @License:MIT 6 | 7 | */ 8 | 9 | layui.define(function(exports){ 10 | 11 | "use strict"; 12 | 13 | // 定义模板的开始和结束标志 14 | var config = { 15 | open: '{{', 16 | close: '}}' 17 | }; 18 | 19 | // 工具对象 20 | var tool = { 21 | // 生成指定的正则表达式 22 | exp: function(str){ 23 | return new RegExp(str, 'g'); 24 | }, 25 | //匹配满足规则内容 26 | query: function(type, _, __){ 27 | var types = [ 28 | '#([\\s\\S])+?', //js语句 29 | '([^{#}])*?' //普通字段 30 | ][type || 0]; 31 | // /{{types[0]}}/, /{{types[1]}}/ 32 | return exp((_||'') + config.open + types + config.close + (__||'')); 33 | }, 34 | escape: function(html){ 35 | return String(html||'').replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&') 36 | .replace(//g, '>').replace(/'/g, ''').replace(/"/g, '"'); 37 | }, 38 | error: function(e, tplog){ 39 | var error = 'Laytpl Error:'; 40 | typeof console === 'object' && console.error(error + e + '\n'+ (tplog || '')); 41 | return error + e; 42 | } 43 | }; 44 | 45 | var exp = tool.exp, Tpl = function(tpl){ 46 | this.tpl = tpl; 47 | }; 48 | 49 | Tpl.pt = Tpl.prototype; 50 | 51 | window.errors = 0; 52 | 53 | //编译模版 54 | Tpl.pt.parse = function(tpl, data){ 55 | var that = this, tplog = tpl; 56 | // jss = new RegExp('^{{#', 'g'), jsse = new RegExp('}}$', 'g') 57 | var jss = exp('^'+config.open+'#', ''), jsse = exp(config.close+'$', ''); 58 | // 将空白字符以及换行符替换掉, 并将{{#替换, }}}替换成} }} 59 | tpl = tpl.replace(/\s+|\r|\t|\n/g, ' ').replace(exp(config.open+'#'), config.open+'# ') 60 | 61 | .replace(exp(config.close+'}'), '} '+config.close).replace(/\\/g, '\\\\') 62 | 63 | .replace(/(?="|')/g, '\\').replace(tool.query(), function(str){ 64 | str = str.replace(jss, '').replace(jsse, ''); 65 | return '";' + str.replace(/\\/g, '') + ';view+="'; 66 | }) 67 | 68 | .replace(tool.query(1), function(str){ 69 | var start = '"+('; 70 | if(str.replace(/\s/g, '') === config.open+config.close){ 71 | return ''; 72 | } 73 | str = str.replace(exp(config.open+'|'+config.close), ''); 74 | if(/^=/.test(str)){ 75 | str = str.replace(/^=/, ''); 76 | start = '"+_escape_('; 77 | } 78 | return start + str.replace(/\\/g, '') + ')+"'; 79 | }); 80 | tpl = '"use strict";var view = "' + tpl + '";return view;'; 81 | 82 | try{ 83 | that.cache = tpl = new Function('d, _escape_', tpl); 84 | return tpl(data, tool.escape); 85 | } catch(e){ 86 | delete that.cache; 87 | return tool.error(e, tplog); 88 | } 89 | }; 90 | 91 | Tpl.pt.render = function(data, callback){ 92 | var that = this, tpl; 93 | if(!data) return tool.error('no data'); 94 | tpl = that.cache ? that.cache(data, tool.escape) : that.parse(that.tpl, data); 95 | if(!callback) return tpl; 96 | callback(tpl); 97 | }; 98 | 99 | var laytpl = function(tpl){ 100 | if(typeof tpl !== 'string') return tool.error('Template not found'); 101 | return new Tpl(tpl); 102 | }; 103 | 104 | laytpl.config = function(options){ 105 | options = options || {}; 106 | for(var i in options){ 107 | config[i] = options[i]; 108 | } 109 | }; 110 | 111 | laytpl.v = '1.2.0'; 112 | 113 | exports('laytpl', laytpl); 114 | 115 | }); -------------------------------------------------------------------------------- /layui/lay/tree.js: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | @Name:layui.tree 树组件 4 | @Author:贤心 5 | @License:MIT 6 | 7 | */ 8 | 9 | 10 | layui.define('jquery', function(exports){ 11 | "use strict"; 12 | 13 | var $ = layui.jquery; 14 | var hint = layui.hint(); 15 | 16 | // Tree构造函数 17 | var enterSkin = 'layui-tree-enter', Tree = function(options){ 18 | this.options = options; 19 | }; 20 | 21 | //图标 22 | var icon = { 23 | arrow: ['', ''] //箭头 24 | ,checkbox: ['', ''] //复选框 25 | ,radio: ['', ''] //单选框 26 | ,branch: ['', ''] //父节点 27 | ,leaf: '' //叶节点 28 | }; 29 | 30 | //初始化 31 | Tree.prototype.init = function(elem){ 32 | var that = this; 33 | elem.addClass('layui-box layui-tree'); //添加tree样式 34 | // 支持皮肤样式的自定义 35 | if(that.options.skin){ 36 | elem.addClass('layui-tree-skin-'+ that.options.skin); 37 | } 38 | // 构建树形结构 39 | that.tree(elem); 40 | // 绑定事件 41 | that.on(elem); 42 | }; 43 | 44 | //树节点解析,elem表示父节点,children表示该父节点下所有子节点数据 45 | Tree.prototype.tree = function(elem, children){ 46 | var that = this, options = that.options 47 | var nodes = children || options.nodes; 48 | 49 | // 遍历数据构建节点 50 | layui.each(nodes, function(index, item){ 51 | // 是否存在存在子菜单判断 52 | var hasChild = item.children && item.children.length > 0; 53 | // 创建ul父节点 54 | var ul = $(''); 55 | // 创建li子节点 56 | var li = $(['
  • ' 57 | //展开箭头, 存在子节点就需要创建箭头图标 58 | ,function(){ 59 | return hasChild ? ''+ ( 60 | item.spread ? icon.arrow[1] : icon.arrow[0] 61 | ) +'' : ''; 62 | }() 63 | 64 | //复选框/单选框 65 | ,function(){ 66 | return options.check ? ( 67 | ''+ ( 68 | options.check === 'checkbox' ? icon.checkbox[0] : ( 69 | options.check === 'radio' ? icon.radio[0] : '' 70 | ) 71 | ) +'' 72 | ) : ''; 73 | }() 74 | 75 | //节点 76 | ,function(){ 77 | return '' 80 | + (''+ ( 81 | hasChild ? ( 82 | item.spread ? icon.branch[1] : icon.branch[0] 83 | ) : icon.leaf 84 | ) +'') //节点图标 85 | + (''+ (item.name||'未命名') +''); 86 | }() 87 | 88 | ,'
  • '].join('')); 89 | 90 | //如果有子节点,则递归继续生成树 91 | if(hasChild){ 92 | li.append(ul); 93 | that.tree(ul, item.children); 94 | } 95 | 96 | elem.append(li); 97 | 98 | //触发点击节点回调 99 | typeof options.click === 'function' && that.click(li, item); 100 | 101 | //伸展节点,就是图标的展开 102 | that.spread(li, item); 103 | 104 | //拖拽节点 105 | options.drag && that.drag(li, item); 106 | }); 107 | }; 108 | 109 | //点击节点回调,支持点击菜单事件处理 110 | Tree.prototype.click = function(elem, item){ 111 | var that = this, options = that.options; 112 | elem.children('a').on('click', function(e){ 113 | layui.stope(e); 114 | options.click(item) 115 | }); 116 | }; 117 | 118 | //伸展节点 119 | Tree.prototype.spread = function(elem, item){ 120 | var that = this, options = that.options; 121 | var arrow = elem.children('.layui-tree-spread') 122 | var ul = elem.children('ul'), a = elem.children('a'); 123 | 124 | //执行伸展 125 | var open = function(){ 126 | if(elem.data('spread')){ 127 | elem.data('spread', null) 128 | ul.removeClass('layui-show'); 129 | arrow.html(icon.arrow[0]); 130 | a.find('.layui-icon').html(icon.branch[0]); 131 | } else { 132 | elem.data('spread', true); 133 | ul.addClass('layui-show'); 134 | arrow.html(icon.arrow[1]); 135 | a.find('.layui-icon').html(icon.branch[1]); 136 | } 137 | }; 138 | 139 | //如果没有子节点,则不执行 140 | if(!ul[0]) return; 141 | 142 | arrow.on('click', open); 143 | a.on('dblclick', open); 144 | } 145 | 146 | //通用事件 147 | Tree.prototype.on = function(elem){ 148 | var that = this, options = that.options; 149 | var dragStr = 'layui-tree-drag'; 150 | 151 | //屏蔽选中文字 152 | elem.find('i').on('selectstart', function(e){ 153 | return false 154 | }); 155 | 156 | //拖拽 157 | if(options.drag){ 158 | $(document).on('mousemove', function(e){ 159 | var move = that.move; 160 | if(move.from){ 161 | var to = move.to, treeMove = $('
    '); 162 | e.preventDefault(); 163 | $('.' + dragStr)[0] || $('body').append(treeMove); 164 | var dragElem = $('.' + dragStr)[0] ? $('.' + dragStr) : treeMove; 165 | (dragElem).addClass('layui-show').html(move.from.elem.children('a').html()); 166 | dragElem.css({ 167 | left: e.pageX + 10 168 | ,top: e.pageY + 10 169 | }) 170 | } 171 | }).on('mouseup', function(){ 172 | var move = that.move; 173 | if(move.from){ 174 | move.from.elem.children('a').removeClass(enterSkin); 175 | move.to && move.to.elem.children('a').removeClass(enterSkin); 176 | that.move = {}; 177 | $('.' + dragStr).remove(); 178 | } 179 | }); 180 | } 181 | }; 182 | 183 | //拖拽节点,目前该版本还未实现该功能 184 | Tree.prototype.move = {}; 185 | Tree.prototype.drag = function(elem, item){ 186 | var that = this, options = that.options; 187 | var a = elem.children('a'), mouseenter = function(){ 188 | var othis = $(this), move = that.move; 189 | if(move.from){ 190 | move.to = { 191 | item: item 192 | ,elem: elem 193 | }; 194 | othis.addClass(enterSkin); 195 | } 196 | }; 197 | a.on('mousedown', function(){ 198 | var move = that.move 199 | move.from = { 200 | item: item 201 | ,elem: elem 202 | }; 203 | }); 204 | a.on('mouseenter', mouseenter).on('mousemove', mouseenter) 205 | .on('mouseleave', function(){ 206 | var othis = $(this), move = that.move; 207 | if(move.from){ 208 | delete move.to; 209 | othis.removeClass(enterSkin); 210 | } 211 | }); 212 | }; 213 | 214 | //暴露接口 215 | exports('tree', function(options){ 216 | var tree = new Tree(options = options || {}); 217 | var elem = $(options.elem); 218 | if(!elem[0]){ 219 | return hint.error('layui.tree 没有找到'+ options.elem +'元素'); 220 | } 221 | tree.init(elem); 222 | }); 223 | }); 224 | -------------------------------------------------------------------------------- /layui/lay/upload.js: -------------------------------------------------------------------------------- 1 | /*! 2 | 3 | @Title: layui.upload 单文件上传 - 全浏览器兼容版 4 | @Author: 贤心 5 | @License:MIT 6 | 7 | */ 8 | 9 | layui.define('layer' , function(exports){ 10 | "use strict"; 11 | 12 | // 保存jqury等 13 | var $ = layui.jquery; 14 | var layer = layui.layer; 15 | var device = layui.device(); 16 | 17 | // 定义变量存储需要的class类 18 | var elemDragEnter = 'layui-upload-enter'; 19 | var elemIframe = 'layui-upload-iframe'; 20 | 21 | 22 | var msgConf = { 23 | icon: 2 24 | ,shift: 6 25 | }, fileType = { 26 | file: '文件' 27 | ,video: '视频' 28 | ,audio: '音频' 29 | }; 30 | 31 | // 构造函数 32 | var Upload = function(options){ 33 | this.options = options; 34 | }; 35 | 36 | //初始化渲染 37 | Upload.prototype.init = function(){ 38 | // 获取body标签的DOM对象以及iframe的html结构 39 | var that = this, options = that.options; 40 | var body = $('body'), elem = $(options.elem || '.layui-upload-file'); 41 | var iframe = $(''); 42 | 43 | //插入iframe 44 | $('#'+elemIframe)[0] || body.append(iframe); 45 | 46 | return elem.each(function(index, item){ 47 | item = $(item); 48 | var form = '
    '; 49 | 50 | var type = item.attr('lay-type') || options.type; //获取文件类型 51 | 52 | //包裹ui元素 53 | if(!options.unwrap){ 54 | form = '
    ' + form + ''+ ( 55 | item.attr('lay-title') || options.title|| ('上传'+ (fileType[type]||'图片') ) 56 | ) +'
    '; 57 | } 58 | 59 | form = $(form); 60 | 61 | //拖拽支持 62 | if(!options.unwrap){ 63 | form.on('dragover', function(e){ 64 | e.preventDefault(); 65 | $(this).addClass(elemDragEnter); 66 | }).on('dragleave', function(){ 67 | $(this).removeClass(elemDragEnter); 68 | }).on('drop', function(){ 69 | $(this).removeClass(elemDragEnter); 70 | }); 71 | } 72 | 73 | //如果已经实例化,则移除包裹元素 74 | if(item.parent('form').attr('target') === elemIframe){ 75 | if(options.unwrap){ 76 | item.unwrap(); 77 | } else { 78 | item.parent().next().remove(); 79 | item.unwrap().unwrap(); 80 | } 81 | }; 82 | 83 | //包裹元素 84 | item.wrap(form); 85 | 86 | //触发上传 87 | item.off('change').on('change', function(){ 88 | that.action(this, type); 89 | }); 90 | }); 91 | }; 92 | 93 | //提交上传 94 | Upload.prototype.action = function(input, type){ 95 | var that = this, options = that.options, val = input.value; 96 | var item = $(input), ext = item.attr('lay-ext') || options.ext || ''; //获取支持上传的文件扩展名; 97 | 98 | if(!val){ 99 | return; 100 | }; 101 | 102 | //校验文件 103 | switch(type){ 104 | case 'file': //一般文件 105 | if(ext && !RegExp('\\w\\.('+ ext +')$', 'i').test(escape(val))){ 106 | layer.msg('不支持该文件格式', msgConf); 107 | return input.value = ''; 108 | } 109 | break; 110 | case 'video': //视频文件 111 | if(!RegExp('\\w\\.('+ (ext||'avi|mp4|wma|rmvb|rm|flash|3gp|flv') +')$', 'i').test(escape(val))){ 112 | layer.msg('不支持该视频格式', msgConf); 113 | return input.value = ''; 114 | } 115 | break; 116 | case 'audio': //音频文件 117 | if(!RegExp('\\w\\.('+ (ext||'mp3|wav|mid') +')$', 'i').test(escape(val))){ 118 | layer.msg('不支持该音频格式', msgConf); 119 | return input.value = ''; 120 | } 121 | break; 122 | default: //图片文件 123 | if(!RegExp('\\w\\.('+ (ext||'jpg|png|gif|bmp|jpeg') +')$', 'i').test(escape(val))){ 124 | layer.msg('不支持该图片格式', msgConf); 125 | return input.value = ''; 126 | } 127 | break; 128 | } 129 | 130 | // 调用提交前的函数 131 | options.before && options.before(input); 132 | // 提交表单 133 | item.parent().submit(); 134 | 135 | // 获取iframe中插入的服务器端返回的数据 136 | var iframe = $('#'+elemIframe), timer = setInterval(function() { 137 | var res; 138 | try { 139 | res = iframe.contents().find('body').text(); 140 | } catch(e) { 141 | layer.msg('上传接口存在跨域', msgConf); 142 | clearInterval(timer); 143 | } 144 | if(res){ 145 | clearInterval(timer); 146 | iframe.contents().find('body').html(''); 147 | try { 148 | res = JSON.parse(res); 149 | } catch(e){ 150 | res = {}; 151 | return layer.msg('请对上传接口返回JSON字符', msgConf); 152 | } 153 | typeof options.success === 'function' && options.success(res, input); 154 | } 155 | }, 30); 156 | 157 | input.value = ''; 158 | }; 159 | 160 | //暴露接口 161 | exports('upload', function(options){ 162 | var upload = new Upload(options = options || {}); 163 | upload.init(); 164 | }); 165 | }); 166 | 167 | -------------------------------------------------------------------------------- /monx/monx.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Monx v0.1.1 3 | * Copyright 2017-2018 Kabir Shah 4 | * Released under the MIT License 5 | * https://github.com/kbrsh/monx 6 | */ 7 | 8 | (function(root, factory) { 9 | /* ======= Global Monx ======= */ 10 | if(typeof module === "undefined") { 11 | root.Monx = factory(); 12 | } else { 13 | module.exports = factory(); 14 | } 15 | }(this, function() { 16 | var MoonDestroy; 17 | 18 | var initState = function(store) { 19 | var state = store.state; 20 | var _state = store._state; 21 | 22 | var instances = store.instances; 23 | var map = store.map; 24 | 25 | // store状态结合对象中属性实现监听,实现响应式数据 26 | var loop = function ( key ) { 27 | Object.defineProperty(state, key, { 28 | get: function() { 29 | var target = store.target; 30 | if(target !== undefined) { 31 | map[target][key] = true; 32 | } 33 | 34 | return _state[key]; 35 | }, 36 | set: function(value) { 37 | _state[key] = value; 38 | 39 | for(var i = 0; i < instances.length; i++) { 40 | var currentInstance = instances[i]; 41 | if(map[currentInstance.name][key] === true) { 42 | currentInstance.build(); 43 | } 44 | } 45 | }, 46 | enumerable: true 47 | }); 48 | }; 49 | 50 | for(var key in _state) loop( key ); 51 | } 52 | 53 | var defineProperty = function(obj, prop, value, def) { 54 | if(value === undefined) { 55 | obj[prop] = def; 56 | } else { 57 | obj[prop] = value; 58 | } 59 | } 60 | 61 | 62 | function Monx(options) { 63 | // 状态集合对象 64 | this.state = {}; 65 | defineProperty(this, "_state", options.state, {}); 66 | 67 | defineProperty(this, "actions", options.actions, {}); 68 | 69 | // Instances 70 | this.instances = []; 71 | 72 | // 对应的Moon实例对象 73 | this.map = {}; 74 | 75 | // Component to capture 76 | this.target = undefined; 77 | 78 | // Initialize reactive state 79 | initState(this); 80 | } 81 | 82 | Monx.prototype.dispatch = function(name, payload) { 83 | this.actions[name](this.state, payload); 84 | } 85 | 86 | // 将store注册到Moon实例上 87 | Monx.prototype.init = function(instance) { 88 | var name = instance.name; 89 | var store = this; 90 | 91 | // Add store to data 92 | instance.data.store = store; 93 | 94 | // Capture dependencies 95 | var render = instance.render; 96 | instance.render = function() { 97 | store.target = name; 98 | var dom = render.apply(this, arguments); 99 | store.target = undefined; 100 | return dom; 101 | } 102 | 103 | // Remove store when destroyed 104 | instance.destroy = function() { 105 | var instances = store.instances; 106 | instances.splice(instances.indexOf(this), 1); 107 | delete store.map[name]; 108 | MoonDestroy.apply(this, arguments); 109 | } 110 | 111 | // Add to set of instances to update 112 | store.instances.push(instance); 113 | 114 | // Add to dependency map 115 | store.map[name] = {}; 116 | } 117 | 118 | Monx.init = function(Moon) { 119 | MoonDestroy = Moon.prototype.destroy; 120 | } 121 | 122 | return Monx; 123 | })); 124 | -------------------------------------------------------------------------------- /moon-cli/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /moon-cli/.gitkeep: -------------------------------------------------------------------------------- 1 | template/dist 2 | template/.gitignore 3 | -------------------------------------------------------------------------------- /moon-cli/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Kabir Shah (kabir.ml) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /moon-cli/README.md: -------------------------------------------------------------------------------- 1 | # Moon Cli 2 | 3 | :sparkles: A CLI to scaffold Moon applications 4 | 5 | ### Installation 6 | 7 | Install with npm: 8 | 9 | ```sh 10 | $ npm install moon-cli -g 11 | ``` 12 | 13 | ### Getting Started 14 | 15 | Create your first project with: 16 | 17 | ```sh 18 | $ moon init 19 | ``` 20 | 21 | `` is the name of your application, and Moon will proceed to create the directory and install the template there. 22 | 23 | Next, move into the directory, install the dependencies, and run a dev server! 24 | 25 | ```sh 26 | $ cd 27 | $ npm install 28 | $ npm run dev 29 | ``` 30 | 31 | ### Production 32 | 33 | To build a minified bundle, run: 34 | 35 | ```sh 36 | $ npm run build 37 | ``` 38 | 39 | All html, css, and javascript will be minified and bundled accordingly. 40 | 41 | ### License 42 | 43 | Licensed under the [MIT License](https://kbrsh.github.io/license) by [Kabir Shah](https://kabir.ml) 44 | -------------------------------------------------------------------------------- /moon-cli/bin/moon: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | "use strict"; 4 | 5 | var hexu = require("hexu"); 6 | var Handlebars = require("handlebars"); 7 | const download = require("download-git-repo"); 8 | var async = require("async"); 9 | var fs = require("fs"); 10 | var path = require('path'); 11 | var readline = require('readline'); 12 | var exec = require("child_process").execSync; 13 | var pkg = require("../package.json"); 14 | var load = require("../src/loader.js"); 15 | 16 | // process是Node的全局对象,cwd代表当前目录路径 17 | const cwd = process.cwd(); 18 | 19 | // process.argv是传入的参数的数组集合 20 | var command = process.argv.slice(2); 21 | 22 | // readline(逐行读取) 23 | const rl = readline.createInterface({ 24 | input: process.stdin, 25 | output: process.stdout 26 | }); 27 | 28 | load.defineRl(rl); 29 | 30 | const space = (num) => { 31 | return "\n".repeat(num); 32 | } 33 | 34 | const intro = () => { 35 | // hexu:指定字符颜色 36 | console.log(hexu.blue("======= MOON =======") + space(1)); 37 | } 38 | 39 | const help = () => { 40 | console.log(" Usage: moon [options]"); 41 | console.log(space(1)); 42 | console.log(" Commands: "); 43 | console.log(" init\tgenerates a new project"); 44 | console.log(" help\tdisplays this help message"); 45 | console.log(space(1)); 46 | console.log(" Options: "); 47 | console.log(" -h, --help\tdisplays this help message"); 48 | console.log(" -v, --version\tdisplays current Moon version"); 49 | exit(); 50 | } 51 | 52 | const version = () => { 53 | console.log(pkg.version); 54 | exit(); 55 | } 56 | 57 | const err = (msg) => { 58 | console.log(" Moon " + hexu.red("ERR") + " " + msg); 59 | exit(); 60 | } 61 | 62 | // 关闭文件流 63 | const exit = () => { 64 | rl.close(); 65 | } 66 | 67 | const sep = path.sep; 68 | // 创建文件或目录 69 | let mkdirp = (dir) => { 70 | const parts = dir.split(sep); 71 | let subdir = sep; 72 | 73 | for(let i = 1; i < parts.length; i++) { 74 | subdir += parts[i] + sep; 75 | if(fs.existsSync(subdir) === false) { 76 | fs.mkdirSync(subdir); 77 | } 78 | } 79 | } 80 | 81 | // 删除目录 82 | const del = (dir) => { 83 | if(fs.lstatSync(dir).isFile()) { 84 | fs.unlinkSync(dir); 85 | return; 86 | } 87 | const files = fs.readdirSync(dir); 88 | for(var i = 0; i < files.length; i++) { 89 | let filePath = path.join(dir, files[i]); 90 | if(fs.existsSync(filePath)) { 91 | del(filePath); 92 | } else { 93 | fs.unlinkSync(filePath); 94 | } 95 | } 96 | } 97 | 98 | // info函数 99 | const info = (cb) => { 100 | // exec是child_process的execSync方法,该方法是创建同步执行命令 101 | // 此处是获取git中的user.name属性的值 102 | var name = JSON.stringify(exec('git config --get user.name').toString().trim()).slice(1, -1); 103 | var answers = ask({ 104 | "Author": { 105 | def: name, 106 | key: "author" 107 | }, 108 | "Description": { 109 | def: "A Moon App", 110 | key: "description" 111 | }, 112 | "Moon Version": { 113 | def: exec("npm show moonjs version").toString().slice(0, -1), 114 | key: "version" 115 | } 116 | }, function(answers) { 117 | cb(answers); 118 | }); 119 | } 120 | 121 | const ask = (questions, cb) => { 122 | var prompt, answers = {}; 123 | // async是异步处理模块 124 | async.eachSeries(Object.keys(questions), function(question, done) { 125 | var def = questions[question].def; 126 | // [?] Author (默认) 127 | if(def) { 128 | prompt = " " + hexu.green("[?]") + " " + question + hexu.grey(" (" + def + ") "); 129 | } else { 130 | prompt = " " + hexu.green("[?]") + " " + question + " "; 131 | } 132 | // 获取用户输入内容 133 | rl.question(prompt, (answer) => { 134 | if(!answer) answer = def; 135 | readline.moveCursor(rl, 0, -1); 136 | rl.write("\n"); 137 | readline.moveCursor(rl, 0, -2); 138 | rl.write(` ${hexu.green("[?]")} ${question} ${hexu.cyan(answer)}\n\n`); 139 | readline.moveCursor(rl, 0, -1); 140 | rl.write(" ".repeat(prompt.length) + "\n"); 141 | answers[questions[question].key] = answer; 142 | done(null); 143 | }); 144 | }, function() { 145 | cb(answers) 146 | }); 147 | } 148 | 149 | var read = function(file, cb) { 150 | fs.readFile(file, 'utf8', function(err, content) { 151 | cb(file, content); 152 | }); 153 | } 154 | 155 | const compile = (file, opts) => { 156 | return Handlebars.compile(fs.readFileSync(file).toString())(opts); 157 | } 158 | 159 | // moon init的直接处理函数 160 | const init = (name) => { 161 | // 调用info函数 162 | info(function(opts) { 163 | // Create Loader 164 | var templateLoader = new load(hexu.blue("generating") + " template"); 165 | 166 | // Create directory 167 | // 创建项目目录 168 | const projectDir = path.join(cwd, name); 169 | mkdirp(projectDir); 170 | 171 | // Download Template 172 | // 获取template目录路径 173 | const templatePath = path.join(__dirname, "/../template"); 174 | // template是否存在,存在就删除 175 | if(fs.existsSync(templatePath)) { 176 | del(templatePath); 177 | } 178 | // 从指定的仓库下载template到本地指定路径 179 | download("KingPixil/moon-template", templatePath, () => { 180 | // 获取template中config.json文件,该文件中存储了moon项目初始化的所有文件名 181 | const configPath = path.join(templatePath, "config.json"); 182 | const config = JSON.parse(fs.readFileSync(configPath)); 183 | const files = config.files; 184 | 185 | // 创建文件或目录 186 | for(var i = 0; i < files.length; i++) { 187 | let source = path.join(templatePath, files[i]); 188 | let target = path.join(projectDir, files[i]); 189 | 190 | mkdirp(path.dirname(target)); 191 | 192 | opts.name = name; 193 | fs.writeFileSync(target, compile(source, opts)); 194 | } 195 | 196 | // close事件触发后的回调函数,输出一些提示信息 197 | rl.on('close', function() { 198 | console.log("\n"); 199 | console.log(`${hexu.green("success")} generated ${hexu.grey(`'${name}'`)} ✨`); 200 | console.log("\n") 201 | console.log("To Start, Run:"); 202 | console.log(hexu.grey(` cd ${name} 203 | npm install 204 | npm run dev`)); 205 | }); 206 | // template下载完毕后关闭readline 207 | templateLoader.done(function() { 208 | rl.close(); 209 | }); 210 | }); 211 | }); 212 | } 213 | 214 | // 输出蓝色提示"=======MOON=======" 215 | intro(); 216 | // 处理moon init、moon help | --help | -h、moon -v | --version命令 217 | switch (command[0]) { 218 | case "--help": 219 | case "help": 220 | case undefined: 221 | help(); 222 | break; 223 | case "-h": 224 | help(); 225 | break; 226 | case "-v": 227 | version(); 228 | break; 229 | case "--version": 230 | version(); 231 | break; 232 | case "init": 233 | if(command[1]) { 234 | init(command[1]); 235 | } else { 236 | err("Please provide an app name"); 237 | } 238 | break; 239 | default: 240 | err("Command Not Found"); 241 | } 242 | -------------------------------------------------------------------------------- /moon-cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "moon-cli", 3 | "version": "0.1.1", 4 | "description": "Client for generating Moon applications.", 5 | "main": "bin/moon", 6 | "bin": { 7 | "moon": "./bin/moon" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/kbrsh/moon-cli.git" 12 | }, 13 | "author": "Kabir Shah", 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/kbrsh/moon-cli/issues" 17 | }, 18 | "homepage": "https://github.com/kbrsh/moon-cli#readme", 19 | "dependencies": { 20 | "async": "^2.1.5", 21 | "download-git-repo": "^0.2.1", 22 | "handlebars": "^4.0.6", 23 | "hexu": "^1.0.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /moon-cli/src/loader.js: -------------------------------------------------------------------------------- 1 | var readline = require('readline'); 2 | var rl; 3 | 4 | var sequence = "⣾⣽⣻⢿⡿⣟⣯⣷".split(""); 5 | function spinner() { 6 | this.index = 0; 7 | this.current = sequence[this.index % sequence.length]; 8 | this.next = function() { 9 | this.index++; 10 | this.current = sequence[this.index % sequence.length]; 11 | } 12 | } 13 | var spin = new spinner(); 14 | function load(text, opts) { 15 | this.text = text; 16 | this.int = setInterval(function() { 17 | rl.clearLine(); 18 | readline.moveCursor(rl, 0, -1); 19 | rl.write(" \x1b[36m" + spin.current + "\x1b[0m " + text + " "); 20 | spin.next(); 21 | }, 100); 22 | } 23 | 24 | load.prototype.done = function(cb) { 25 | var self = this; 26 | setTimeout(function() { 27 | clearInterval(self.int); 28 | rl.clearLine(); 29 | readline.moveCursor(rl, 0, -1); 30 | rl.write(" \x1b[32m" + "✓" + "\x1b[0m " + self.text + " \n"); 31 | cb(); 32 | }, 1000); 33 | } 34 | // Expose loader 35 | module.exports = load; 36 | module.exports.defineRl = (instance) => { 37 | rl = instance; 38 | } 39 | -------------------------------------------------------------------------------- /moon/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Document 6 | 7 | 8 | 9 |
    10 | {{text}} 11 |
    12 | 21 | 22 | -------------------------------------------------------------------------------- /nprogress/nprogress.js: -------------------------------------------------------------------------------- 1 | /* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress 2 | * @license MIT */ 3 | 4 | // IIFE 5 | ;(function(root, factory) { 6 | 7 | // 兼容AMD、CMD以及window的方式来暴露api 8 | if (typeof define === 'function' && define.amd) { 9 | define(factory); 10 | } else if (typeof exports === 'object') { 11 | module.exports = factory(); 12 | } else { 13 | root.NProgress = factory(); 14 | } 15 | 16 | })(this, function() { 17 | // 创建NProgress对象 18 | var NProgress = {}; 19 | 20 | // 版本号 21 | NProgress.version = '0.2.0'; 22 | 23 | /** 24 | * 默认参数 25 | * minimum:进度最小值,最大值为1 26 | * easing:设置动画的方式 27 | * showSpinner: 是否显示loading图标 28 | * barSelector:使用querySelector来查询标记 29 | * spinnerSelector:亦然 30 | * parent: 直接父节点 31 | * template:nprogress内部html结构 32 | * 33 | */ 34 | var Settings = NProgress.settings = { 35 | minimum: 0.08, 36 | easing: 'linear', 37 | positionUsing: '', 38 | speed: 200, 39 | trickle: true, 40 | trickleSpeed: 200, 41 | showSpinner: true, 42 | barSelector: '[role="bar"]', 43 | spinnerSelector: '[role="spinner"]', 44 | parent: 'body', 45 | template: '
    ' 46 | }; 47 | 48 | /** 49 | * 用户自定义设置参数的合并 50 | */ 51 | NProgress.configure = function(options) { 52 | var key, value; 53 | for (key in options) { 54 | value = options[key]; 55 | if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value; 56 | } 57 | 58 | return this; 59 | }; 60 | 61 | // status保存nprogress的起始进度 62 | NProgress.status = null; 63 | 64 | /** 65 | * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`. 66 | * 设置进度条开始时进度 67 | * 68 | */ 69 | NProgress.set = function(n) { 70 | 71 | // 判断进度是否开启 72 | var started = NProgress.isStarted(); 73 | 74 | // 判断n是否超出0.08~1的范围 75 | n = clamp(n, Settings.minimum, 1); 76 | // 设置进度起始进度 77 | NProgress.status = (n === 1 ? null : n); 78 | 79 | // 构建html结构 80 | var progress = NProgress.render(!started), 81 | bar = progress.querySelector(Settings.barSelector), 82 | speed = Settings.speed, 83 | ease = Settings.easing; 84 | 85 | // 获取nprogress的宽度 86 | progress.offsetWidth; /* Repaint */ 87 | 88 | // 队列 89 | queue(function(next) { 90 | // Set positionUsing if it hasn't already been set 91 | if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS(); 92 | 93 | // 设置进度以及过渡效果 94 | css(bar, barPositionCSS(n, speed, ease)); 95 | 96 | // 如果设置开始进度就是100% 97 | if (n === 1) { 98 | // 设置nprogress样式 99 | css(progress, { 100 | transition: 'none', 101 | opacity: 1 102 | }); 103 | // 获取progress宽度 104 | progress.offsetWidth; 105 | 106 | // 定时器 107 | setTimeout(function() { 108 | // nprogress设置样式 109 | css(progress, { 110 | transition: 'all ' + speed + 'ms linear', 111 | opacity: 0 112 | }); 113 | // 移除class以及nprogress节点 114 | setTimeout(function() { 115 | NProgress.remove(); 116 | // 递归 117 | next(); 118 | }, speed); 119 | }, speed); 120 | } else { 121 | // 递归执行,设置进度 122 | setTimeout(next, speed); 123 | } 124 | }); 125 | 126 | return this; 127 | }; 128 | 129 | // 判断进度是否开始 130 | NProgress.isStarted = function() { 131 | return typeof NProgress.status === 'number'; 132 | }; 133 | 134 | /** 135 | * Shows the progress bar. 136 | * This is the same as setting the status to 0%, except that it doesn't go backwards. 137 | * 138 | * NProgress.start(); 139 | * 140 | */ 141 | NProgress.start = function() { 142 | // 判断start是否为null 143 | if (!NProgress.status) NProgress.set(0); 144 | 145 | 、、 146 | var work = function() { 147 | setTimeout(function() { 148 | if (!NProgress.status) return; 149 | NProgress.trickle(); 150 | work(); 151 | }, Settings.trickleSpeed); 152 | }; 153 | 154 | if (Settings.trickle) work(); 155 | 156 | return this; 157 | }; 158 | 159 | // 进度结束 160 | NProgress.done = function(force) { 161 | // status为0 162 | if (!force && !NProgress.status) return this; 163 | 164 | return NProgress.inc(0.3 + 0.5 * Math.random()).set(1); 165 | }; 166 | 167 | // 设置 168 | NProgress.inc = function(amount) { 169 | // 获取开始进度值 170 | var n = NProgress.status; 171 | 172 | // n = 0 或null 173 | if (!n) { 174 | return NProgress.start(); 175 | } else if(n > 1) { 176 | return; 177 | } else { 178 | // 处理n > 0 179 | // 判断amount是否是number 180 | if (typeof amount !== 'number') { 181 | if (n >= 0 && n < 0.2) { amount = 0.1; } 182 | else if (n >= 0.2 && n < 0.5) { amount = 0.04; } 183 | else if (n >= 0.5 && n < 0.8) { amount = 0.02; } 184 | else if (n >= 0.8 && n < 0.99) { amount = 0.005; } 185 | else { amount = 0; } 186 | } 187 | 188 | // 保证n + amount值在0~0.994范围内 189 | n = clamp(n + amount, 0, 0.994); 190 | return NProgress.set(n); 191 | } 192 | }; 193 | 194 | // inc是 195 | NProgress.trickle = function() { 196 | return NProgress.inc(); 197 | }; 198 | 199 | /** 200 | * Waits for all supplied jQuery promises and 201 | * increases the progress as the promises resolve. 202 | * 203 | * @param $promise jQUery Promise 204 | */ 205 | (function() { 206 | var initial = 0, current = 0; 207 | 208 | NProgress.promise = function($promise) { 209 | if (!$promise || $promise.state() === "resolved") { 210 | return this; 211 | } 212 | 213 | if (current === 0) { 214 | NProgress.start(); 215 | } 216 | 217 | initial++; 218 | current++; 219 | 220 | $promise.always(function() { 221 | current--; 222 | if (current === 0) { 223 | initial = 0; 224 | NProgress.done(); 225 | } else { 226 | NProgress.set((initial - current) / initial); 227 | } 228 | }); 229 | 230 | return this; 231 | }; 232 | 233 | })(); 234 | 235 | /** 236 | * 构建nprogress的结构以及添加class类 237 | */ 238 | NProgress.render = function(fromStart) { 239 | // 判断id为nprogress的节点是否存在, 如果存在就获取该节点并返回 240 | if (NProgress.isRendered()) return document.getElementById('nprogress'); 241 | 242 | // html添加class类nprogress-busy 243 | addClass(document.documentElement, 'nprogress-busy'); 244 | 245 | // 创建div节点并设置id属性以及其他结构 246 | var progress = document.createElement('div'); 247 | progress.id = 'nprogress'; 248 | progress.innerHTML = Settings.template; 249 | 250 | // 获取进度条、nprogress所属父元素 251 | // formStart表示 252 | var bar = progress.querySelector(Settings.barSelector), 253 | perc = fromStart ? '-100' : toBarPerc(NProgress.status || 0), 254 | parent = document.querySelector(Settings.parent), 255 | spinner; 256 | 257 | // 进度条节点对象添加css样式 258 | css(bar, { 259 | transition: 'all 0 linear', 260 | transform: 'translate3d(' + perc + '%,0,0)' 261 | }); 262 | 263 | // 是否显示loading 264 | if (!Settings.showSpinner) { 265 | spinner = progress.querySelector(Settings.spinnerSelector); 266 | spinner && removeElement(spinner); 267 | } 268 | 269 | // 若nprogress的父元素不是body, 添加class类 270 | if (parent != document.body) { 271 | addClass(parent, 'nprogress-custom-parent'); 272 | } 273 | 274 | // 追加节点 275 | parent.appendChild(progress); 276 | return progress; 277 | }; 278 | 279 | // 删除class以及nprogress节点 280 | NProgress.remove = function() { 281 | removeClass(document.documentElement, 'nprogress-busy'); 282 | removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent'); 283 | var progress = document.getElementById('nprogress'); 284 | progress && removeElement(progress); 285 | }; 286 | 287 | // 检查是否存在id为nprogress的节点 288 | NProgress.isRendered = function() { 289 | return !!document.getElementById('nprogress'); 290 | }; 291 | 292 | /** 293 | * Determine which positioning CSS rule to use. 294 | */ 295 | 296 | NProgress.getPositioningCSS = function() { 297 | // Sniff on document.body.style 298 | var bodyStyle = document.body.style; 299 | 300 | // Sniff prefixes 301 | var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' : 302 | ('MozTransform' in bodyStyle) ? 'Moz' : 303 | ('msTransform' in bodyStyle) ? 'ms' : 304 | ('OTransform' in bodyStyle) ? 'O' : ''; 305 | 306 | if (vendorPrefix + 'Perspective' in bodyStyle) { 307 | // Modern browsers with 3D support, e.g. Webkit, IE10 308 | return 'translate3d'; 309 | } else if (vendorPrefix + 'Transform' in bodyStyle) { 310 | // Browsers without 3D support, e.g. IE9 311 | return 'translate'; 312 | } else { 313 | // Browsers without translate() support, e.g. IE7-8 314 | return 'margin'; 315 | } 316 | }; 317 | 318 | // 检验数值范围 319 | function clamp(n, min, max) { 320 | if (n < min) return min; 321 | if (n > max) return max; 322 | return n; 323 | } 324 | 325 | // 将0.1形式的数值转换为百分比样式数值 326 | // 0 -> -100 1 -> 0 327 | function toBarPerc(n) { 328 | return (-1 + n) * 100; 329 | } 330 | 331 | // 设置进度以及过渡效果 332 | function barPositionCSS(n, speed, ease) { 333 | var barCSS; 334 | 335 | if (Settings.positionUsing === 'translate3d') { 336 | barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' }; 337 | } else if (Settings.positionUsing === 'translate') { 338 | barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' }; 339 | } else { 340 | barCSS = { 'margin-left': toBarPerc(n)+'%' }; 341 | } 342 | 343 | barCSS.transition = 'all '+speed+'ms '+ease; 344 | 345 | return barCSS; 346 | } 347 | 348 | // IIFE 349 | var queue = (function() { 350 | var pending = []; 351 | 352 | // 删除数组中第一个元素 353 | function next() { 354 | var fn = pending.shift(); 355 | if (fn) { 356 | fn(next); 357 | } 358 | } 359 | 360 | return function(fn) { 361 | pending.push(fn); 362 | if (pending.length == 1) next(); 363 | }; 364 | })(); 365 | 366 | // 设置css 367 | var css = (function() { 368 | var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ], 369 | cssProps = {}; 370 | 371 | function camelCase(string) { 372 | return string.replace(/^-ms-/, 'ms-').replace(/-([\da-z])/gi, function(match, letter) { 373 | return letter.toUpperCase(); 374 | }); 375 | } 376 | 377 | function getVendorProp(name) { 378 | var style = document.body.style; 379 | if (name in style) return name; 380 | 381 | var i = cssPrefixes.length, 382 | capName = name.charAt(0).toUpperCase() + name.slice(1), 383 | vendorName; 384 | while (i--) { 385 | vendorName = cssPrefixes[i] + capName; 386 | if (vendorName in style) return vendorName; 387 | } 388 | 389 | return name; 390 | } 391 | 392 | function getStyleProp(name) { 393 | name = camelCase(name); 394 | return cssProps[name] || (cssProps[name] = getVendorProp(name)); 395 | } 396 | 397 | function applyCss(element, prop, value) { 398 | prop = getStyleProp(prop); 399 | element.style[prop] = value; 400 | } 401 | 402 | return function(element, properties) { 403 | var args = arguments, 404 | prop, 405 | value; 406 | 407 | if (args.length == 2) { 408 | for (prop in properties) { 409 | value = properties[prop]; 410 | if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value); 411 | } 412 | } else { 413 | applyCss(element, args[1], args[2]); 414 | } 415 | } 416 | })(); 417 | 418 | /** 419 | * (Internal) Determines if an element or space separated list of class names contains a class name. 420 | */ 421 | 422 | function hasClass(element, name) { 423 | var list = typeof element == 'string' ? element : classList(element); 424 | return list.indexOf(' ' + name + ' ') >= 0; 425 | } 426 | 427 | /** 428 | * (Internal) Adds a class to an element. 429 | */ 430 | 431 | function addClass(element, name) { 432 | var oldList = classList(element), 433 | newList = oldList + name; 434 | 435 | if (hasClass(oldList, name)) return; 436 | 437 | // Trim the opening space. 438 | element.className = newList.substring(1); 439 | } 440 | 441 | /** 442 | * (Internal) Removes a class from an element. 443 | */ 444 | 445 | function removeClass(element, name) { 446 | var oldList = classList(element), 447 | newList; 448 | 449 | if (!hasClass(element, name)) return; 450 | 451 | // Replace the class name. 452 | newList = oldList.replace(' ' + name + ' ', ' '); 453 | 454 | // Trim the opening and closing spaces. 455 | element.className = newList.substring(1, newList.length - 1); 456 | } 457 | 458 | /** 459 | * (Internal) Gets a space separated list of the class names on the element. 460 | * The list is wrapped with a single space on each end to facilitate finding 461 | * matches within the list. 462 | */ 463 | 464 | function classList(element) { 465 | return (' ' + (element && element.className || '') + ' ').replace(/\s+/gi, ' '); 466 | } 467 | 468 | /** 469 | * (Internal) Removes an element from the DOM. 470 | */ 471 | 472 | function removeElement(element) { 473 | element && element.parentNode && element.parentNode.removeChild(element); 474 | } 475 | 476 | return NProgress; 477 | }); 478 | -------------------------------------------------------------------------------- /requirejs/requireJs-define.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/requirejs/requireJs-define.xmind -------------------------------------------------------------------------------- /requirejs/requireJs.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/requirejs/requireJs.xmind -------------------------------------------------------------------------------- /requirejs/requireJs实例流程.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quyinggang/js-sourcecode/abead6e4b2f8590b96230adc3f8d0061d052e2cc/requirejs/requireJs实例流程.xmind -------------------------------------------------------------------------------- /vue-cli-webpack-config/build/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | require('./check-versions')() 3 | 4 | process.env.NODE_ENV = 'production' 5 | 6 | // 终端loading 7 | const ora = require('ora') 8 | // rm命令 9 | const rm = require('rimraf') 10 | const path = require('path') 11 | const chalk = require('chalk') 12 | const webpack = require('webpack') 13 | const config = require('../config') 14 | const webpackConfig = require('./webpack.prod.conf') 15 | 16 | // 开始编译:显示loading图标 17 | const spinner = ora('building for production...') 18 | spinner.start() 19 | 20 | // 删除以前的输出目录,调用webpack重新打包 21 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 22 | if (err) throw err 23 | // 调用webpack方法打包 24 | webpack(webpackConfig, (err, stats) => { 25 | spinner.stop() 26 | if (err) throw err 27 | // 指定终端输出信息 28 | process.stdout.write(stats.toString({ 29 | colors: true, 30 | modules: false, 31 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. 32 | chunks: false, 33 | chunkModules: false 34 | }) + '\n\n') 35 | 36 | if (stats.hasErrors()) { 37 | console.log(chalk.red(' Build failed with errors.\n')) 38 | process.exit(1) 39 | } 40 | 41 | console.log(chalk.cyan(' Build complete.\n')) 42 | console.log(chalk.yellow( 43 | ' Tip: built files are meant to be served over an HTTP server.\n' + 44 | ' Opening index.html over file:// won\'t work.\n' 45 | )) 46 | }) 47 | }) 48 | -------------------------------------------------------------------------------- /vue-cli-webpack-config/build/check-versions.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const chalk = require('chalk') 3 | // 版本命名规范检查 4 | const semver = require('semver') 5 | const packageConfig = require('../package.json') 6 | // 跨平台shell实现 7 | const shell = require('shelljs') 8 | 9 | function exec (cmd) { 10 | return require('child_process').execSync(cmd).toString().trim() 11 | } 12 | 13 | const versionRequirements = [ 14 | { 15 | name: 'node', 16 | currentVersion: semver.clean(process.version), 17 | versionRequirement: packageConfig.engines.node 18 | } 19 | ] 20 | 21 | if (shell.which('npm')) { 22 | versionRequirements.push({ 23 | name: 'npm', 24 | currentVersion: exec('npm --version'), 25 | versionRequirement: packageConfig.engines.npm 26 | }) 27 | } 28 | 29 | // 检查node和npm版本 30 | module.exports = function () { 31 | const warnings = [] 32 | 33 | for (let i = 0; i < versionRequirements.length; i++) { 34 | const mod = versionRequirements[i] 35 | 36 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 37 | warnings.push(mod.name + ': ' + 38 | chalk.red(mod.currentVersion) + ' should be ' + 39 | chalk.green(mod.versionRequirement) 40 | ) 41 | } 42 | } 43 | 44 | if (warnings.length) { 45 | console.log('') 46 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 47 | console.log() 48 | 49 | for (let i = 0; i < warnings.length; i++) { 50 | const warning = warnings[i] 51 | console.log(' ' + warning) 52 | } 53 | 54 | console.log() 55 | process.exit(1) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /vue-cli-webpack-config/build/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const config = require('../config') 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 5 | const packageConfig = require('../package.json') 6 | 7 | exports.assetsPath = function (_path) { 8 | const assetsSubDirectory = process.env.NODE_ENV === 'production' 9 | ? config.build.assetsSubDirectory 10 | : config.dev.assetsSubDirectory 11 | 12 | return path.posix.join(assetsSubDirectory, _path) 13 | } 14 | 15 | // 支持css、postcss、less、sass、scss、stylus 16 | exports.cssLoaders = function (options) { 17 | options = options || {} 18 | 19 | const cssLoader = { 20 | loader: 'css-loader', 21 | options: { 22 | sourceMap: options.sourceMap 23 | } 24 | } 25 | 26 | const postcssLoader = { 27 | loader: 'postcss-loader', 28 | options: { 29 | sourceMap: options.sourceMap 30 | } 31 | } 32 | 33 | // generate loader string to be used with extract text plugin 34 | function generateLoaders (loader, loaderOptions) { 35 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] 36 | 37 | if (loader) { 38 | loaders.push({ 39 | loader: loader + '-loader', 40 | options: Object.assign({}, loaderOptions, { 41 | sourceMap: options.sourceMap 42 | }) 43 | }) 44 | } 45 | 46 | // Extract CSS when that option is specified 47 | // (which is the case during production build) 48 | if (options.extract) { 49 | return ExtractTextPlugin.extract({ 50 | use: loaders, 51 | fallback: 'vue-style-loader' 52 | }) 53 | } else { 54 | return ['vue-style-loader'].concat(loaders) 55 | } 56 | } 57 | 58 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html 59 | return { 60 | css: generateLoaders(), 61 | postcss: generateLoaders(), 62 | less: generateLoaders('less'), 63 | sass: generateLoaders('sass', { indentedSyntax: true }), 64 | scss: generateLoaders('sass'), 65 | stylus: generateLoaders('stylus'), 66 | styl: generateLoaders('stylus') 67 | } 68 | } 69 | 70 | // Generate loaders for standalone style files (outside of .vue) 71 | exports.styleLoaders = function (options) { 72 | const output = [] 73 | const loaders = exports.cssLoaders(options) 74 | 75 | for (const extension in loaders) { 76 | const loader = loaders[extension] 77 | output.push({ 78 | test: new RegExp('\\.' + extension + '$'), 79 | use: loader 80 | }) 81 | } 82 | 83 | return output 84 | } 85 | 86 | exports.createNotifierCallback = () => { 87 | const notifier = require('node-notifier') 88 | 89 | return (severity, errors) => { 90 | if (severity !== 'error') return 91 | 92 | const error = errors[0] 93 | const filename = error.file && error.file.split('!').pop() 94 | 95 | notifier.notify({ 96 | title: packageConfig.name, 97 | message: severity + ': ' + error.name, 98 | subtitle: filename || '', 99 | icon: path.join(__dirname, 'logo.png') 100 | }) 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /vue-cli-webpack-config/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const config = require('../config') 4 | const isProduction = process.env.NODE_ENV === 'production' 5 | const sourceMapEnabled = isProduction 6 | ? config.build.productionSourceMap 7 | : config.dev.cssSourceMap 8 | 9 | module.exports = { 10 | loaders: utils.cssLoaders({ 11 | // 生成.map文件便于调试 12 | sourceMap: sourceMapEnabled, 13 | // 是否使用extract-text-webpack-plugin插件将文件的中的css部分抽离出来生成单独的css文件 14 | extract: isProduction 15 | }), 16 | // vue-loader参数:是否开启CSS source maps 17 | cssSourceMap: sourceMapEnabled, 18 | // vue-loader参数:是否要缓存文件,可以让浏览器不缓存,即动态生成文件中加入hash就会让每一次构建的文件都不同 19 | cacheBusting: config.dev.cacheBusting, 20 | // 解决Vue中src需要使用require先导入的问题,这里统一配置 21 | transformToRequire: { 22 | video: ['src', 'poster'], 23 | source: 'src', 24 | img: 'src', 25 | // svg的image标签 26 | image: 'xlink:href' 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /vue-cli-webpack-config/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const config = require('../config') 5 | const vueLoaderConfig = require('./vue-loader.conf') 6 | 7 | // 返回指定目录的绝对路径 8 | function resolve (dir) { 9 | return path.join(__dirname, '..', dir) 10 | } 11 | 12 | const createLintingRule = () => ({ 13 | test: /\.(js|vue)$/, 14 | loader: 'eslint-loader', 15 | // enforce: pre | post, loader使用优先级定义,定义了pre会优先于其他同类型相同模块使用loader解析 16 | enforce: 'pre', 17 | // include表示必须匹配的目录 18 | include: [resolve('src'), resolve('test')], 19 | options: { 20 | // eslint-friendly-formatter插件会将eslint详细输出到控制台 21 | formatter: require('eslint-friendly-formatter'), 22 | // 是否显示警告信息 23 | emitWarning: !config.dev.showEslintErrorsInOverlay 24 | } 25 | }) 26 | 27 | module.exports = { 28 | // 绝对路径的基础目录即解析entry和loader的目录,默认当前目录 29 | context: path.resolve(__dirname, '../'), 30 | // 入口 31 | entry: { 32 | app: './src/main.js' 33 | }, 34 | // 输出 35 | output: { 36 | // 指定编译输出目录 37 | path: config.build.assetsRoot, 38 | // 输出文件名称 39 | filename: '[name].js', 40 | // 配置输出目录对应的公开URL 41 | publicPath: process.env.NODE_ENV === 'production' 42 | ? config.build.assetsPublicPath 43 | : config.dev.assetsPublicPath 44 | }, 45 | // 模块解析规则 46 | resolve: { 47 | // 省略模块扩展匹配规则 48 | extensions: ['.js', '.vue', '.json'], 49 | // 模块别名 50 | alias: { 51 | 'vue$': 'vue/dist/vue.esm.js', 52 | '@': resolve('src'), 53 | } 54 | }, 55 | module: { 56 | // 定义loader 57 | rules: [ 58 | ...(config.dev.useEslint ? [createLintingRule()] : []), 59 | { 60 | test: /\.vue$/, 61 | loader: 'vue-loader', 62 | options: vueLoaderConfig 63 | }, 64 | { 65 | test: /\.js$/, 66 | loader: 'babel-loader', 67 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] 68 | }, 69 | { 70 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 71 | loader: 'url-loader', 72 | options: { 73 | limit: 10000, 74 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 75 | } 76 | }, 77 | { 78 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 79 | loader: 'url-loader', 80 | options: { 81 | limit: 10000, 82 | name: utils.assetsPath('media/[name].[hash:7].[ext]') 83 | } 84 | }, 85 | { 86 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 87 | loader: 'url-loader', 88 | options: { 89 | limit: 10000, 90 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 91 | } 92 | } 93 | ] 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /vue-cli-webpack-config/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const webpack = require('webpack') 4 | const path = require('path') 5 | const config = require('../config') 6 | // 公用webpack配置 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | // webpack配置文件合并插件 9 | const merge = require('webpack-merge') 10 | // 复制插件 11 | const CopyWebpackPlugin = require('copy-webpack-plugin') 12 | // 生成HTML插件 13 | const HtmlWebpackPlugin = require('html-webpack-plugin') 14 | // 清理webpack编译输出的信息 15 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 16 | // 端口扫描 17 | const portfinder = require('portfinder') 18 | 19 | // 获取域名和端口 20 | const HOST = process.env.HOST 21 | const PORT = process.env.PORT && Number(process.env.PORT) 22 | 23 | const devWebpackConfig = merge(baseWebpackConfig, { 24 | // 定义对模块源代码转换的loader 25 | module: { 26 | // 重新定义Style相关的loader 27 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) 28 | }, 29 | /** 30 | * 选择source map,用于开发环境的增强调试 31 | * cheap-module-eval-source-map是开发环境速度最快的 32 | */ 33 | devtool: config.dev.devtool, 34 | 35 | // 本地开发服务,相关配置都在/config/index.js文件中 36 | devServer: { 37 | // 控制台log等级,默认是info输出所有信息;warning表示只输出警告和错误信息 38 | clientLogLevel: 'warning', 39 | // 查不到指定路由时的方案 40 | historyApiFallback: { 41 | rewrites: [ 42 | // 找不到路由时就跳转到首页 43 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, 44 | ], 45 | }, 46 | // 是否启用热替换 47 | hot: true, 48 | // 告诉服务器从哪个目录中提供内容,默认情况下使用当前工作目录作为提供内容的目录 49 | // false表示禁用 50 | contentBase: false, 51 | // 是否启用gzip压缩 52 | compress: true, 53 | // 域名,默认是localhost,如果希望服务器外部可访问,设置为0.0.0.0 54 | host: HOST || config.dev.host, 55 | // 端口 56 | port: PORT || config.dev.port, 57 | // 是否允许server打开浏览器 58 | open: config.dev.autoOpenBrowser, 59 | // 是否在浏览器中显示编译器错误或警告 60 | overlay: config.dev.errorOverlay 61 | ? { warnings: false, errors: true } 62 | : false, 63 | // 可在浏览器中访问的打包文件,默认是/ 64 | publicPath: config.dev.assetsPublicPath, 65 | // 设置代理,主要用于解决前后端分离时跨域问题 66 | proxy: config.dev.proxyTable, 67 | // webpack错误或警告在控制台是否不显示,true表示不显示 68 | quiet: true, 69 | // 定制watch模式的选项 70 | watchOptions: { 71 | // 是否检查变动 72 | poll: config.dev.poll, 73 | } 74 | }, 75 | // 插件使用 76 | plugins: [ 77 | // 允许在编译时配置全局常量,对于区分生产和开发环境定制不同行为非常有用 78 | new webpack.DefinePlugin({ 79 | 'process.env': require('../config/dev.env') 80 | }), 81 | // 启用模块热替换 82 | new webpack.HotModuleReplacementPlugin(), 83 | // 开启模块热替换时使用该插件会显示模块相对路径 84 | new webpack.NamedModulesPlugin(), 85 | // webpack编译出现错误使用该插件跳过输出阶段,保证输出资源不会包含错误 86 | new webpack.NoEmitOnErrorsPlugin(), 87 | // 动态生成html 88 | new HtmlWebpackPlugin({ 89 | filename: 'index.html', 90 | template: 'index.html', 91 | inject: true 92 | }), 93 | // 文件复制插件,常用于将文件复制到编译后的目录中 94 | new CopyWebpackPlugin([ 95 | { 96 | from: path.resolve(__dirname, '../static'), 97 | to: config.dev.assetsSubDirectory, 98 | ignore: ['.*'] 99 | } 100 | ]) 101 | ] 102 | }) 103 | 104 | module.exports = new Promise((resolve, reject) => { 105 | portfinder.basePort = process.env.PORT || config.dev.port 106 | // 端口扫描,当指定端口被占用,自动跳转到下一个端口 107 | portfinder.getPort((err, port) => { 108 | if (err) { 109 | reject(err) 110 | } else { 111 | process.env.PORT = port 112 | devWebpackConfig.devServer.port = port 113 | 114 | // 控制台输出信息控制插件friendly-errors-webpack-plugin 115 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ 116 | // 编译成功后的提示 117 | compilationSuccessInfo: { 118 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], 119 | }, 120 | // 错误信息 121 | onErrors: config.dev.notifyOnErrors 122 | ? utils.createNotifierCallback() 123 | : undefined 124 | })) 125 | 126 | resolve(devWebpackConfig) 127 | } 128 | }) 129 | }) 130 | -------------------------------------------------------------------------------- /vue-cli-webpack-config/build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const webpack = require('webpack') 5 | const config = require('../config') 6 | const merge = require('webpack-merge') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | // 抽取CSS形成单独文件插件 11 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 12 | // 压缩css插件 13 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') 14 | // 压缩JS插件 15 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin') 16 | 17 | const env = require('../config/prod.env') 18 | 19 | const webpackConfig = merge(baseWebpackConfig, { 20 | module: { 21 | // Style loader相关处理 22 | rules: utils.styleLoaders({ 23 | sourceMap: config.build.productionSourceMap, 24 | extract: true, 25 | usePostCSS: true 26 | }) 27 | }, 28 | devtool: config.build.productionSourceMap ? config.build.devtool : false, 29 | output: { 30 | path: config.build.assetsRoot, 31 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 32 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 33 | }, 34 | plugins: [ 35 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 36 | new webpack.DefinePlugin({ 37 | 'process.env': env 38 | }), 39 | // JS压缩 40 | new UglifyJsPlugin({ 41 | uglifyOptions: { 42 | compress: { 43 | warnings: false 44 | } 45 | }, 46 | sourceMap: config.build.productionSourceMap, 47 | parallel: true 48 | }), 49 | // 抽取CSS到单独文件中 50 | new ExtractTextPlugin({ 51 | filename: utils.assetsPath('css/[name].[contenthash].css'), 52 | allChunks: true, 53 | }), 54 | // 优化CSS 55 | new OptimizeCSSPlugin({ 56 | cssProcessorOptions: config.build.productionSourceMap 57 | ? { safe: true, map: { inline: false } } 58 | : { safe: true } 59 | }), 60 | // 动态生成HTML 61 | new HtmlWebpackPlugin({ 62 | filename: config.build.index, 63 | template: 'index.html', 64 | inject: true, 65 | minify: { 66 | // 移除注释 67 | removeComments: true, 68 | // 删除空格 69 | collapseWhitespace: true, 70 | // 属性双引号 71 | removeAttributeQuotes: true 72 | // more options: 73 | // https://github.com/kangax/html-minifier#options-quick-reference 74 | }, 75 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 76 | chunksSortMode: 'dependency' 77 | }), 78 | // 根据模块的相对路径生成四位数hash作为模块id,用于避免vendor hash变化 79 | new webpack.HashedModuleIdsPlugin(), 80 | // 提升或预编译模块 81 | new webpack.optimize.ModuleConcatenationPlugin(), 82 | // 抽取第三方库到vendor 83 | new webpack.optimize.CommonsChunkPlugin({ 84 | name: 'vendor', 85 | minChunks (module) { 86 | // 引入node_modules中模块会被抽取 87 | return ( 88 | module.resource && 89 | /\.js$/.test(module.resource) && 90 | module.resource.indexOf( 91 | path.join(__dirname, '../node_modules') 92 | ) === 0 93 | ) 94 | } 95 | }), 96 | /** 97 | * 抽取manifest(manifest文件包含了加载和处理模块的逻辑,防止vendor重复编译) 98 | * 实际上就是将webpackJsonp和__webpack__require__逻辑抽离出来 99 | */ 100 | new webpack.optimize.CommonsChunkPlugin({ 101 | name: 'manifest', 102 | minChunks: Infinity 103 | }), 104 | // 当不同异步加载模块中引用相同模块3次以上就会抽离引用模块为公共模块,防止重复打包 105 | new webpack.optimize.CommonsChunkPlugin({ 106 | name: 'app', 107 | async: 'vendor-async', 108 | children: true, 109 | minChunks: 3 110 | }), 111 | // 拷贝static目录到输出目录 112 | new CopyWebpackPlugin([ 113 | { 114 | from: path.resolve(__dirname, '../static'), 115 | to: config.build.assetsSubDirectory, 116 | ignore: ['.*'] 117 | } 118 | ]) 119 | ] 120 | }) 121 | 122 | // 开启gzip压缩,该插件会提供压缩版本 123 | if (config.build.productionGzip) { 124 | const CompressionWebpackPlugin = require('compression-webpack-plugin') 125 | 126 | webpackConfig.plugins.push( 127 | new CompressionWebpackPlugin({ 128 | asset: '[path].gz[query]', 129 | algorithm: 'gzip', 130 | test: new RegExp( 131 | '\\.(' + 132 | config.build.productionGzipExtensions.join('|') + 133 | ')$' 134 | ), 135 | threshold: 10240, 136 | minRatio: 0.8 137 | }) 138 | ) 139 | } 140 | 141 | // 可视化输出文件大小 142 | if (config.build.bundleAnalyzerReport) { 143 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 144 | webpackConfig.plugins.push(new BundleAnalyzerPlugin()) 145 | } 146 | 147 | module.exports = webpackConfig 148 | -------------------------------------------------------------------------------- /vue-cli-webpack-config/config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /vue-cli-webpack-config/config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.3.1 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | 7 | // 定义开发环境和生产环境相关配置 8 | module.exports = { 9 | dev: { 10 | 11 | // Paths 12 | assetsSubDirectory: 'static', 13 | assetsPublicPath: '/', 14 | proxyTable: {}, 15 | 16 | // Various Dev Server settings 17 | host: 'localhost', // can be overwritten by process.env.HOST 18 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 19 | autoOpenBrowser: false, 20 | errorOverlay: true, 21 | notifyOnErrors: true, 22 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 23 | 24 | // Use Eslint Loader? 25 | // If true, your code will be linted during bundling and 26 | // linting errors and warnings will be shown in the console. 27 | useEslint: true, 28 | // If true, eslint errors and warnings will also be shown in the error overlay 29 | // in the browser. 30 | showEslintErrorsInOverlay: false, 31 | 32 | /** 33 | * Source Maps 34 | */ 35 | 36 | // https://webpack.js.org/configuration/devtool/#development 37 | devtool: 'cheap-module-eval-source-map', 38 | 39 | // If you have problems debugging vue-files in devtools, 40 | // set this to false - it *may* help 41 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 42 | cacheBusting: true, 43 | 44 | cssSourceMap: true 45 | }, 46 | 47 | build: { 48 | // Template for index.html 49 | index: path.resolve(__dirname, '../dist/index.html'), 50 | 51 | // Paths 52 | assetsRoot: path.resolve(__dirname, '../dist'), 53 | assetsSubDirectory: 'static', 54 | assetsPublicPath: '/', 55 | 56 | /** 57 | * Source Maps 58 | */ 59 | 60 | productionSourceMap: true, 61 | // https://webpack.js.org/configuration/devtool/#production 62 | devtool: '#source-map', 63 | 64 | // Gzip off by default as many popular static hosts such as 65 | // Surge or Netlify already gzip all static assets for you. 66 | // Before setting to `true`, make sure to: 67 | // npm install --save-dev compression-webpack-plugin 68 | productionGzip: false, 69 | productionGzipExtensions: ['js', 'css'], 70 | 71 | // Run the build command with an extra argument to 72 | // View the bundle analyzer report after build finishes: 73 | // `npm run build --report` 74 | // Set to `true` or `false` to always turn it on or off 75 | bundleAnalyzerReport: process.env.npm_config_report 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /vue-cli-webpack-config/config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | --------------------------------------------------------------------------------