0.參考資料
尊重他人的勞動成果,貼上參考的資料地址,本文僅做學習記錄之用。html
- https://www.codeproject.com/Articles/869059/Topological-sorting-in-Csharp
- https://songlee24.github.io/2015/05/07/topological-sorting/
- http://www.javashuo.com/article/p-vidabxub-dn.html
1.介紹
本身以前並無接觸過拓撲排序,頂多據說過拓撲圖。在寫前一篇文章的時候,看到 Abp 框架在處理模塊依賴項的時候使用了拓撲排序,來確保頂級節點始終是最早進行加載的。第一次看到以爲很神奇,看了一下維基百科頭也是略微大,本身的水平也是停留在冒泡排序的層次。ヽ(≧□≦)ノlinux
看了第二篇參考資料才大體瞭解,在此記錄一下。nginx
2.原理
先來一個基本定義:c++
在圖論中,拓撲排序(Topological Sorting)是一個有向無環圖(DAG, Directed Acyclic Graph)的全部頂點的線性序列。且該序列必須知足下面兩個條件:git
- 每一個頂點出現且只出現一次。
- 若存在一條從頂點 A 到頂點 B 的路徑,那麼在序列中頂點 A 出如今頂點 B 的前面。
有向無環圖(DAG)纔有拓撲排序,非DAG圖沒有拓撲排序一說。程序員
例如,有一個集合它的依賴關係以下圖:github
能夠看到他有一個依賴關係:正則表達式
- Module D 依賴於 Module E 與 Module B 。
- Module E 依賴於 Module B 與 Module C 。
- Module B 依賴於 Module A 與 Module C 。
- Module C 依賴於 Module A 。
- Module A 無依賴 。
這個就是一個 DAG 圖,咱們要獲得它的拓撲排序,一個簡單的步驟以下:算法
- 從 DAG 圖中選擇一個沒有前驅的頂點並輸出。
- 從 DAG 圖中刪除該頂點,以及以它爲起點的有向邊。
- 重複步驟 一、2 直到當前的 DAG 圖爲空,或者當前圖不存在無前驅的頂點爲止。
按照以上步驟,咱們來進行一個排序試試。
最後的排序結果就是:
Module D -> Module E -> Module B -> Module C -> Module A
emmmm,其實一個有向無環圖能夠有一個或者多個拓撲序列的,由於有的時候會存在一種狀況,即如下這種狀況:
這個時候你就可能會有這兩種結果
D->E->B->C->F->A
D->E->B->F->C->A
由於 F 與 C 是平級的,他們初始化順序即使不一樣也沒有什麼影響,由於他們的依賴層級是一致的,不過細心的朋友可能會發現這個順序好像是反的,咱們還須要將其再反轉一次。
3.實現
上面這種方法僅適用於已知入度的時候,也就是說這些內容自己就是存在於一個有向無環圖之中的,若是按照以上方法進行拓撲排序,你須要維護一個入度爲 0 的隊列,而後每次迭代移除入度爲 0 頂點所指向的頂點入度。
例若有如下圖:
按照咱們以前的算法,
- 首先初始化隊列,將 5 與 4 這兩個入度爲 0 的頂點加入隊列當中。
- 執行 While 循環,條件是隊列不爲空。
- 以後首先拿出 4 。
- 而後針對其指向的頂點 0 與 頂點 1 的入度減去 1。
- 減去指向頂點入度的時候同時判斷,被減去入度的頂點其值是否爲 0 。
- 這裏 1 入度被減去 1 ,爲 0 ,添加到隊列。
- 0 頂點入度減去 1 ,爲 1。
- 隊列如今有 5 與 1 這兩個頂點,循環判斷隊列不爲空。
- 5 指向的頂點 0 入度 減去 1,頂點 0 入度爲 0 ,插入隊列。
這樣反覆循環,最終隊列所有清空,退出循環,獲得拓撲排序的結果4, 5, 2, 0, 3, 1 。
4.深度優先搜索實現
在參考資料 1 的代碼當中使用的是深度優先算法,它適用於有向無環圖。
有如下有向環圖 G2:
對上圖 G2 進行深度優先遍歷,首先從入度爲 0 的頂點 A 開始遍歷:
它的步驟以下:
-
訪問 A 。
-
訪問 B 。
-
訪問 C 。
在訪問了 B 後應該是訪問 B 的另一個頂點,這裏能夠是隨機的也能夠是有序的,具體取決於你存儲的序列順序,這裏先訪問 C 。
-
訪問 E 。
-
訪問 D 。
這裏訪問 D 是由於 B 已經被訪問過了,因此訪問頂點 D 。
- 訪問 F 。
由於頂點 C 已經被訪問過,因此應該回溯訪問頂點 B 的另外一個有向邊指向的頂點 F 。
- 訪問 G 。
所以最後的訪問順序就是 A -> B -> C -> E -> D -> F -> G ,注意順序仍是不太對哦。
看起來跟以前的方法差很少,實現當中,其 Sort()
方法內部包含一個 visited 字典,用於標記已經訪問過的頂點,sorted 則是已經排序完成的集合列表。
在字典裏 Key 是頂點的值,其 value 值用來標識是否已經訪問完全部路徑,爲 true
則表示正在處理該頂點,爲 false
則表示已經處理完成。
如今咱們來寫實現吧:
public static IList<T> Sort<T>(IEnumerable<T> source, Func<T, IEnumerable<T>> getDependencies) { var sorted = new List<T>(); var visited = new Dictionary<T, bool>(); foreach (var item in source) { Visit(item, getDependencies, sorted, visited); } return sorted; } public static void Visit<T>(T item, Func<T, IEnumerable<T>> getDependencies, List<T> sorted, Dictionary<T, bool> visited) { bool inProcess; var alreadyVisited = visited.TryGetValue(item, out inProcess); // 若是已經訪問該頂點,則直接返回 if (alreadyVisited) { // 若是處理的爲當前節點,則說明存在循環引用 if (inProcess) { throw new ArgumentException("Cyclic dependency found."); } } else { // 正在處理當前頂點 visited[item] = true; // 得到全部依賴項 var dependencies = getDependencies(item); // 若是依賴項集合不爲空,遍歷訪問其依賴節點 if (dependencies != null) { foreach (var dependency in dependencies) { // 遞歸遍歷訪問 Visit(dependency, getDependencies, sorted, visited); } } // 處理完成置爲 false visited[item] = false; sorted.Add(item); } }
頂點定義:
// Item 定義 public class Item { // 條目名稱 public string Name { get; private set; } // 依賴項 public Item[] Dependencies { get; set; } public Item(string name, params Item[] dependencies) { Name = name; Dependencies = dependencies; } public override string ToString() { return Name; } }
調用:
static void Main(string[] args) { var moduleA = new Item("Module A"); var moduleC = new Item("Module C", moduleA); var moduleB = new Item("Module B", moduleC); var moduleE = new Item("Module E", moduleB); var moduleD = new Item("Module D", moduleE); var unsorted = new[] { moduleE, moduleA, moduleD, moduleB, moduleC }; var sorted = Sort(unsorted, x => x.Dependencies); foreach (var item in sorted) { Console.WriteLine(item.Name); } Console.ReadLine(); }
結果:
dotNet Core WEB程序使用 Nginx反向代理
以前記錄過一篇 使用 jexus 做爲dotNetCore的反向代理,發現jexus的內存佔用較大,最終選擇使用Nginx的緣由就是佔用內存較小(https://www.cnblogs.com/jhy55/p/9229933.html)
Jexux與 Nginx性能對比參考(https://www.aliyun.com/jiaocheng/202277.html)
直入正題。。。。。。。。。。
Nginx 安裝
安裝所需環境
Nginx 是 C語言 開發,建議在 Linux 上運行,固然,也能夠安裝 Windows 版本,本篇則使用 CentOS 7 做爲安裝環境。
一. gcc 安裝
安裝 nginx 須要先將官網下載的源碼進行編譯,編譯依賴 gcc 環境,若是沒有 gcc 環境,則須要安裝:
yum install gcc-c++
二. PCRE pcre-devel 安裝
PCRE(Perl Compatible Regular Expressions) 是一個Perl庫,包括 perl 兼容的正則表達式庫。nginx 的 http 模塊使用 pcre 來解析正則表達式,因此須要在 linux 上安裝 pcre 庫,pcre-devel 是使用 pcre 開發的一個二次開發庫。nginx也須要此庫。命令:
yum install -y pcre pcre-devel
三. zlib 安裝
zlib 庫提供了不少種壓縮和解壓縮的方式, nginx 使用 zlib 對 http 包的內容進行 gzip ,因此須要在 Centos 上安裝 zlib 庫。
yum install -y zlib zlib-devel
四. OpenSSL 安裝
OpenSSL 是一個強大的安全套接字層密碼庫,囊括主要的密碼算法、經常使用的密鑰和證書封裝管理功能及 SSL 協議,並提供豐富的應用程序供測試或其它目的使用。
nginx 不只支持 http 協議,還支持 https(即在ssl協議上傳輸http),因此須要在 Centos 安裝 OpenSSL 庫。
yum install -y openssl openssl-devel
官網下載
1.直接下載.tar.gz安裝包,地址:https://nginx.org/en/download.html
2.使用wget命令下載(推薦)。
wget -c https://nginx.org/download/nginx-1.14.0.tar.gz
我下載的是1.14.0版本,這個是目前的穩定版。
解壓
依然是直接命令:
tar -zxvf nginx-1.14.0.tar.gz cd nginx-1.14.0
其實在 nginx-1.10.1 版本中你就不須要去配置相關東西,默認就能夠了。固然,若是你要本身配置目錄也是能夠的。
1.使用默認配置
./configure
編譯安裝
make make install
查找安裝路徑:
whereis nginx
啓動、中止nginx
cd /usr/local/nginx/sbin/ ./nginx ./nginx -s stop ./nginx -s quit ./nginx -s reload
./nginx -s quit:此方式中止步驟是待nginx進程處理任務完畢進行中止。
./nginx -s stop:此方式至關於先查出nginx進程id再使用kill命令強制殺掉進程。
查詢nginx進程:
ps aux|grep nginx
重啓 nginx
1.先中止再啓動(推薦):
對 nginx 進行重啓至關於先中止再啓動,即先執行中止命令再執行啓動命令。以下:
./nginx -s quit ./nginx
2.從新加載配置文件:
當 ngin x的配置文件 nginx.conf 修改後,要想讓配置生效須要重啓 nginx,使用-s reload不用先中止 ngin x再啓動 nginx 便可將配置信息在 nginx 中生效,以下:
./nginx -s reload
啓動成功後,在瀏覽器能夠看到這樣的頁面:
添加到系統服務,開機自啓動
vim /etc/init.d/nginx
添加內容以下
#!/bin/bash
#chkconfig:- 99 20
#description:Nginx Service Control Script
cmd='/usr/local/nginx/sbin/nginx'
pid='/usr/local/nginx/logs/nginx.pid'
case "$1" in
start)
$cmd
;;
stop)
kill -s QUIT $(cat $pid)
;;
restart)
$0 stop
$0 start
;;
reload)
kill -s HUP $(cat $pid)
;;
*)
echo 'Usage:$0 {start|stop|restart|reload}'
exit 1
esac
exit 0
重啓服務
service nginx restart
到這裏nginx安裝完成了
站點配置
HTTP配置代理
若是在 nginx.conf 文件中添加站點配置,多站點的狀況下,不利於管理
多站點配置,須要啓用這個配置,而後在conf.d文件夾下,建立多個配置文件便可。好比lotteryAdmin.conf、lotteryAPI.conf
新建文件夾
mkdir /usr/local/nginx/conf.d/
vim /usr/local/nginx/conf/nginx.conf
在尾部 http { }內添加
include /usr/local/nginx/conf.d/*.conf;
而後 :wq!保存
vim /usr/local/nginx/conf.d/lotteryAdmin.conf
添加內容
server {
listen 80;
index /Main/index;
server_name admin1.lottery.com; #域名
location / {
# 傳遞真實IP到後端
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://localhost:5001;#dotNetCore程序的端口號
}
}
而後 :wq!保存
重啓 Nginx 服務
service nginx restart
查看Nginx配置是否正常
/usr/local/nginx/sbin/nginx -t
如今能夠訪問你的站點了
HTTPS配置代理
申請到證書以後,我這裏有 xxx.key和xxx.pem兩個文件
server {
listen 443;
server_name api.lottery.com;
ssl on;
index index.html index.htm;
ssl_certificate /dotnet/httpsKey/cretc.pem;
ssl_certificate_key /dotnet/httpsKey/cretc.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://localhost:5003;#dotNetCore程序的端口號
}
}
按 :wq!保存
service nginx restart
若是報錯
unknown directive "ssl"............
切換到你解壓的nginx目錄下
####### 下載你當前版本的nginx包,而且解壓 進到目錄
./configure --with-http_ssl_module
####### 切記千萬不要make install 那樣就覆蓋安裝了
make
####### 將原來的nginx備份 備份以前先kill當前正在啓動的nginx
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
####### make以後會在當前目錄生成 objs 目錄
cp objs/nginx /usr/local/nginx/sbin/nginx
####### 而後從新啓動nginx
/usr/local/nginx/sbin/nginx
在重啓nginx服務
service nginx restart
這個時候能夠訪問你的站點了
C#裏面得到應用程序的當前路徑
在C#裏面得到應用程序的當前路徑
Environment.CurrentDirectory
System.IO.Directory.GetCurrentDirectory()
——上面兩種得到的是當前路徑,這個路徑不必定是程序所在的路徑。任何會改變當前路徑的方法都會改變它,例如:OpenFileDialog每換一次目錄就會改變它。所以,用這2個方法獲取程序路徑並不可靠。
AppDomain.CurrentDomain.BaseDirectory
AppDomain.CurrentDomain.SetupInformation.ApplicationBase
——這兩個只能在WindowForm中使用;這兩個方法是可靠的獲取程序路徑的方法。返回的路徑最末以"\"結尾。能夠方便的在後面加入任何Path。固然就算沒有也能夠用Path.Combine來合併路徑以得到想要的路徑。
Application.StartupPath
——這個方法也是可靠的獲取程序路徑的方法。不過返回的路徑最末並無"\"結尾。另外由於是Forms命名空間的。所以若是使用WPF仍是不用的好。
Application.ExecutablePath
——這個方法獲取的是執行程序的完整文件名。是最可靠的方式,只須要去掉程序文件名就能夠得到路徑。
關於Nginx設置端口號,在Asp.net 獲取不到的,解決辦法
不知道你有沒有遇到過這樣的問題,網站訪客多起來後,內心非常高興,加上了Nginx反向代理,出問題了
原來是這麼寫的:
Request.Url.ToString()
輸出是這樣的:
http://www.zhyj2013.com:6038/Default/Index
無緣無故多出個端口號
Nginx是這樣配置的
server { listen 80; server_name www.zhyj2013.com; location / { root html; index index.html index.htm; proxy_pass http://localhost:6038; proxy_set_header Host $http_host:$server_port; proxy_set_header X-Real-IP $remote_addr; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
你們都是這樣配置的,沒有什麼問題,網上也找不到Asp.Net解決問題的方法,最後我翻看了System.Web.dll 發現他讀取appSetting節點 aspnet:UseHostHeaderForRequestUrl 子節點,因而,在項目的WebConfig加上配置,好了
<appSettings> <add key="aspnet:UseHostHeaderForRequestUrl" value="true"/> </appSettings>
再刷新
輸出是這樣的:
http://www.zhyj2013.com/Default/Index
.Net程序員 初學Ubuntu ,配置Nignix
一、安裝VM虛擬機
二、升級VI編輯器
三、安裝Nginx
四、測試localhost
五、編輯配置文件
僅僅用了記錄一個過程,不會太詳細
一、安裝虛擬機,網上一大片,不是特別難
二、爲何要升級VI編輯器?
vi至關於windows的記事本,可是習慣了windows的我,不會用,上下左右箭頭都與平時不同,查了好久的各類命令,找到一篇博文,地址以下:
解決Ubuntu中vi命令的編輯模式下不能正常使用方向鍵和退格鍵的問題
2.一、vi 的使用,在黑窗口裏面輸入 sudo vi filename ,回車,根據提示輸入密碼,回車,這樣就能看到文件的內容了,也是在當前黑窗看到的,跟windows很不同
此時,是在命令行模式,不能編輯輸入文字,一直回車知道本身想編輯的那一行,把光標移動到想要編輯的字符,
輸入 i ,此時,進入插入模式,能夠寫文字了,不想寫了,按下esc鍵,重回到了命令模式,此時也沒有保存文件
若是想保存文件,在命令模式下輸入 :w! ,回車,就保存了,輸入的時候,看黑窗的最下方。
若是想退出的話,能夠輸入 :q ,就回到了打開以前的
參考的網址是:
三、安裝niginx 是由於用到了一點點
打開黑窗口 輸入,
sudo apt-get install nginx
按照提輸入密碼,最後沒有報錯就是安裝完成了。
參考網站
在虛擬機內打開瀏覽器,輸入localhost應該能看到一個nginx的默認頁面
3.一、安裝後,我找到了這麼幾個文件夾
/etc/nginx/ 這個是主文件夾
/etc/nginx/nginx.conf 這是主配置文件,可是內容跟windows的時候,稍微有點不同,server配置在
/etc/nginx/sites-available/default 這是主要的配置文件,我主要是在這裏面修改了反向代理的配置
/var/www/http/index.nginx-debian.html 這是nginx的默認首頁
四、測試,在上一步已經測試過了
五、編輯配置文件,這個是核心的,因爲以前我在windows上簡單的配置過,就使用第一步的vi編輯器作了配置,這裏把個人文件內容貼下面,增長如下篇幅
server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name _; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; } location /tydyxsk/ { proxy_pass http://www.tydyxsk.com/; } location /Site/ { proxy_pass http://www.tydyxsk.com/Site/; } location /attached/ { proxy_pass http://www.tydyxsk.com/attached/; } }
只有後面的三個 location是我配置的,最終實現了以下效果:
輸入http://localhost ,顯示默認頁面
輸入http://localhost/tydyxsk/,顯示太原德育新時空的主站
截圖幾張
做爲一個老鳥,真的發現不學習就落後
夜深了,寫了個JQuery的省市區三級級聯效果
剛剛練手的JQuery,但願大神們指正
主要實現如下功能:
一、三級菜單級聯加載數據
二、能夠在不操做腳本的狀況下,給元素加屬性實現級聯功能
三、自定義動態顯示數據
諮詢問題:
對於通常比較固定不變的數據,是否是應該生成靜態的文件,直接加載整個數據文件,訪問文件比較好?仍是這樣動態的訪問比較好?
通常的數據文件,小的會在50k,大的會在3M
這個能夠討論下
1 /** 2 省市區縣級聯 3 */ 4 (function($){ 5 6 /* 7 * 8 *獲取ele的相對元素 9 * 10 **/ 11 function CssFirstElement(ele, css) { 12 ele = $(ele); 13 if (!ele) { 14 var event = event ? arguments[0] : window.event; 15 ele = event.srcElement ? event.srcElement : event.target; 16 ele = $(ele); 17 } 18 var targetInpage; 19 20 if ((typeof css == 'string') && css.constructor == String && css.substr(0, "css:#".length) == "css:#") { 21 //以css:# 開頭,是一個ID選擇器 22 targetInpage = $( $(css.substring(4))[0] ); 23 } else if ((typeof css == 'string') && css.constructor == String && css.substr(0, "css:".length) == "css:") { 24 //以css: 開頭,是一個基於元素的父級元素 25 var css0 = css.substring(4); 26 if (css0.split(' ').length==1) { 27 var parentCss = css0.substring(0, css0.indexOf(' ')); 28 var eleCss = css0.substring(css0.indexOf(' ')).replace(/(^\s*)|(\s*$)/g, ""); 29 targetInpage = ele.parents(eleCss + ":first"); 30 } else { 31 var parentCss = css0.substring(0, css0.indexOf(' ')); 32 var eleCss = css0.substring(css0.indexOf(' ')).replace(/(^\s*)|(\s*$)/g, ""); 33 targetInpage = ele.parents(parentCss+":first").find(eleCss); 34 } 35 36 } else if ((typeof css == 'string') && css.constructor == String) { 37 targetInpage = $(css); 38 } else { 39 //對象直接返回 40 return []; 41 } 42 43 return targetInpage.length > 0 ? $(targetInpage.get(0)) : []; 44 } 45 function SelectData(element) { 46 this.element = element;//元素 47 this.optionUrl = element.attr("data-optionUrl");//加載選項的url 48 this.defaultValue = element.attr("data-defaultValue");//加載選項試的默認值 49 this.display = element.attr("data-display");//返回對象的 option 顯示的鍵 50 this.value = element.attr("data-value");//返回對象的 option 綁定的鍵 51 this.changeTarget = CssFirstElement(element, element.attr("data-changeTarget"));//元素選擇改變後,觸發目標元素從新加載選項 52 this.showAll = element.attr("data-showAll");//是否顯示所有選項 53 this.immediately = element.attr("data-immediately");//是否當即加載選項 54 this.param = element.attr("data-param");//請求時攜帶的參數 55 //有須要觸發改變選項的目標,就添加change事件,觸發目標請求時,攜帶的參數 56 if (this.changeTarget.length > 0) { 57 this.element.on("change.selectDataFill",$.proxy(this.changeEvent,this)); 58 } 59 this.element.data("SelectDataFillObj",this); 60 } 61 SelectData.prototype = { 62 changeEvent: function () { 63 this.changeTarget.attr("data-param", 64 this.element.get(0).name + "=" + this.element.get(0).value); 65 this.changeTarget.data("SelectDataFillObj").empty(); 66 67 var targetW=this.changeTarget; 68 while (true) { 69 targetW = targetW.data("SelectDataFillObj").changeTarget; 70 if (targetW && targetW.length>0) { 71 targetW.data("SelectDataFillObj").empty(); 72 } else { 73 break; 74 } 75 } 76 this.changeTarget.data("SelectDataFillObj").LoadData(); 77 }, 78 empty: function () { 79 this.element.empty(); 80 if (this.showAll) { 81 $("<option value=\"\">所有</option>").appendTo(this.element); 82 } 83 }, 84 FillDataSuccess: function (data) { 85 debugger; 86 var element = this.element; 87 this.empty(); 88 89 for (var i = 0; i < data.list.length; i++) { 90 var item = data.list[i]; 91 $("<option value=\"" + item[this.value] + "\" " + 92 (item[this.value] == this.defaultValue ? "selected" : "") + ">" + 93 item[this.display] + "</option>").appendTo(element); 94 } 95 if (this.element.val()!='') { 96 this.element.trigger("change.selectDataFill"); 97 } 98 }, 99 LoadData: function () { 100 $.getJSON(this.optionUrl,this.element.attr("data-param")).success($.proxy(this.FillDataSuccess, this)); 101 } 102 }; 103 $.fn.SelectDataFill = function () { 104 105 this.each(function (index, element) { 106 107 var element = $(element); 108 var obj = new SelectData(element); 109 if (obj.immediately) { 110 obj.LoadData(); 111 } 112 113 }); 114 115 } 116 117 118 })(jQuery);
應用:
1 <td colspan="3"> 2 <select name="ProvinceId" 3 data-optionUrl="/BasicPlugin/Area/ProvinceJson" 4 data-defaultValue="3" 5 data-display="Name" 6 data-value="Id" 7 data-changeTarget="css:td select[name=CityId]" 8 data-showAll="true" 9 data-immediately="true"> 10 <option value="">請選擇</option> 11 </select> 12 <select name="CityId" 13 data-optionUrl="/BasicPlugin/Area/CityJson" 14 data-defaultValue="1" 15 data-display="Name" 16 data-value="Id" 17 data-changeTarget="css:td select[name=DistrictId]" 18 data-showAll="true"> 19 <option value="">請選擇</option> 20 </select> 21 <select name="DistrictId" 22 data-optionUrl="/BasicPlugin/Area/DistrictJson" 23 data-defaultValue="1" 24 data-display="Name" 25 data-value="Id" 26 data-changeTarget="css:td select[name=StreetId]" 27 data-showAll="true"> 28 <option value="">請選擇</option> 29 </select> 30 <select name="StreetId" 31 data-optionUrl="/BasicPlugin/Area/StreetJson" 32 data-defaultValue="1" 33 data-display="Name" 34 data-value="Id" 35 data-showAll="true"> 36 <option value="">請選擇</option> 37 </select> 38 </td>
以上代碼中的請求路徑,如 /BasicPlugin/Area/StreetJson 返回的json格式爲:
1 { 2 list:[ 3 {ID:1,Name:"名稱",Code:"001"}, 4 {ID:1,Name:"名稱",Code:"001"} 5 ] 6 }
效果以下:
一級選擇改變,相關聯的均從新加載數據,若是加載項中有默認值,則會選中默認值
暫時公開訪問地址能夠看到效果:
http://uiprogrammer.sxxxt.cn/Home/Index