| <!DOCTYPE html><html lang="en-US"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1" user-scalable="no"><meta name="description" content="ECharts, a powerful, interactive charting and visualization library for browser"><link rel="shortcut icon" href="images/favicon.png"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"><!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries--><!--[if lt IE 9]><script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script><script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script><![endif]--><link rel="stylesheet" type="text/css" href="./css/main.css?_v_=1571425310596"><script>window.EC_WWW_LANG = 'en'; |
| </script><script type="text/javascript" src="./vendors/pace/pace.min.js"></script><script id="font-hack" type="text/javascript">if (/windows/i.test(navigator.userAgent)) { |
| var el = document.createElement('style'); |
| el.innerHTML = '' |
| + '@font-face {font-family:"noto-thin";src:local("Microsoft Yahei");}' |
| + '@font-face {font-family:"noto-light";src:local("Microsoft Yahei");}'; |
| document.head.insertBefore(el, document.getElementById('font-hack')); |
| } |
| </script><title>Coding Standard - Apache ECharts (incubating)</title><link rel="stylesheet" type="text/css" href="./vendors/prettify/prettify.css"><script type="text/javascript" src="./vendors/prettify/prettify.js"></script><script type="text/javascript" src="./vendors/prettify/lang-css.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@2.2.4/dist/jquery.min.js"></script></head><!--[if lte IE 8]><body class="lower-ie"><div id="lowie-main"><img src="./images/forie.png" alt="ie tip"></div></body><![endif]--> |
| <!--[if (gt IE 8)|!(IE)]><body class="undefined"></body><![endif]--><div id="apache-banner"><div class="txt"><p>Apache ECharts is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator.</p><p>We are working on redirecting this Website to <a href="https://echarts.apache.org" target="_blank">https://echarts.apache.org</a>. You may visit our new official Website now.</p></div><a href="https://echarts.apache.org" target="_blank" onclick="logApache()" class="btn"><div>Visit Official Website</div></a><a href="javascript:;" onclick="closeApacheBanner(true)" class="close-btn">x</a></div><div id="main"><nav class="navbar navbar-default navbar-fixed-top"><div class="container-fluid"><div class="navbar-header"><button type="button" data-toggle="collapse" data-target="#navbar-collapse" aria-expanded="false" class="navbar-toggle collapsed"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="https://echarts.apache.org/en/index.html" class="navbar-brand"><img src="https://echarts.apache.org/en/images/logo.png" alt="echarts logo" class="navbar-logo"></a></div><div id="navbar-collapse" class="collapse navbar-collapse"><ul class="nav navbar-nav navbar-left"><li id="nav-index"><a href="https://echarts.apache.org/en/index.html">Home</a></li><li id="nav-doc" class="dropdown"><a href="#" data-toggle="dropdown" class="dropdown-toggle">Documents<b class="caret"></b></a><ul class="dropdown-menu"><li><a href="https://echarts.apache.org/en/feature.html">Features</a></li><li><a href="https://echarts.apache.org/en/tutorial.html">Tutorials</a></li><li><a href="https://echarts.apache.org/en/api.html">API</a></li><li><a href="https://echarts.apache.org/en/cheat-sheet.html">Cheat Sheet<span class="new">NEW</span></a></li><li><a href="https://echarts.apache.org/en/option.html">Chart Configuration</a></li><li><a href="https://echarts.apache.org/en/option-gl.html">GL Configuration (Chinese)</a></li><li><a href="https://echarts.apache.org/en/changelog.html">Changelog</a></li></ul></li><li id="nav-download" class="dropdown"><a href="#" data-toggle="dropdown" class="dropdown-toggle">Download<b class="caret"></b></a><ul class="dropdown-menu"><li><a href="https://echarts.apache.org/en/download.html">Download</a></li><li><a href="https://echarts.apache.org/en/download-theme.html">Download Themes</a></li><li><a href="https://echarts.apache.org/en/download-extension.html">Download Extensions</a></li></ul></li><li id="nav-examples"><a href="#" data-toggle="dropdown" class="dropdown-toggle">Examples<b class="caret"></b></a><ul class="dropdown-menu"><li><a href="https://echarts.apache.org/examples/en/">ECharts Examples</a></li><li><a href="https://echarts.apache.org/examples/en/index.html#chart-type-globe">GL Examples</a></li></ul></li><li id="nav-contribute"><a href="#" data-toggle="dropdown" class="dropdown-toggle">Contribute<b class="caret"></b></a><ul class="dropdown-menu"><li><a href="https://github.com/apache/incubator-echarts" target="_blank">Source Code (GitHub)</a></li><li><a href="https://github.com/apache/incubator-echarts/issues" target="_blank">Issue Tracking</a></li><li><a href="https://echarts.apache.org/en/coding-standard.html">Code Standard</a></li></ul></li><li id="nav-about"><a href="#" data-toggle="dropdown" class="dropdown-toggle">About<b class="caret"></b></a><ul class="dropdown-menu"><li><a href="https://echarts.apache.org/en/committers.html">Committers</a></li><li><a href="https://www.apache.org/licenses/">License</a></li><li><a href="https://echarts.apache.org/en/maillist.html">Mailing List</a></li><li><a href="https://echarts.apache.org/en/dependencies.html">Dependencies</a></li><li><a href="https://echarts.apache.org/en/faq.html">FAQ</a></li></ul></li></ul><ul class="nav navbar-nav navbar-right"><li id="nav-github"><a href="https://github.com/ecomfe/echarts" target="_blank"><img src="https://echarts.apache.org/en/images/github.png" width="18"></a></li><li id="nav-homeen"><a href="javascript:;" onclick="changeLang('zh')">中文</a></li></ul></div></div></nav><div class="page-info"><h1>Coding Standard</h1><p>Please follow this standard when contribute to ECharts project.</p></div><div class="page-content single-page"><div class="page-nav"><ul id="standard-nav"></ul></div><div class="page-detail"><h2 id="code-style">Code Style</h2> |
| <h3 id="file">File</h3> |
| <p><strong>[MUST]</strong> JavaScript Source files must be encoded in UTF-8 without BOM.</p> |
| <h3 id="indentation">Indentation</h3> |
| <p><strong>[MUST]</strong> 4 space indentation. tabs and 2 space are not allowed.</p> |
| <p><strong>[MUST]</strong> <code>case</code> and <code>default</code> in <code>switch</code> must be indented.</p> |
| <pre><code class="lang-js">// good |
| switch (variable) { |
| case '1': |
| // do... |
| break; |
| case '2': |
| // do... |
| break; |
| default: |
| // do... |
| } |
| |
| // bad |
| switch (variable) { |
| case '1': |
| // do... |
| break; |
| case '2': |
| // do... |
| break; |
| default: |
| // do... |
| } |
| </code></pre> |
| <h3 id="space">Space</h3> |
| <p><strong>[MUST]</strong> Set off binary operator with spaces. But place no space between unary operator and its operand.</p> |
| <pre><code class="lang-js">var a = !arr.length; |
| a++; |
| a = b + c; |
| </code></pre> |
| <p><strong>[MUST]</strong> Place 1 space before the leading brace.</p> |
| <pre><code class="lang-js">// good |
| |
| if (condition) { |
| } |
| |
| set('attr', { |
| some: 'xxx', |
| any: 'yyy' |
| }); |
| |
| function funcName() { |
| } |
| |
| |
| // bad |
| |
| if (condition){ |
| } |
| |
| set('attr',{ |
| some: 'xxx', |
| any: 'yyy' |
| }); |
| |
| function funcName(){ |
| } |
| </code></pre> |
| <p><strong>[MUST]</strong> Place 1 space after <code>if</code> / <code>else</code> / <code>for</code> / <code>while</code> / <code>function</code> / <code>switch</code> / <code>do</code> / <code>try</code> / <code>catch</code> / <code>finally</code>.</p> |
| <pre><code class="lang-js">// good |
| |
| if (condition) { |
| } |
| |
| while (condition) { |
| } |
| |
| (function () { |
| })(); |
| |
| |
| // bad |
| |
| if(condition) { |
| } |
| |
| while(condition) { |
| } |
| |
| (function() { |
| })(); |
| </code></pre> |
| <p><strong>[MUST]</strong> In the object creating statement, place 1 space after <code>:</code>, but no space before it.</p> |
| <pre><code class="lang-js">// good |
| var obj = { |
| a: 1, |
| b: 2, |
| c: 3 |
| }; |
| |
| // bad |
| var obj = { |
| a : 1, |
| b:2, |
| c :3 |
| }; |
| </code></pre> |
| <p><strong>[MUST]</strong> Place no space between the function name and <code>(</code> in function declaration, expression of named function and function call.</p> |
| <pre><code class="lang-js">// good |
| |
| function funcName() { |
| } |
| |
| var funcName = function funcName() { |
| }; |
| |
| funcName(); |
| |
| |
| // bad |
| |
| function funcName () { |
| } |
| |
| var funcName = function funcName () { |
| }; |
| |
| funcName (); |
| </code></pre> |
| <p><strong>[MUST]</strong> Place no space between <code>,</code> and <code>;</code>.</p> |
| <pre><code class="lang-js">// good |
| callFunc(a, b); |
| |
| // bad |
| callFunc(a , b) ; |
| </code></pre> |
| <p><strong>[MUST]</strong> Place no space after <code>(</code> and <code>[</code> and before <code>)</code> and <code>]</code>.</p> |
| <pre><code class="lang-js">// good |
| |
| callFunc(param1, param2, param3); |
| |
| save(this.list[this.indexes[i]]); |
| |
| needIncream && (variable += increament); |
| |
| if (num > list.length) { |
| } |
| |
| while (len--) { |
| } |
| |
| |
| // bad |
| |
| callFunc( param1, param2, param3 ); |
| |
| save( this.list[ this.indexes[ i ] ] ); |
| |
| needIncreament && ( variable += increament ); |
| |
| if ( num > list.length ) { |
| } |
| |
| while ( len-- ) { |
| } |
| |
| |
| // good |
| var arr1 = []; |
| var arr2 = [1, 2, 3]; |
| var obj1 = {}; |
| var obj2 = {name: 'obj'}; |
| var obj3 = { |
| name: 'obj', |
| age: 20, |
| sex: 1 |
| }; |
| |
| // bad |
| var arr1 = [ ]; |
| var arr2 = [ 1, 2, 3 ]; |
| var obj1 = { }; |
| var obj2 = { name: 'obj' }; |
| var obj3 = {name: 'obj', age: 20, sex: 1}; |
| </code></pre> |
| <p><strong>[MUST]</strong> Must no trailing space in each line.</p> |
| <h3 id="line-break">Line Break</h3> |
| <p><strong>[MUST]</strong> Place line break in the end of a statement.</p> |
| <p><strong>[MUST]</strong> No more than 120 characters per line.</p> |
| <p><strong>[MUST]</strong> Place operator at the beginning of a line if it break lines.</p> |
| <pre><code class="lang-js">// good |
| if (user.isAuthenticated() |
| && user.isInRole('admin') |
| && user.hasAuthority('add-admin') |
| || user.hasAuthority('delete-admin') |
| ) { |
| // Code |
| } |
| |
| var result = number1 + number2 + number3 |
| + number4 + number5; |
| |
| |
| // bad |
| if (user.isAuthenticated() && |
| user.isInRole('admin') && |
| user.hasAuthority('add-admin') || |
| user.hasAuthority('delete-admin')) { |
| // Code |
| } |
| |
| var result = number1 + number2 + number3 + |
| number4 + number5; |
| </code></pre> |
| <p><strong>[MUST]</strong> Start a new line for <code>)</code>, <code>]</code>, <code>}</code> if the content inside the brackets occupies multiple lines. |
| Make the same indent as the line where the corresponding <code>(</code>, <code>[</code>, <code>{</code> placed.</p> |
| <pre><code class="lang-js">// good |
| if (product) { |
| product.load(); |
| if (user.isAuthenticated() |
| && user.isInRole('admin') |
| && user.hasAuthority('add-admin') |
| ) { |
| sendProduct(user, product); |
| } |
| } |
| var arr = [ |
| 'candy', 'sugar' |
| ]; |
| |
| // bad |
| if (product) { |
| product.load(); |
| if (user.isAuthenticated() |
| && user.isInRole('admin') |
| && user.hasAuthority('add-admin')) { |
| sendProduct(user, product); |
| } |
| } |
| var arr = [ |
| 'candy', 'sugar' |
| ]; |
| </code></pre> |
| <p><strong>[MUST]</strong> Must not break lines before <code>,</code> or <code>;</code>.</p> |
| <pre><code class="lang-js">// good |
| var obj = { |
| a: 1, |
| b: 2, |
| c: 3 |
| }; |
| |
| foo( |
| aVeryVeryLongArgument, |
| anotherVeryLongArgument, |
| callback |
| ); |
| |
| |
| // bad |
| var obj = { |
| a: 1 |
| , b: 2 |
| , c: 3 |
| }; |
| |
| foo( |
| aVeryVeryLongArgument |
| , anotherVeryLongArgument |
| , callback |
| ); |
| </code></pre> |
| <p><strong>[SUGGEST]</strong> Suggestion about line break and indent:</p> |
| <pre><code class="lang-js">if (user.isAuthenticated() |
| && user.isInRole('admin') |
| && user.hasAuthority('add-admin') |
| ) { |
| // Code |
| } |
| |
| foo( |
| aVeryVeryLongArgument, |
| anotherVeryLongArgument, |
| callback |
| ); |
| |
| baidu.format( |
| dateFormatTemplate, |
| year, month, date, hour, minute, second |
| ); |
| |
| $('#items') |
| .find('.selected') |
| .highlight() |
| .end(); |
| |
| var result = thisIsAVeryVeryLongCondition |
| ? resultA : resultB; |
| |
| var result = condition |
| ? thisIsAVeryVeryLongResult |
| : resultB; |
| </code></pre> |
| <p><strong>[MUST]</strong> Start a new line for <code>else</code> and <code>catch</code> if using multi-line blocks.</p> |
| <pre><code class="lang-js">// good |
| |
| if (condition) { |
| // some statements; |
| } |
| else { |
| // some statements; |
| } |
| |
| try { |
| // some statements; |
| } |
| catch (ex) { |
| // some statements; |
| } |
| |
| |
| // bad |
| |
| if (condition) { |
| // some statements; |
| } else { |
| // some statements; |
| } |
| |
| try { |
| // some statements; |
| } catch (ex) { |
| // some statements; |
| } |
| </code></pre> |
| <h3 id="statement">Statement</h3> |
| <p><strong>[MUST]</strong> The comma must not be ignored at the end of a statement.</p> |
| <p><strong>[MUST]</strong> The <code>{}</code> must not be ignored even if there is only one line.</p> |
| <pre><code class="lang-js">// good |
| if (condition) { |
| callFunc(); |
| } |
| |
| // bad |
| if (condition) callFunc(); |
| if (condition) |
| callFunc(); |
| </code></pre> |
| <p><strong>[MUST]</strong> Place no comma at the end of a function definition.</p> |
| <pre><code class="lang-js">// good |
| function funcName() { |
| } |
| |
| // bad |
| function funcName() { |
| }; |
| |
| // For function expression, the comma must not be ignored. |
| var funcName = function () { |
| }; |
| </code></pre> |
| <p><strong>[MUST]</strong> No trailing comma in object and array declarations.</p> |
| <pre><code class="lang-js">// good |
| |
| var obj = { |
| attr1: 'xxx', |
| attr2: 'yyy' |
| }; |
| |
| var arr = [ |
| 'xxx', |
| 'yyy' |
| ]; |
| |
| |
| // bad |
| |
| var obj = { |
| attr1: 'xxx', |
| attr2: 'yyy', |
| }; |
| |
| var arr = [ |
| 'xxx', |
| 'yyy', |
| ]; |
| </code></pre> |
| <h3 id="naming-conventions">Naming Conventions</h3> |
| <p><strong>[MUST]</strong> Use lowerCamelCase for variables, properties and function names.</p> |
| <pre><code class="lang-js">var loadingModules = {}; |
| function loadProduct() { |
| } |
| </code></pre> |
| <p><strong>[MUST]</strong> Use UpperCamelCase (Pascal) for class names.</p> |
| <pre><code class="lang-js">function Element(options) { |
| } |
| </code></pre> |
| <p><strong>[SUGGEST]</strong> All of the letters of a abbreviation should be both upper cases or both lower cases.</p> |
| <pre><code class="lang-js">function parseSVG() { |
| } |
| var svgParser; |
| </code></pre> |
| <h2 id="language-features">Language features</h2> |
| <h3 id="compatibility">Compatibility</h3> |
| <p><strong>[MUST]</strong> The JavaScript code of ECharts should be based on <code>ECMAScript Language Specification Edition 3 (ES3)</code>. The language features that not supported by ES3 (namely, features that are only supported by ES5, ES6 or upper versions) must not be used.</p> |
| <p>But there is an exception that ES Module can be used.</p> |
| <p>Language features can be polyfilled by some utilities, but must not by modifying the prototype of the built-in JS objects.</p> |
| <pre><code class="lang-js">// good |
| |
| import * as zrUtil from 'zrender/src/core/util'; |
| |
| zrUtil.each(array, function (val, index) { |
| sum += val; |
| }); |
| |
| var result = zrUtil.map(array, function (val) { |
| return parse(val); |
| }); |
| |
| var pos = zrUtil.indexOf(array, val); |
| |
| var obj2 = zrUtil.extend({}, obj1); |
| |
| function Element() { |
| // ... |
| } |
| |
| |
| // bad |
| |
| array.forEach(function (val, index) { |
| sum += val; |
| }); |
| |
| let result = array.map(function (val) { |
| return parse(val); |
| }); |
| |
| const pos = array.indexOf(val); |
| |
| var obj2 = Object.assign({}, obj1); |
| |
| class Element { |
| // ... |
| } |
| |
| String.prototype.trim = function () { |
| }; |
| </code></pre> |
| <h3 id="variable">Variable</h3> |
| <p><strong>[MUST]</strong> Variables must be declared by <code>var</code>. And a <code>var</code> can not declares more than one variable.</p> |
| <pre><code class="lang-js">// good |
| var name = 'MyName'; |
| var hangModules = []; |
| var missModules = []; |
| var visited = {}; |
| |
| // bad |
| name = 'MyName'; |
| var hangModules = [], |
| missModules = [], |
| visited = {}; |
| </code></pre> |
| <h3 id="condition">Condition</h3> |
| <p><strong>[MUST]</strong> In equality expression, <code>==</code> can only be used on <code>null</code> or <code>undefined</code> detection. <code>===</code> should be used in the rest of cases .</p> |
| <pre><code class="lang-js">// good |
| if (age === 30) { |
| // ... |
| } |
| if (type == null) { |
| // ... |
| } |
| |
| // bad |
| if (age == 30) { |
| // ...... |
| } |
| </code></pre> |
| <p><strong>[SUGGEST]</strong> Use <code>xxx == null</code> to determine <code>null</code> or <code>undefined</code>.</p> |
| <p><strong>[SUGGEST]</strong> Try best to make the meaning of <code>null</code> and <code>undefined</code> the same, namely, do not make users or developers distinguishing whether a variable is <code>null</code> or <code>undefined</code>.</p> |
| <p><strong>[SUGGEST]</strong> The function expression or function declaration should not be placed inside a loop body.</p> |
| <pre><code class="lang-js">// good |
| function clicker() { |
| // ...... |
| } |
| |
| for (var i = 0, len = elements.length; i < len; i++) { |
| var element = elements[i]; |
| addListener(element, 'click', clicker); |
| } |
| |
| |
| // bad |
| for (var i = 0, len = elements.length; i < len; i++) { |
| var element = elements[i]; |
| addListener(element, 'click', function () {}); |
| } |
| </code></pre> |
| <h3 id="type-conversion">Type Conversion</h3> |
| <p><strong>[SUGGEST]</strong> Use <code>+ ''</code> to convert a value to string.</p> |
| <pre><code class="lang-js">// good |
| num + ''; |
| |
| // bad |
| new String(num); |
| num.toString(); |
| String(num); |
| </code></pre> |
| <p><strong>[SUGGEST]</strong> Use <code>+</code> to convert a value to number.</p> |
| <pre><code class="lang-js">// good |
| +str; |
| |
| // bad |
| Number(str); |
| </code></pre> |
| <p><strong>[MUST]</strong> The second parameter must not be ignored when using <code>parseInt</code>.</p> |
| <pre><code class="lang-js">// good |
| parseInt(str, 10); |
| |
| // bad |
| parseInt(str); |
| </code></pre> |
| <h3 id="string-object-array">String, Object, Array</h3> |
| <p><strong>[MUST]</strong> Use <code>'</code> but not <code>"</code> to define a string.</p> |
| <p><strong>[MUST]</strong> Use object literal <code>{}</code> to create a plain object.</p> |
| <pre><code class="lang-js">// good |
| var obj = {}; |
| |
| // bad |
| var obj = new Object(); |
| </code></pre> |
| <p><strong>[MUST]</strong> If all of the properties of an object literal do not need quotation marks, they should ignore them. If quotation marks is necessary, use <code>'</code> but not <code>"</code>.</p> |
| <pre><code class="lang-js">// good |
| var info = { |
| name: 'someone', |
| age: 28 |
| }; |
| |
| // bad |
| var info = { |
| 'name': 'someone', |
| 'age': 28 |
| }; |
| var info2 = { |
| "age": 40 |
| }; |
| </code></pre> |
| <p><strong>[MUST]</strong> The prototype of built-in objects must not be modified.</p> |
| <pre><code class="lang-js">// Forbidden |
| String.prototype.trim = function () { |
| }; |
| </code></pre> |
| <p><strong>[SUGGEST]</strong> Try best to use <code>.</code> but not <code>[]</code> to visit properties of an object.</p> |
| <p><strong>[SUGGEST]</strong> <code>hasOwnProperty</code> should be used to when using <code>for ... in ...</code>, in case that some extra properties is added on the prototype of <code>Object</code> in some runtime environment.</p> |
| <pre><code class="lang-js">var newInfo = {}; |
| for (var key in info) { |
| if (info.hasOwnProperty(key)) { |
| newInfo[key] = info[key]; |
| } |
| } |
| </code></pre> |
| <p><strong>[MUST]</strong> Use array literal <code>[]</code> to create an array, except intending to create an array with a given length.</p> |
| <pre><code class="lang-js">// good |
| var arr = []; |
| var arr2 = new Array(1e4); |
| |
| // bad |
| var arr = new Array(); |
| </code></pre> |
| <p><strong>[MUST]</strong> Do not use <code>for in</code> in array traverse.</p> |
| <h3 id="others">Others</h3> |
| <p><strong>[MUST]</strong> Do not use <code>eval</code> and <code>with</code>. <code>new Function</code> can be used.</p> |
| </div></div></div><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script><script type="text/javascript" src="./js/common.js"></script><script type="text/javascript">document.getElementById('nav-contribute').className = 'active'; |
| |
| var $list = $('#standard-nav'); |
| $('.page-detail h2, .page-detail h3, .page-detail h4') |
| .each(function () { |
| var $this = $(this); |
| var text = $this.text(); |
| var anchor = text.toLowerCase().replace(/[^\w]+/g, '-'); |
| var tagName = $this.prop('tagName').toLowerCase(); |
| |
| if (tagName === 'h2') { |
| $list.append('<a href="#' + anchor + '"><h4 class="inner">' + text + '</h4></a>'); |
| } |
| else { |
| $list.append('<a href="#' + anchor + '">' + text + '</a>'); |
| } |
| }); |
| |
| $('.page-nav a').click(function () { |
| $('.page-nav a').removeClass('active'); |
| $(this).addClass('active'); |
| }); |
| |
| // Fix scroll position covered by nav |
| window.addEventListener('hashchange', function() { |
| scrollBy(0, -50); |
| }); |
| |
| $('.page-detail pre code').each(function (index, el) { |
| $(el).addClass('prettyprint'); |
| }); |
| prettyPrint();</script><!-- Baidu Tongji--><script type="text/javascript">var _hmt = _hmt || []; |
| (function() { |
| var hm = document.createElement("script"); |
| hm.src = "https://hm.baidu.com/hm.js?54b918eee37cb8a7045f0fd0f0b24395"; |
| var s = document.getElementsByTagName("script")[0]; |
| s.parentNode.insertBefore(hm, s); |
| })(); |
| </script><!-- Google Analytics--><script type="text/javascript" async src="https://www.googletagmanager.com/gtag/js?id=UA-141228404-1"></script><script type="text/javascript">window.dataLayer = window.dataLayer || []; |
| function gtag(){dataLayer.push(arguments);} |
| gtag('js', new Date()); |
| gtag('config', 'UA-141228404-1');</script></html> |