如何创建一个基本JQuery的插件
如何創(chuàng)建一個(gè)基本的插件
有時(shí)您希望在整個(gè)代碼中提供一些功能。例如,也許你想要一個(gè)單一的方法,你可以調(diào)用一個(gè)jQuery選擇,對(duì)選擇執(zhí)行一系列的操作。在這種情況下,您可能需要編寫(xiě)一個(gè)插件。
鏈接jQuery如何工作101:jQuery對(duì)象方法
在我們編寫(xiě)自己的插件之前,首先要了解一下jQuery如何工作。看看這段代碼:
| 1 | $( "a" ).css( "color", "red" ); |
這是一些很基礎(chǔ)的jQuery代碼,但你知道幕后發(fā)生了什么嗎?無(wú)論何時(shí)使用該$函數(shù)來(lái)選擇元素,它返回一個(gè)jQuery對(duì)象。這個(gè)對(duì)象包含了所有的你已經(jīng)使用(方法.css(),.click()等)和所有適合你的選擇要素。jQuery對(duì)象從對(duì)象中獲取這些方法$.fn。這個(gè)對(duì)象包含了所有的jQuery對(duì)象方法,如果我們想編寫(xiě)自己的方法,它也需要包含這些方法。
鏈接基本插件創(chuàng)作
假設(shè)我們要?jiǎng)?chuàng)建一個(gè)插件,使一組檢索到的元素中的文本變?yōu)榫G色。我們所要做的就是添加一個(gè)調(diào)用的函數(shù)greenify來(lái)$.fn,這將是可用的,就像任何其他的jQuery對(duì)象的方法。
| 1 2 3 4 五 | $.fn.greenify = function() { this.css( "color", "green" ); }; $( "a" ).greenify(); // Makes all the links green. |
注意使用.css(),另一種方法,我們使用this,而不是$( this )。這是因?yàn)槲覀兊膅reenify函數(shù)是與之相同的對(duì)象的一部分.css()。
鏈接鏈接
這是有效的,但是我們需要做的幾件事情就是讓我們的插件在現(xiàn)實(shí)生活中生存下去。當(dāng)您將五個(gè)或六個(gè)操作鏈接到一個(gè)選擇器上時(shí),jQuery的功能之一就是鏈接。這是通過(guò)使所有jQuery對(duì)象方法再次返回原始的jQuery對(duì)象來(lái)實(shí)現(xiàn)的(有一些例外:.width()調(diào)用無(wú)參數(shù)返回所選元素的寬度,并且不可鏈接)。使我們的插件方法可鏈接需要一行代碼:
| 1 2 3 4 五 6 | $.fn.greenify = function() { this.css( "color", "green" ); return this; } $( "a" ).greenify().addClass( "greenified" ); |
鏈接保護(hù)$別名和添加范圍
該$變量是JavaScript庫(kù)中很受歡迎,如果你正在使用jQuery的另一個(gè)庫(kù),你將不得不作出的jQuery不使用$帶jQuery.noConflict()。然而,這將會(huì)破壞我們的插件,因?yàn)樗怯煤瘮?shù)$的別名假設(shè)來(lái)寫(xiě)的jQuery。為了與其他插件很好地工作,并且仍然使用jQuery的$別名,我們需要把我們所有的代碼里面立即調(diào)用函數(shù)表達(dá)式,然后傳遞給函數(shù)jQuery,并命名參數(shù)$:
| 1 2 3 4 五 6 7 8 | (function ( $ ) { $.fn.greenify = function() { this.css( "color", "green" ); return this; }; }( jQuery )); |
此外,立即調(diào)用函數(shù)的主要目的是允許我們擁有自己的私有變量。假裝我們想要一個(gè)不同的顏色綠色,我們想把它存儲(chǔ)在變量中。
| 1 2 3 4 五 6 7 8 9 10 | (function ( $ ) { var shade = "#556b2f"; $.fn.greenify = function() { this.css( "color", shade ); return this; }; }( jQuery )); |
鏈接最小化插件足跡
編寫(xiě)插件時(shí)只需占用一個(gè)插槽就是很好的做法$.fn。這樣可以減少您的插件被覆蓋的機(jī)會(huì),并且插件將覆蓋其他插件的機(jī)會(huì)。換句話(huà)說(shuō),這是壞的:
| 1 2 3 4 五 6 7 8 9 10 11 | (function( $ ) { $.fn.openPopup = function() { // Open popup code. }; $.fn.closePopup = function() { // Close popup code. }; }( jQuery )); |
有一個(gè)插槽會(huì)更好,并使用參數(shù)來(lái)控制一個(gè)插槽執(zhí)行什么操作。
| 1 2 3 4 五 6 7 8 9 10 11 12 13 14 15 | (function( $ ) { $.fn.popup = function( action ) { if ( action === "open") { // Open popup code. } if ( action === "close" ) { // Close popup code. } }; }( jQuery )); |
鏈接使用each()方法
您的典型jQuery對(duì)象將包含對(duì)任意數(shù)量的DOM元素的引用,這就是為什么jQuery對(duì)象通常被稱(chēng)為集合。如果要對(duì)特定元素進(jìn)行任何操作(例如獲取數(shù)據(jù)屬性,計(jì)算特定位置),則需要使用.each()循環(huán)元素。
| 1 2 3 4 五 6 7 | $.fn.myNewPlugin = function() { return this.each(function() { // Do something to each element here. }); }; |
請(qǐng)注意,我們返回結(jié)果.each()而不是返回this。既然.each()已經(jīng)是可鏈接的,它返回this,然后我們返回。這是保持可鏈接性的一種更好的方法,而不是我們迄今為止所做的一切。
鏈接接受選項(xiàng)
隨著您的插件越來(lái)越復(fù)雜,最好通過(guò)接受選項(xiàng)來(lái)使您的插件可自定義。最簡(jiǎn)單的方法是這樣做,特別是如果有很多選項(xiàng),那就是一個(gè)對(duì)象文字。我們更改我們的greenify插件以接受一些選項(xiàng)。
| 1 2 3 4 五 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | (function ( $ ) { $.fn.greenify = function( options ) { // This is the easiest way to have default options. var settings = $.extend({ // These are the defaults. color: "#556b2f", backgroundColor: "white" }, options ); // Greenify the collection based on the settings variable. return this.css({ color: settings.color, backgroundColor: settings.backgroundColor }); }; }( jQuery )); |
使用示例
| 1 2 3 | $( "div" ).greenify({ color: "orange" }); |
為默認(rèn)值color的#556b2f獲取通過(guò)重寫(xiě)$.extend()為橙色。
鏈接在一起
這是一個(gè)使用我們討論的一些技巧的小插件的例子:
| 1 2 3 4 五 6 7 8 9 10 11 12 13 14 15 16 17 | (function( $ ) { $.fn.showLinkLocation = function() { this.filter( "a" ).each(function() { var link = $( this ); link.append( " (" + link.attr( "href" ) + ")" ); }); return this; }; }( jQuery )); // Usage example: $( "a" ).showLinkLocation(); |
這個(gè)方便的插件遍歷集合中的所有錨點(diǎn),并將該href屬性附加在括號(hào)中。
| 1 2 3 4 五 | <!-- Before plugin is called: --> <a href="page.html">Foo</a> <!-- After plugin is called: --> <a href="page.html">Foo (page.html)</a> |
我們的插件可以通過(guò)以下優(yōu)化:
| 1 2 3 4 五 6 7 8 9 10 11 12 13 | (function( $ ) { $.fn.showLinkLocation = function() { this.filter( "a" ).append(function() { return " (" + this.href + ")"; }); return this; }; }( jQuery )); |
我們使用該.append()方法的能力來(lái)接受回調(diào),并且該回調(diào)的返回值將決定附加到集合中每個(gè)元素的內(nèi)容。還要注意,我們沒(méi)有使用該.attr()方法來(lái)檢索href屬性,因?yàn)楸緳C(jī)DOM API可以方便地訪(fǎng)問(wèn)aptly named?href屬性。
高級(jí)插件概念
鏈接提供公共訪(fǎng)問(wèn)默認(rèn)插件設(shè)置
我們可以而且應(yīng)該對(duì)上面的代碼進(jìn)行改進(jìn)是公開(kāi)默認(rèn)的插件設(shè)置。這很重要,因?yàn)樗共寮脩?hù)很容易用最小的代碼覆蓋/定制插件。這就是我們開(kāi)始利用函數(shù)對(duì)象的地方。
| 1 2 3 4 五 6 7 8 9 10 11 12 13 14 15 16 17 | // Plugin definition. $.fn.hilight = function( options ) { // Extend our default options with those provided. // Note that the first argument to extend is an empty // object – this is to keep from overriding our "defaults" object. var opts = $.extend( {}, $.fn.hilight.defaults, options ); // Our plugin implementation code goes here. }; // Plugin defaults – added as a property on our plugin function. $.fn.hilight.defaults = { foreground: "red", background: "yellow" }; |
現(xiàn)在,用戶(hù)可以在腳本中包含這樣一行:
| 1 2 3 | // This needs only be called once and does not // have to be called from within a "ready" block $.fn.hilight.defaults.foreground = "blue"; |
現(xiàn)在我們可以像這樣調(diào)用插件方法,它將使用藍(lán)色的前景色:
| 1 | $( "#myDiv" ).hilight(); |
您可以看到,我們?cè)试S用戶(hù)編寫(xiě)一行代碼來(lái)更改插件的默認(rèn)前景色。而用戶(hù)仍然可以選擇性地覆蓋這個(gè)新的默認(rèn)值:
| 1 2 3 4 五 6 7 8 9 10 11 12 13 14 | // Override plugin default foreground color. $.fn.hilight.defaults.foreground = "blue"; // ... // Invoke plugin using new defaults. $( ".hilightDiv" ).hilight(); // ... // Override default by passing options to plugin method. $( "#green" ).hilight({ foreground: "green" }); |
鏈接提供公共訪(fǎng)問(wèn)次要功能作為適用
該項(xiàng)目與上一個(gè)項(xiàng)目緊密相關(guān),是擴(kuò)展插件(并允許其他擴(kuò)展插件)的有趣方式。例如,我們的插件的實(shí)現(xiàn)可以定義一個(gè)稱(chēng)為“格式”的功能,其格式化高亮文本。我們的插件可能看起來(lái)像這樣,默認(rèn)實(shí)現(xiàn)的格式方法定義在hilight函數(shù)下面:
| 1 2 3 4 五 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // Plugin definition. $.fn.hilight = function( options ) { // Iterate and reformat each matched element. return this.each(function() { var elem = $( this ); // ... var markup = elem.html(); // Call our format function. markup = $.fn.hilight.format( markup ); elem.html( markup ); }); }; // Define our format function. $.fn.hilight.format = function( txt ) { return "<strong>" + txt + "</strong>"; }; |
我們可以輕松地支持選項(xiàng)對(duì)象上的另一個(gè)屬性,允許提供回調(diào)函數(shù)來(lái)覆蓋默認(rèn)格式。這是支持自定義插件的另一個(gè)很好的方法。這里顯示的技術(shù)通過(guò)實(shí)際暴露格式功能使其可以重新定義,從而進(jìn)一步擴(kuò)展。使用這種技術(shù),其他人可能會(huì)發(fā)布自己的插件自定義覆蓋 - 換句話(huà)說(shuō),這意味著其他人可以為插件編寫(xiě)插件。
考慮到我們?cè)诒疚闹袠?gòu)建的簡(jiǎn)單的示例插件,您可能會(huì)想知道何時(shí)會(huì)有用。一個(gè)現(xiàn)實(shí)世界的例子是循環(huán)插件。循環(huán)插件是一個(gè)幻燈片插件,它支持多種內(nèi)置的轉(zhuǎn)換效果 - 滾動(dòng),滑動(dòng),淡入淡出等。但是,實(shí)際上,沒(méi)有辦法定義可能希望應(yīng)用于幻燈片轉(zhuǎn)換的每種類(lèi)型的效果。這就是這種類(lèi)型的可擴(kuò)展性是有用的。循環(huán)插件公開(kāi)了一個(gè)“transition”對(duì)象,用戶(hù)可以添加自己的自定義轉(zhuǎn)換定義。它在插件中定義如下:
| 1 2 3 4 五 | $.fn.cycle.transitions = { // ... }; |
這種技術(shù)使得其他人可以定義和提供插件到循環(huán)插件的轉(zhuǎn)換定義。
鏈接保持私人功能私有
暴露部分插件被覆蓋的技術(shù)可以非常強(qiáng)大。但是,您需要仔細(xì)考慮實(shí)施的哪些部分才能公開(kāi)。一旦暴露,您需要記住,調(diào)用參數(shù)或語(yǔ)義的任何更改可能會(huì)破壞向后兼容性。作為一般規(guī)則,如果您不確定是否公開(kāi)特定功能,那么您可能不應(yīng)該。
那么,我們?nèi)绾味x更多的功能,而不會(huì)混淆命名空間,而不會(huì)暴露實(shí)現(xiàn)?這是關(guān)閉的工作。為了演示,我們將在我們的插件中添加另一個(gè)函數(shù)叫做“debug”。調(diào)試功能將所選元素的數(shù)量記錄到控制臺(tái)。要?jiǎng)?chuàng)建一個(gè)閉包,我們將整個(gè)插件定義包裝在一個(gè)函數(shù)中(如jQuery創(chuàng)作指南中所詳述的)。
| 1 2 3 4 五 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // Create closure. (function( $ ) { // Plugin definition. $.fn.hilight = function( options ) { debug( this ); // ... }; // Private function for debugging. function debug( obj ) { if ( window.console && window.console.log ) { window.console.log( "hilight selection count: " + obj.length ); } }; // ... // End of closure. })( jQuery ); |
我們的“調(diào)試”方法無(wú)法從關(guān)閉的外部訪(fǎng)問(wèn),因此對(duì)我們的實(shí)現(xiàn)是私有的。
鏈接Bob和Sue
假設(shè)鮑勃?jiǎng)?chuàng)建了一個(gè)邪惡的新畫(huà)廊插件(稱(chēng)為“超級(jí)畫(huà)廊”),其中包含一幅圖像列表,并使其可導(dǎo)航。鮑勃拋出了一些動(dòng)畫(huà),使它更有趣。他試圖使插件盡可能的自定義,最終結(jié)果是這樣的:
| 1 2 3 4 五 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 三十 | jQuery.fn.superGallery = function( options ) { // Bob's default settings: var defaults = { textColor: "#000", backgroundColor: "#fff", fontSize: "1em", delay: "quite long", getTextFromTitle: true, getTextFromRel: false, getTextFromAlt: false, animateWidth: true, animateOpacity: true, animateHeight: true, animationDuration: 500, clickImgToGoToNext: true, clickImgToGoToLast: false, nextButtonText: "next", previousButtonText: "previous", nextButtonTextColor: "red", previousButtonTextColor: "red" }; var settings = $.extend( {}, defaults, options ); return this.each(function() { // Plugin code would go here... }); }; |
第一件事可能是你的頭腦(好的,也許不是第一個(gè)),這個(gè)插件必須有多大,以適應(yīng)這樣一個(gè)級(jí)別的定制。插件,如果不是虛構(gòu)的,可能會(huì)比必要的大得多。只有這么多千字節(jié)的人會(huì)愿意花費(fèi)!
現(xiàn)在,我們的朋友鮑勃認(rèn)為這一切都很好;?事實(shí)上,他對(duì)插件及其定制級(jí)別印象深刻。他認(rèn)為,所有的選擇都可以使用更為通用的解決方案,可以在許多不同的情況下使用。
蘇,我們的另一個(gè)朋友,決定使用這個(gè)新的插件。她已經(jīng)設(shè)置了所有的選項(xiàng),現(xiàn)在有一個(gè)工作的方案坐在她面前。只有五分鐘后,玩插件后,如果每張圖片的寬度都以較慢的速度動(dòng)畫(huà),她意識(shí)到畫(huà)廊會(huì)更好看。她匆忙搜索Bob的文檔,但沒(méi)有發(fā)現(xiàn)animateWidthDuration選項(xiàng)!
鏈接你看到問(wèn)題嗎?
這不是真的關(guān)于您的插件有多少選項(xiàng);?但它有什么選擇!
鮑勃已經(jīng)超過(guò)了頂峰。他提供的定制水平雖然可能高,但實(shí)際上相當(dāng)?shù)?#xff0c;特別是考慮到使用此插件時(shí)可能需要控制的所有可能的事情。鮑勃犯了錯(cuò)誤提供了很多可笑的具體選擇,使他的插件更難以自定義!
鏈接更好的模型
所以很明顯:鮑勃需要一個(gè)新的定制模式,一個(gè)不放棄控制或抽出必要細(xì)節(jié)的模型。
鮑勃如此吸引這個(gè)高級(jí)簡(jiǎn)單性的原因是,jQuery框架非常適合于這種觀念。提供一個(gè)previousButtonTextColor選項(xiàng)是好的和簡(jiǎn)單的,但讓我們面對(duì)它,絕大多數(shù)的插件用戶(hù)將要更多的控制!
以下是一些提示,可幫助您為插件創(chuàng)建更好的可定制選項(xiàng):
鏈接不要?jiǎng)?chuàng)建特定于插件的語(yǔ)法
使用您的插件的開(kāi)發(fā)人員不應(yīng)該學(xué)習(xí)一種新的語(yǔ)言或術(shù)語(yǔ),只是為了完成這項(xiàng)工作。
鮑勃認(rèn)為他提供最大的定制與他的延遲選項(xiàng)(看上面)。他做的這樣,他的插件可以指定四個(gè)不同的延遲,“很短”,“很短”,“相當(dāng)長(zhǎng)”或“很長(zhǎng)”:
| 1 2 3 4 五 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | var delayDuration = 0; switch ( settings.delay ) { case "very short": delayDuration = 100; break; case "quite short": delayDuration = 200; break; case "quite long": delayDuration = 300; break; case "very long": delayDuration = 400; break; default: delayDuration = 200; } |
這不僅限制了人們的控制水平,而且占用了相當(dāng)多的空間。十二行代碼只是為了定義延遲時(shí)間有點(diǎn)多,你不覺(jué)得嗎?構(gòu)建此選項(xiàng)的更好方法是讓插件用戶(hù)以數(shù)字的形式指定時(shí)間(以毫秒為單位),以便不需要處理該選項(xiàng)。
這里的關(guān)鍵不在于通過(guò)抽象來(lái)減少控制的程度。您的抽象,無(wú)論如何,可以像您想要的一樣簡(jiǎn)單,但確保使用您的插件的人仍然會(huì)有這么多追捧的低級(jí)控制!(低級(jí)我的意思是非抽象的)
鏈接充分控制元素
如果您的插件創(chuàng)建要在DOM中使用的元素,那么為插件用戶(hù)提供一些訪(fǎng)問(wèn)這些元素的方法是個(gè)好主意。有時(shí)這意味著給予某些元素ID或類(lèi)。但請(qǐng)注意,您的插件不應(yīng)該在內(nèi)部依賴(lài)這些鉤子:
執(zhí)行不良
| 1 2 3 4 | // Plugin code $( "<div class='gallery-wrapper' />" ).appendTo( "body" ); $( ".gallery-wrapper" ).append( "..." ); |
為了允許用戶(hù)訪(fǎng)問(wèn)甚至操縱該信息,您可以將其存儲(chǔ)在包含插件設(shè)置的變量中。以前的代碼的更好的實(shí)現(xiàn)如下所示:
| 1 2 3 4 五 6 7 | // Retain an internal reference: var wrapper = $( "<div />" ) .attr( settings.wrapperAttrs ) .appendTo( settings.container ); // Easy to reference later... wrapper.append( "..." ); |
請(qǐng)注意,我們創(chuàng)建了一個(gè)引用包裝器的引用,并且我們還調(diào)用該.attr()方法來(lái)向元素添加任何指定的屬性。所以在我們的設(shè)置中可能會(huì)像這樣處理:
| 1 2 3 4 五 6 7 8 9 10 | var defaults = { wrapperAttrs : { class: "gallery-wrapper" }, // ... rest of settings ... }; // We can use the extend method to merge options/settings as usual: // But with the added first parameter of TRUE to signify a DEEP COPY: var settings = $.extend( true, {}, defaults, options ); |
在$ .extend()方法現(xiàn)在將通過(guò)所有嵌套對(duì)象遞歸給我們?cè)O(shè)定值和通過(guò)選擇兩者的合并版本,給人傳遞的選項(xiàng)優(yōu)先。
插件用戶(hù)現(xiàn)在有權(quán)力指定該包裝器元素的任何屬性,因此如果它們需要任何CSS樣式的鉤子,那么他們可以很容易地添加一個(gè)類(lèi)或更改ID的名稱(chēng),而無(wú)需去挖掘插件源碼。
可以使用相同的模型來(lái)讓用戶(hù)定義CSS樣式:
| 1 2 3 4 五 6 7 8 9 10 | var defaults = { wrapperCSS: {}, // ... rest of settings ... }; // Later on in the plugin where we define the wrapper: var wrapper = $( "<div />" ) .attr( settings.wrapperAttrs ) .css( settings.wrapperCSS ) // ** Set CSS! .appendTo( settings.container ); |
您的插件可能有一個(gè)關(guān)聯(lián)的樣式表,開(kāi)發(fā)人員可以添加CSS樣式。即使在這種情況下,最好提供一些方便的方法來(lái)設(shè)置JavaScript中的樣式,而無(wú)需使用選擇器來(lái)獲取元素。
鏈接提供回調(diào)功能
什么是回調(diào)??- 回調(diào)本質(zhì)上是一個(gè)稍后調(diào)用的函數(shù),通常由一個(gè)事件觸發(fā)。它作為參數(shù)傳遞,通常是組件的發(fā)起調(diào)用,在這種情況下是一個(gè)jQuery插件。
如果您的插件由事件驅(qū)動(dòng),那么為每個(gè)事件提供回調(diào)功能可能是一個(gè)好主意。此外,您可以創(chuàng)建自己的自定義事件,然后為其提供回調(diào)。在這個(gè)gallery插件中添加一個(gè)“onImageShow”回調(diào)可能是有意義的。
| 1 2 3 4 五 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | var defaults = { // We define an empty anonymous function so that // we don't need to check its existence before calling it. onImageShow : function() {}, // ... rest of settings ... }; // Later on in the plugin: nextButton.on( "click", showNextImage ); function showNextImage() { // Returns reference to the next image node var image = getNextImage(); // Stuff to show the image here... // Here's the callback: settings.onImageShow.call( image ); } |
而不是通過(guò)傳統(tǒng)方式(加括號(hào))啟動(dòng)回調(diào),我們?cè)谏舷挛闹姓{(diào)用它將image是對(duì)圖像節(jié)點(diǎn)的引用。這意味著您可以通過(guò)this回調(diào)中的關(guān)鍵字訪(fǎng)問(wèn)實(shí)際的圖像節(jié)點(diǎn):
| 1 2 3 4 五 6 7 | $( "ul.imgs li" ).superGallery({ onImageShow: function() { $( this ).after( "<span>" + $( this ).attr( "longdesc" ) + "</span>" ); }, // ... other options ... }); |
同樣,您可以添加一個(gè)“onImageHide”回調(diào)函數(shù)和其他許多回調(diào)函數(shù)。回調(diào)點(diǎn)是給插件用戶(hù)一個(gè)簡(jiǎn)單的方法來(lái)添加額外的功能,而不需要在源代碼中挖掘。
鏈接記住,這是一個(gè)妥協(xié)
您的插件無(wú)法在每種情況下工作。同樣地,如果您提供的控制方法不是很少或很少,則不會(huì)非常有用。所以,請(qǐng)記住,這將是一個(gè)妥協(xié)。您必須始終考慮的三件事情是:
- 靈活性:您的插件可以處理多少情況?
- 大小:插件的大小是否對(duì)應(yīng)于其功能級(jí)別?也許你使用一個(gè)非常基本的工具提示插件,如果它是20k的大小?- 可能不會(huì)!
- 性能:您的插件是否以任何方式大量處理選項(xiàng)?這是否影響速度?為最終用戶(hù)帶來(lái)的開(kāi)銷(xiāo)是否值得?
轉(zhuǎn)載于:https://www.cnblogs.com/burningmyself/p/7451399.html
總結(jié)
以上是生活随笔為你收集整理的如何创建一个基本JQuery的插件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: BZOJ1026 [SCOI2009]w
- 下一篇: Linux Centos7安装Oracl