欧美人与禽2O2O性论交,秋霞免费视频,国产美女视频免费观看网址,国产成人亚洲综合网色欲网

「前端」一篇詳細(xì)且全面的“前端模塊化方案”總結(jié)分享(含代碼)

隨著前端功能越來(lái)越復(fù)雜,前端代碼日益膨脹,為了減少維護(hù)成本,提高代碼的可復(fù)用性,前端模塊化勢(shì)在必行。歡迎閱讀~

當(dāng)所有.js文件都在一個(gè)html中引入,造成以下不良影響:

  1. 請(qǐng)求過(guò)多。首先我們要依賴多個(gè)模塊,那樣就會(huì)發(fā)送多個(gè)請(qǐng)求,導(dǎo)致請(qǐng)求過(guò)多
  2. 依賴模糊。我們不知道他們的具體依賴關(guān)系是什么,也就是說(shuō)很容易因?yàn)椴涣私馑麄冎g的依賴關(guān)系導(dǎo)致加載先后順序出錯(cuò)。
  3. 難以維護(hù)。以上兩種原因就導(dǎo)致了很難維護(hù),很可能出現(xiàn)牽一發(fā)而動(dòng)全身的情況導(dǎo)致項(xiàng)目出現(xiàn)嚴(yán)重的問(wèn)題。

一、模塊的概念

webpack 中是這樣定義的:

在模塊化編程中,開發(fā)者將程序分解成離散功能塊(discrete chunks of functionality),并稱之為模塊。 每個(gè)模塊具有比完整程序更小的接觸面,使得校驗(yàn)、調(diào)試、測(cè)試輕而易舉。 精心編寫的模塊提供了可靠的抽象和封裝界限,使得應(yīng)用程序中每個(gè)模塊都具有條理清楚的設(shè)計(jì)和明確的目的。

模塊應(yīng)該是職責(zé)單一、相互獨(dú)立、低耦合的、高度內(nèi)聚且可替換的離散功能塊。

二、模塊化的概念

模塊化是一種處理復(fù)雜系統(tǒng)分解成為更好的可管理模塊的方式,它可以把系統(tǒng)代碼劃分為一系列職責(zé)單一,高度解耦且可替換的模塊,系統(tǒng)中某一部分的變化將如何影響其它部分就會(huì)變得顯而易見,系統(tǒng)的可維護(hù)性更加簡(jiǎn)單易得。

模塊化是一種分治的思想,通過(guò)分解復(fù)雜系統(tǒng)為獨(dú)立的模塊實(shí)現(xiàn)細(xì)粒度的精細(xì)控制,對(duì)于復(fù)雜系統(tǒng)的維護(hù)和管理十分有益。模塊化也是組件化的基石,是構(gòu)成現(xiàn)在色彩斑斕的前端世界的前提條件。

三、為什么需要模塊化

前端開發(fā)和其他開發(fā)工作的主要區(qū)別,首先是前端是基于多語(yǔ)言、多層次的編碼和組織工作,其次前端產(chǎn)品的交付是基于瀏覽器,這些資源是通過(guò)增量加載的方式運(yùn)行到瀏覽器端,如何在開發(fā)環(huán)境組織好這些碎片化的代碼和資源,并且保證他們?cè)跒g覽器端快速、優(yōu)雅的加載和更新,就需要一個(gè)模塊化系統(tǒng)。

四、模塊化的好處

  1. 可維護(hù)性。 因?yàn)槟K是獨(dú)立的,一個(gè)設(shè)計(jì)良好的模塊會(huì)讓外面的代碼對(duì)自己的依賴越少越好,這樣自己就可以獨(dú)立去更新和改進(jìn)。
  2. 命名空間。 在 JavaScript 里面,如果一個(gè)變量在最頂級(jí)的函數(shù)之外聲明,它就直接變成全局可用。因此,常常不小心出現(xiàn)命名沖突的情況。使用模塊化開發(fā)來(lái)封裝變量,可以避免污染全局環(huán)境。
  3. 重用代碼。 我們有時(shí)候會(huì)喜歡從之前寫過(guò)的項(xiàng)目中拷貝代碼到新的項(xiàng)目,這沒(méi)有問(wèn)題,但是更好的方法是,通過(guò)模塊引用的方式,來(lái)避免重復(fù)的代碼庫(kù)。我們可以在更新了模塊之后,讓引用了該模塊的所有項(xiàng)目都同步更新,還能指定版本號(hào),避免 API 變更帶來(lái)的麻煩。

五、模塊化簡(jiǎn)史

5.1 最簡(jiǎn)單粗暴的方式

function fn1(){ // ...}function fn2(){ // ...}

通過(guò) script 標(biāo)簽引入文件,調(diào)用相關(guān)的函數(shù)。這樣需要手動(dòng)去管理依賴順序,容易造成命名沖突,污染全局,隨著項(xiàng)目的復(fù)雜度增加維護(hù)成本也越來(lái)越高。

5.2 用對(duì)象來(lái)模擬命名空間

var output = { _count: 0, fn1: function(){ // ... }}

這樣可以解決上面的全局污染的問(wèn)題,有那么點(diǎn)命名空間的意思,但是隨著項(xiàng)目復(fù)雜度增加需要越來(lái)越多的這樣的對(duì)象需要維護(hù),不說(shuō)別的,取名字都是個(gè)問(wèn)題。最關(guān)鍵的還是內(nèi)部的屬性還是可以被直接訪問(wèn)和修改。

5.3 閉包

var module = (function(){ var _count = 0; var fn1 = function (){ // ... } var fn2 = function fn2(){ // ... } return { fn1: fn1, fn2: fn2 }})()module.fn1();module._count; // undefined

這樣就擁有獨(dú)立的詞法作用域,內(nèi)存中只會(huì)存在一份 copy。這不僅避免了外界訪問(wèn)此 IIFE 中的變量,而且又不會(huì)污染全局作用域,通過(guò) return 暴露出公共接口供外界調(diào)用。這其實(shí)就是現(xiàn)代模塊化實(shí)現(xiàn)的基礎(chǔ)。

5.4 更多

還有基于閉包實(shí)現(xiàn)的松耦合拓展、緊耦合拓展、繼承、子模塊、跨文件共享私有對(duì)象、基于 new 構(gòu)造的各種方式,這種方式在現(xiàn)在看來(lái)都不再優(yōu)雅。

// 松耦合拓展// 這種方式使得可以在不同的文件中以相同結(jié)構(gòu)共同實(shí)現(xiàn)一個(gè)功能塊,且不用考慮在引入這些文件時(shí)候的順序問(wèn)題。// 缺點(diǎn)是沒(méi)辦法重寫你的一些屬性或者函數(shù),也不能在初始化的時(shí)候就是用module的屬性。var module = (function(my){ // ... return my})(module || {})// 緊耦合拓展(沒(méi)有傳默認(rèn)參數(shù))// 加載順序不再自由,但是可以重載var module = (function(my){ var old = my.someOldFunc my.someOldFunc = function(){ // 重載方法,依然可通過(guò)old調(diào)用舊的方法... } return my})(module)

六、實(shí)現(xiàn)模塊化的方案規(guī)范總覽

歷史上,JavaScript 一直沒(méi)有模塊(module)體系,無(wú)法將一個(gè)大程序拆分成互相依賴的小文件,再用簡(jiǎn)單的方法拼裝起來(lái)。其他語(yǔ)言都有這項(xiàng)功能,比如 Ruby 的require、Python 的import,甚至就連 CSS 都有@import,但是 JavaScript 任何這方面的支持都沒(méi)有,這對(duì)開發(fā)大型的、復(fù)雜的項(xiàng)目形成了巨大障礙。

在 ES6 之前,社區(qū)制定了一些模塊加載方案,最主要的有 CommonJSAMD 兩種。前者用于服務(wù)器,后者用于瀏覽器。ES6 在語(yǔ)言標(biāo)準(zhǔn)的層面上,實(shí)現(xiàn)了模塊功能,而且實(shí)現(xiàn)得相當(dāng)簡(jiǎn)單,完全可以取代 CommonJS 和 AMD 規(guī)范,成為瀏覽器和服務(wù)器通用的模塊解決方案。

ES6 模塊的設(shè)計(jì)思想是盡量的靜態(tài)化,使得編譯時(shí)就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量。CommonJS 和 AMD 模塊,都只能在運(yùn)行時(shí)確定這些東西。比如,CommonJS 模塊就是對(duì)象,輸入時(shí)必須查找對(duì)象屬性。

目前實(shí)現(xiàn)模塊化的規(guī)范主要有:

  • CommonJS
  • CMD
  • AMD
  • ES6模塊

七、CommonJS()

CommonJS 是以在瀏覽器環(huán)境之外構(gòu)建 JavaScript 生態(tài)系統(tǒng)為目標(biāo)而產(chǎn)生的項(xiàng)目,比如在服務(wù)器和桌面環(huán)境中。

采用同步加載模塊的方式,也就是說(shuō)只有加載完成,才能執(zhí)行后面的操作。CommonJS 代表:Node 應(yīng)用中的模塊,通俗的說(shuō)就是你用 npm 安裝的模塊。

它使用 require 引用和加載模塊,exports 定義和導(dǎo)出模塊,module 標(biāo)識(shí)模塊。使用 require 時(shí)需要去讀取并執(zhí)行該文件,然后返回 exports 導(dǎo)出的內(nèi)容。

//定義模塊 math.js var random=Math.random()*10; function printRandom(){ console.log(random) } function printIntRandom(){ console.log(Math.floor(random)) } //模塊輸出 module.exports={ printRandom:printRandom, printIntRandom:printIntRandom } //加載模塊 math.js var math=require('math') //調(diào)用模塊提供的方法 math.printIntRandom() math.printRandom()

7.1 CommonJS主要用于服務(wù)端的模塊化,不適用于前端模塊化的原因在于:

  • 服務(wù)端加載一個(gè)模塊,直接就從硬盤或者內(nèi)存中讀取了,消耗時(shí)間可以忽略不計(jì)
  • 瀏覽器需要從服務(wù)端下載這個(gè)文件,所以說(shuō)如果用CommonJS的require方式加載模塊,需要等代碼模塊下載完畢,并運(yùn)行之后才能得到所需要的API。
  • 如果我們?cè)谀硞€(gè)代碼模塊里使用CommonJS的方法require了一個(gè)模塊,而這個(gè)模塊需要通過(guò)http請(qǐng)求從服務(wù)器去取,如果網(wǎng)速很慢,而CommonJS又是同步的,所以將阻塞后面代碼的執(zhí)行,從而阻塞瀏覽器渲染頁(yè)面,使得頁(yè)面出現(xiàn)假死狀態(tài)。

7.2 CommonJS在瀏覽器端實(shí)現(xiàn)的步驟:

1. 創(chuàng)建項(xiàng)目結(jié)構(gòu)

|-js |-dist //打包生成文件的目錄 |-src //源碼所在的目錄 |-module1.js |-module2.js |-module3.js |-app.js //應(yīng)用主源文件|-index.html //運(yùn)行于瀏覽器上|-package.json { "name": "browserify-test", "version": "1.0.0" }

2. 下載browserify

  • 全局: npm install browserify -g
  • 局部: npm install browserify –save-dev

3. 定義模塊代碼(同服務(wù)器端)

注意:index.html文件要運(yùn)行在瀏覽器上,需要借助browserify將app.js文件打包編譯,如果直接在index.html引入app.js就會(huì)報(bào)錯(cuò)!

4. 打包處理js

根目錄下運(yùn)行browserify js/src/app.js -o js/dist/bundle.js

5. 頁(yè)面使用引入

在index.html文件中引入<script type="text/javascript" src="js/dist/bundle.js"></script>

八、AMD(Asynchronous Module Definition)

異步模塊定義,所謂異步是指模塊和模塊的依賴可以被異步加載,他們的加載不會(huì)影響它后面語(yǔ)句的運(yùn)行。有效避免了采用同步加載方式中導(dǎo)致的頁(yè)面假死現(xiàn)象。AMD代表:RequireJS。

AMD一開始是CommonJS規(guī)范中的一個(gè)草案,全稱是Asynchronous Module Definition,即異步模塊加載機(jī)制。后來(lái)由該草案的作者以RequireJS實(shí)現(xiàn)了AMD規(guī)范,所以一般說(shuō)AMD也是指RequireJS。

RequireJS是一個(gè)工具庫(kù),主要用于客戶端的模塊管理。它的模塊管理遵守AMD規(guī)范,RequireJS的基本思想是,通過(guò)define方法,將代碼定義為模塊;通過(guò)require方法,實(shí)現(xiàn)代碼的模塊加載。

它主要有兩個(gè)接口:definerequire。define 是模塊開發(fā)者關(guān)注的方法,而 require 則是模塊使用者關(guān)注的方法。

8.1 define() 函數(shù):

define(id?, dependencies?, factory);//id :可選參數(shù),它指的是模塊的名字。//dependencies:可選參數(shù),定義中模塊所依賴模塊的數(shù)組。//factory:模塊初始化要執(zhí)行的函數(shù)或?qū)ο?/code>

需要注意的是,dependencies有多少個(gè)元素,factory就有多少個(gè)傳參,位置一一對(duì)應(yīng)。
使用栗子:

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) { exports.verb = function() { return beta.verb(); //Or: //return require("beta").verb(); } });

8.2 require() 函數(shù)

require([module], callback);//module:一個(gè)數(shù)組,里面的成員就是要加載的模塊.//callback:模塊加載成功之后的回調(diào)函數(shù)。

需要注意的是 ,module 有多少個(gè)元素,callback 就有多少個(gè)傳參,位置一一對(duì)應(yīng)。

require(["a","b","c"],function(a,b,c){ //code here });

8.3 AMD的優(yōu)缺點(diǎn)

AMD 運(yùn)行時(shí)核心思想是「Early Executing」,也就是提前執(zhí)行依賴 AMD 的這個(gè)特性有好有壞:

  • 首先,盡早執(zhí)行依賴可以盡早發(fā)現(xiàn)錯(cuò)誤。
  • 另外,盡早執(zhí)行依賴通常可以帶來(lái)更好的用戶體驗(yàn),也容易產(chǎn)生浪費(fèi)。
  • 引用AMD的Javscript庫(kù): 目前,主要有兩個(gè)Javascript庫(kù)實(shí)現(xiàn)了AMD規(guī)范:require.js和curl.js
  • 在瀏覽器環(huán)境中異步加載模塊;并行加載多個(gè)模塊;
  • 開發(fā)成本高,代碼的閱讀和書寫比較困難,模塊定義方式的語(yǔ)義不順暢;不符合通用的模塊化思維方式,是一種妥協(xié)的實(shí)現(xiàn)。

8.4 AMD在瀏覽器端的實(shí)現(xiàn)步驟

1. 下載require.js, 并引入

  • 官網(wǎng): http://www.requirejs.cn/
  • github : https://github.com/requirejs/requirejs

然后將require.js導(dǎo)入項(xiàng)目: js/libs/require.js

2. 創(chuàng)建項(xiàng)目結(jié)構(gòu)

|-js |-libs |-require.js |-modules |-alerter.js |-dataService.js |-main.js|-index.html

3. 定義require.js的模塊代

// dataService.js文件// 定義沒(méi)有依賴的模塊define(function() { let Msg = 'www.baidu.com' function getMsg() { return msg.toUpperCase() } return { getMsg } // 暴露模塊});//alerter.js文件// 定義有依賴的模塊define(['dataService'], function(dataService) { let name = 'Tom' function showMsg() { alert(dataService.getMsg() ', ' name) } // 暴露模塊 return { showMsg }});// main.js文件(function() { require.config({ baseUrl: 'js/', //基本路徑 出發(fā)點(diǎn)在根目錄下 paths: { //映射: 模塊標(biāo)識(shí)名: 路徑 alerter: './modules/alerter', //此處不能寫成alerter.js,會(huì)報(bào)錯(cuò) dataService: './modules/dataService' } }); require(['alerter'], function(alerter) { alerter.showMsg() });})();// index.html文件<!DOCTYPE html><html> <head> <title>Modular Demo</title> </head> <body> <!-- 引入require.js并指定js主文件的入口 --> <script data-main="js/main" src="js/libs/require.js"></script> </body></html>

4. 頁(yè)面引入require.js模塊:

在index.html引入 <script data-main="js/main" src="js/libs/require.js"></script>

此外在項(xiàng)目中如何引入第三方庫(kù)?只需在上面代碼的基礎(chǔ)稍作修改:

// alerter.js文件define(['dataService', 'jquery'], function(dataService, $) { let name = 'Tom' function showMsg() { alert(dataService.getMsg() ', ' name) } $('body').css('background', 'green') // 暴露模塊 return { showMsg }});// main.js文件(function() { require.config({ baseUrl: 'js/', //基本路徑 出發(fā)點(diǎn)在根目錄下 paths: { //自定義模塊 alerter: './modules/alerter', //此處不能寫成alerter.js,會(huì)報(bào)錯(cuò) dataService: './modules/dataService', // 第三方庫(kù)模塊 jquery: './libs/jquery-1.10.1' //注意:寫成jQuery會(huì)報(bào)錯(cuò) } }) require(['alerter'], function(alerter) { alerter.showMsg() })})()

上例是在alerter.js文件中引入jQuery第三方庫(kù),main.js文件也要有相應(yīng)的路徑配置。 小結(jié):通過(guò)兩者的比較,可以得出AMD模塊定義的方法非常清晰,不會(huì)污染全局環(huán)境,能夠清楚地顯示依賴關(guān)系。AMD模式可以用于瀏覽器環(huán)境,并且允許非同步加載模塊,也可以根據(jù)需要?jiǎng)討B(tài)加載模塊。

九、CMD(Common Module Definition)

CMD是SeaJS在推廣過(guò)程中生產(chǎn)的對(duì)模塊定義的規(guī)范,在Web瀏覽器端的模塊加載器中,SeaJS與RequireJS并稱,SeaJS作者為阿里的玉伯。

CMD規(guī)范專門用于瀏覽器端,模塊的加載是異步的,模塊使用時(shí)才會(huì)加載執(zhí)行。CMD規(guī)范整合了CommonJS和AMD規(guī)范的特點(diǎn)。在 Sea.js 中,所有 JavaScript 模塊都遵循 CMD模塊定義規(guī)范。

9.1 CMD語(yǔ)法

定義暴露模塊:

//定義沒(méi)有依賴的模塊define(function(require, exports, module){ exports.xxx = value module.exports = value})//定義有依賴的模塊define(function(require, exports, module){ //引入依賴模塊(同步) var module2 = require('./module2') //引入依賴模塊(異步) require.async('./module3', function (m3) { }) //暴露模塊 exports.xxx = value})

引入使用模塊:

define(function (require) { var m1 = require('./module1') var m4 = require('./module4') m1.show() m4.show()})

9.2 CMD的優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):依賴就近,延遲執(zhí)行 可以很容易在 Node.js 中運(yùn)行;
  • 缺點(diǎn):依賴 SPM 打包,模塊的加載邏輯偏重;

9.3 sea.js使用步驟

1. 下載sea.js, 并引入

  • 官網(wǎng): seajs.org/
  • github : github.com/seajs/seajs

然后將sea.js導(dǎo)入項(xiàng)目: js/libs/sea.js

2. 創(chuàng)建項(xiàng)目結(jié)構(gòu)

|-js |-libs |-sea.js |-modules |-module1.js |-module2.js |-module3.js |-module4.js |-main.js|-index.html

3. 定義sea.js的模塊代碼

// module1.js文件define(function (require, exports, module) { //內(nèi)部變量數(shù)據(jù) var data = 'atguigu.com' //內(nèi)部函數(shù) function show() { console.log('module1 show() ' data) } //向外暴露 exports.show = show});// module2.js文件define(function (require, exports, module) { module.exports = { msg: 'I Will Back' }});// module3.js文件define(function(require, exports, module) { const API_KEY = 'abc123' exports.API_KEY = API_KEY});// module4.js文件define(function (require, exports, module) { //引入依賴模塊(同步) var module2 = require('./module2') function show() { console.log('module4 show() ' module2.msg) } exports.show = show //引入依賴模塊(異步) require.async('./module3', function (m3) { console.log('異步引入依賴模塊3 ' m3.API_KEY) })});// main.js文件define(function (require) { var m1 = require('./module1') var m4 = require('./module4') m1.show() m4.show()})

4. 在index.html中引入

<script type="text/javascript" src="js/libs/sea.js"></script><script type="text/javascript"> seajs.use('./js/modules/main')</script>

十、ES6模塊化(重點(diǎn)介紹)

ES6模塊的設(shè)計(jì)思想,是盡量的靜態(tài)化,使得編譯時(shí)就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量。所以說(shuō)ES6是編譯時(shí)加載,不同于CommonJS的運(yùn)行時(shí)加載(實(shí)際加載的是一整個(gè)對(duì)象),ES6模塊不是對(duì)象,而是通過(guò)export命令顯式指定輸出的代碼,輸入時(shí)也采用靜態(tài)命令的形式。

ES6 的模塊自動(dòng)采用嚴(yán)格模式,不管你有沒(méi)有在模塊頭部加上"use strict";。

嚴(yán)格模式主要有以下限制。

  • 變量必須聲明后再使用
  • 函數(shù)的參數(shù)不能有同名屬性,否則報(bào)錯(cuò)
  • 不能使用with語(yǔ)句
  • 不能對(duì)只讀屬性賦值,否則報(bào)錯(cuò)
  • 不能使用前綴 0 表示八進(jìn)制數(shù),否則報(bào)錯(cuò)
  • 不能刪除不可刪除的屬性,否則報(bào)錯(cuò)
  • 不能刪除變量delete prop,會(huì)報(bào)錯(cuò),只能刪除屬性delete global[prop]
  • eval不會(huì)在它的外層作用域引入變量
  • eval和arguments不能被重新賦值
  • arguments不會(huì)自動(dòng)反映函數(shù)參數(shù)的變化
  • 不能使用arguments.callee
  • 不能使用arguments.caller
  • 禁止this指向全局對(duì)象
  • 不能使用fn.caller和fn.arguments獲取函數(shù)調(diào)用的堆棧
  • 增加了保留字(比如protected、static和interface)

其中,尤其需要注意this的限制。ES6 模塊之中,頂層的this指向undefined,即不應(yīng)該在頂層代碼使用this。

10.1 語(yǔ)法

模塊功能主要由兩個(gè)命令構(gòu)成:export和import。export命令用于規(guī)定模塊的對(duì)外接口,import命令用于輸入其他模塊提供的功能。

10.1.1 export

一個(gè)模塊就是一個(gè)獨(dú)立的文件。該文件內(nèi)部的所有變量,外部無(wú)法獲取。如果你希望外部能夠讀取模塊內(nèi)部的某個(gè)變量,就必須使用export關(guān)鍵字輸出該變量。下面是一個(gè) JS 文件,里面使用export命令輸出變量。

function cUl(){ let ulEle = document.createElement("ul"); for(let i = 0; i < 5; i ){ let liEle = document.createElement("li"); liEle.innerHTML = "無(wú)序列表" i; ulEle.appendChild(liEle); } return ulEle;}let ul = cUl();export {ul};

10.1.2 import

使用export命令定義了模塊的對(duì)外接口以后,其他 JS 文件就可以通過(guò)import命令加載這個(gè)模塊。

import {table} from "../test/test_table.js";import {div} from "../test/test_div.js" ;import {ul} from "../test/test_ul.js" ;export {table, div, ul};

10.2 ES6 模塊與 CommonJS 模塊的差異

它們有兩個(gè)重大差異:

1. CommonJS 模塊輸出的是一個(gè)值的拷貝,ES6 模塊輸出的是值的引用。

2. CommonJS 模塊是運(yùn)行時(shí)加載,ES6 模塊是編譯時(shí)輸出接口

第二個(gè)差異是因?yàn)?CommonJS 加載的是一個(gè)對(duì)象(即module.exports屬性),該對(duì)象只有在腳本運(yùn)行完才會(huì)生成。而 ES6 模塊不是對(duì)象,它的對(duì)外接口只是一種靜態(tài)定義,在代碼靜態(tài)解析階段就會(huì)生成。

下面重點(diǎn)解釋第一個(gè)差異,我們還是舉上面那個(gè)CommonJS模塊的加載機(jī)制例子:

// lib.jsexport let counter = 3;export function incCounter() { counter ;}// main.jsimport { counter, incCounter } from './lib';console.log(counter); // 3incCounter();console.log(counter); // 4

ES6 模塊的運(yùn)行機(jī)制與 CommonJS 不一樣。ES6 模塊是動(dòng)態(tài)引用,并且不會(huì)緩存值,模塊里面的變量綁定其所在的模塊。

文章來(lái)源:https://zhuanlan.zhihu.com/p/134070306

相關(guān)新聞

聯(lián)系我們
聯(lián)系我們
公眾號(hào)
公眾號(hào)
在線咨詢
分享本頁(yè)
返回頂部