chilin99999-blog
chilin99999-blog
千刃的網頁筆記
33 posts
CSS、Javascript、dotnet-mvc
Don't wanna be here? Send us removal request.
chilin99999-blog · 8 years ago
Text
[JS] AND(&&)與OR(||)
撰寫Javascript, && 與 || 是不可或缺的。
最常見的使用方式,就是在if判斷式內:
if(conditionA && conditionB) { // do something.. }
但,你真的了解 && 與 || 的運作方式嗎?
最常見的迷思,就是認為 && 與 || 所返回的是個Boolean值。
小明:「咦?不是嗎?if判斷式不就是接收到Boolean值後,再決定是否執行的嗎?」
其實不然!
&& 與 || 所回傳的,是最後一個判斷的值!!!!
舉例來說,A&&B,若A是true,則會再判斷B是否為true。
所以B是最後一個判定的值。
if正是接收那值,再將其強制轉型為Boolean做判斷!
以下,用程式碼做細部解釋:
let a = true; let b = null; let c = 'abc'; let result1 = a && c; // a是truthy值,所以會回傳c let result2 = b && c; // b是falsy值,所以直接回傳b let result3 = a || c; // a是truthy值,所以直接回傳a let result4 = b || c; // b是falsy值,所以會回傳c
哇哇哇,真是博大精深啊!
但是...
if都幫我強制轉型得好好的,不懂好像也沒差吧?
學會這對我有何好處?
其實好處可多了!
我們可以利用JS這語法特性,大幅精煉一些判斷的語法!!!
let david = { hair: { color: 'red', }, }; let myColor = david.hat.color; // Uncaught TypeError! Cannot read property 'color' of undefined!
我們預期,如果david沒有hat這屬性,就給予myColor變數undefined。
david有hat這屬性,就將value傳遞過去。
但...糟了個糕,程式掛掉啦!
為了防止這種讓人崩潰的情況,我們可能會想到以下解法:
let david = { hair: { color: 'red', }, }; let myColor; if(david.hat) { myColor = david.hat; } // undefined
我們的問題解決啦!
但這冗長的代碼,實在無法讓人心情美麗。
我們讓&&登場吧!
let david = { hair: { color: 'red', }, }; let myColor = david.hat && david.hat.color; // undefined
若david的hat屬性存在,則會回傳david.hat.color。
若david的hat屬性不存在,則會回傳david.hat,也就是undefined!
搞定啦!簡短的一行,做到剛剛費盡千辛萬苦(?)才達成的事情!
以下,再提供幾個實務常見用法,讓大家做參考。
/******* 1 *******/ let david = { favoriteColor: 'yellow', hair: { color: 'red', }, }; let myColor = (david.hat && david.hat.color) || david.favoriteColor; // yellow //沒有登記到david的帽子顏色時,就以他最愛顏色為主 /******* 2 *******/ let height = boxHeight || 100; // 給定預設值
0 notes
chilin99999-blog · 8 years ago
Text
[JS] 瀏覽器/裝置偵測
不多說,直接給代碼。
console.log(JSON.stringify({ isAndroid: /Android/.test(navigator.userAgent), isCordova: !!window.cordova, isEdge: /Edge/.test(navigator.userAgent), isFirefox: /Firefox/.test(navigator.userAgent), isChrome: /Google Inc/.test(navigator.vendor), isChromeIOS: /CriOS/.test(navigator.userAgent), isChromiumBased: !!window.chrome && !/Edge/.test(navigator.userAgent), isIE: /Trident/.test(navigator.userAgent), isIOS: /(iPhone|iPad|iPod)/.test(navigator.platform), isOpera: /OPR/.test(navigator.userAgent), isSafari: /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent), isTouchScreen: ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch, isWebComponentsSupported: 'registerElement' in document && 'import' in document.createElement('link') && 'content' in document.createElement('template') }));
0 notes
chilin99999-blog · 8 years ago
Text
[JS] 陣列操作實務範例
Array操作系列文:http://chilin99999.tumblr.com/tagged/array%E6%93%8D%E4%BD%9C
這篇文章,舉幾個比較貼近實務的case,與大家分享。
如果大家想對Array做什麼害羞的事(?),可以在底下留言。
版主會的話就將其補上~
let data = { title: 'Javascript超級大亂鬥', players: { teamA: [ { name: 'David', age: 18, score: 6688, }, { name: 'Peter', age: 16, score: 5689, } ], teamB: [ { name: 'Kelly', age: 62, score: 7566, }, { name: 'Diana', age: 24, score: 4089 } ] }, };
情境1:找出Diana是否為玩家
data.players.teamA.concat(data.players.teamB).some(d => d.name === 'Diana'); // true
情境2:從players清單中刪除Peter
Object.keys(data.players).forEach((key) => { let team = data.players[key]; let index = team.map(d => d.name).indexOf('Peter'); if(index > 0) team.splice(index, 1); });
情境3:找出分數最高的玩家
data.players.teamA.concat(data.players.teamB).reduce((pre, cur) => { return pre < cur ? pre : cur; }); // {name: "Diana", age: 24, score: 4089}
情境4:將新成員Tom隨機加入某隊
let playerTom = { name: 'Tom', age: 87, score: 8787, }; let randomTeam = Math.floor((Math.random()) + 1) ? 'teamA' : 'teamB'; data.players[randomTeam].push(playerTom);
0 notes
chilin99999-blog · 8 years ago
Text
[JS] 迴圈與非同步處理
本來想先寫些Array操作的實務經驗,不過有觀眾提到想看非同步(Async)處理。
so...插隊一下好囉。
---
寫網頁,透過ajax與server side溝通是非常常見的。
而ajax本身是非同步方法。
因此建構網頁時,非同步方法可說是無所不在。
但...寫個範例,還要架API來call未免太過麻煩..
因此我會用其他方式來模擬API request。
// 以Math.random模擬呼叫API時的時間長短不一。並最後回傳Promise物件。 function HTTP(data) { let delayedTime = Math.floor(Math.random() * 1000 + 1); return new Promise((resolve) => { setTimeout(() => { resolve(data + ' ok'); }, delayedTime); }); }
宣告了個HTTP function,模擬呼叫API。
// 跑個forEach呼叫HTTP,將資料塞進myData後檢查其長度,並顯示處理後的資料。 let array = ['a', 'b', 'c', 'd', 'e']; let myData = []; array.forEach(d => { HTTP(d) .then((result) => { myData.push(result); }); }); console.log(myData.length); // 0 myData.forEach(d => console.log(d)); // Nothing shit happened!
花惹發?
為什麼myData.length是0?
明明就塞進了很多資料啊!!!
這是因為,HTTP是非同步方法。
所以底下的console.log與myData.forEach在HTTP回傳資料前,就先執行了。
那...該怎麼辦呢?
let array = ['a', 'b', 'c', 'd', 'e']; let myData = []; let promises = []; // 注意這個 array.forEach(d => { promises.push( HTTP(d) .then((result) => { myData.push(result); }) ); }); Promise.all(promises) .then(() => { console.log(myData.length); // 5 myData.forEach(d => console.log(d)); // Holly cow! It works! });
Tumblr media
宣告個promises的陣列,將每個HTTP回傳的Promise物件塞進去!
然後使用Promise.all,限定當每個promise都resolve後,才執行後續(then)的動作。
這樣,就可以處理好非同步請求帶來的執行順序先後問題囉!
---
有觀眾提問,有辦法讓HTTP回傳的資料,按照原本的順序嗎?
其實可以的!不過思維略有不同。
let array = ['a', 'b', 'c', 'd', 'e']; // 改用map方式承接所有Promise,但回傳後先不push儲存 let promises = array.map(HTTP); Promise.all(promises) .then((data) => { console.log(data.length); // 5 data.forEach(d => console.log(d)); // Holly cow! It works in order! });
差異在於,HTTP的每個Promise回來,不做後續動作(then)。
Promise.all等待所有Promise完成(resolve)後,將所有回傳資料用then承接。
由於then的data,會"依序"對應到Promise.all裡的所有Promise,
所以最後的forEach就會按原本的順序執行囉!
0 notes
chilin99999-blog · 8 years ago
Text
[JS] Array資料組裝與查詢
Array操作系列文:http://chilin99999.tumblr.com/tagged/array%E6%93%8D%E4%BD%9C
不熟悉的朋友可以先翻閱前兩篇。
---
這篇文章,將介紹Array組裝與查詢的幾個語法:map, some, every, find, filter, reduce。
這些方法很具實務性,適合將DB提取的資料加工處理後渲染到View。
從DB提取的資料:
let array = [ { id: 1, name: '小明', age: 20 }, { id: 2, name: '小華', age: 26 }, { id: 3, name: '大雄', age: 13 }, { id: 4, name: '小夫', age: 15 } ];
(1) map : 將Array以特定規則組裝成新的Array
// 提取所有人的名字並組成陣列 array.map(d => d.name); // ['小明', '小華', '大雄', '小夫']
(2) some : 查詢Array中是否有符合特定規則的元素
// 是否有25歲以上的老屁股 array.some(d => d.age > 25); // true
(3) every : 查詢Array中是否每個元素都符合特定規則
// 是否沒有15歲以下小鮮肉 array.every(d => d.age >= 15); // false
(4) find : 查詢符合特定規則的第一筆資料
// 大雄,查水表囉 array.find(d => d.name === '大雄'); // {id:3, name:'大雄', age:13}
(5) filter : 篩選出符合特定規則的所有資料
// 18歲以下屁孩滾出來 array.filter(d => d.age < 18); // [{id:3, name:'大雄', age:13}, {id:4, name:'小夫', age:15}]
(6) reduce : 以特定規則進行累計運算
// 班長,統計班上所有人年紀總和 array.reduce((total, cur) => { return total + cur.age }, 0); // 74
reduce的進階用法,之後有空另撰文章介紹。
0 notes
chilin99999-blog · 8 years ago
Text
[JS] 遍歷Array
講白話一點,就是跑迴圈啦xD
不過Javascript裡,跑迴圈撈取Array資料的方式有數種。
以下,來幾個簡單示範:
let array = [2, 4, 6, 8, 10]; for(let i=0; i
(2) forEach
let array = [2, 4, 6, 8, 10]; array.forEach(item => { console.log(item); });
(3) for of
let array = [2, 4, 6, 8, 10]; for(item of array) { console.log(item); }
從C語言過來的朋友,可能會直覺想到for的方法
不過實務上,個人更常使用forEach。覺得其更簡潔、可讀性更高。
for of則是ES6才新增的語法,與forEach跟for各有87%的相似度 (?)
版主我只在一種情況使用for of,就是在 "需要條件式中斷迴圈" 的時候!
因為,forEach是無法用break中斷的喲!!!
至於各語言常見的while迴圈,在javascript裡也是支援的。
只是個人覺得while迴圈並不適合用來遍歷Array,所以就不多介紹了。
0 notes
chilin99999-blog · 8 years ago
Text
[JS] Array基本操作
近來年,Javascript framework不斷推陳出新,又以Angular、React、Vue為箇中翹楚。
相較於JQuery,這些framework為我們處理了許多瑣碎工作。
漸漸地Javascript的開發者只需注重資料的流動,而不必花太多心思在DOM的操作。
而資料的流動,通常離不開Array的操作。
所以這Blog的第一篇文章,將介紹常見的Array操作技巧。
let array = []; array.push('Apple'); // ['Apple'] array.push('Orange'); // ['Apple', 'Orange']
(2) splice : 刪除Array的值
let array = ['Apple', 'Orange', 'Banana']; array.splice(1, 1); // ['Apple', 'Banana']
(3) concat : 串接Array
let array = ['Apple']; let array2 = ['Orange', 'Banana']; let array3 = array.concat(array2); // ['Apple', 'Orange', 'Banana']
(4) indexOf : 取得element在Array中的位置
let array = ['Apple', 'Orange', 'Banana']; array.indexOf('Banana'); // 2
(5) sort : Array排序
let array = ['Apple', 'Orange', 'Banana']; array.sort(); // ['Apple', 'Banana', 'Orange']
sort方法之後將另外撰文介紹。 下一篇文章,將介紹各種遍歷Array的方式。
0 notes
chilin99999-blog · 9 years ago
Text
【CSS】inline-block間距問題
「踩地雷時間到,我們一起來禱告」
          周杰倫 - 以父之名 (?
今天又接觸到一個關於 inline-block,很容易踩到的地雷。
我將div設為inline-block,想將其水平併在一起。
卻發現,明明margin為0,div之間卻仍有間隔。
這要從css的display介紹起。
display最常見有三種型態:
inline:行內元素。不換行、無法自由伸展。
block:區塊元素。自動換行、可自由伸展。
inline-block:行內區塊元素。不換行、可自由伸展。
而Html有個特性:
為了程式設計師排版方便,行內元素之間的空白、換行皆會被忽略,濃縮為 "一個空白"!
大家處理行內元素時,應該習慣這點了。
但行內區塊元素,一樣會受這因素影響!
也就是說,div與div之間的間隔,其實是一個空白字元擋在那!
...
好吧。地雷找到了,但該如何拆除呢?
方法1、將行內區塊元素併再一起。
簡單可行,但影響排版可讀性。
方法2、設定負數margin。
調整略嫌麻煩
方法3、使用float。
須注意浮動的清除,避免影響後續物件
方法4、使用flex。
新時代解決方案,可惜IE9不支援,IE10也只部分支援...
以上方法各有利弊,大家就看心情使用吧...
0 notes
chilin99999-blog · 9 years ago
Text
【JQuery】mouseover多重觸發
我在網路上找到了個不錯的JQuery Slider套件,
想將其加上 "每當hover時autoplay會暫停的功能",所遇到的問題。
程式碼如下:
它可以work,但並不好。
加上個console.log,會發現滑鼠在slider上移來移去時,event會被多重觸發(multiple trigger)。
該如何解決呢?
答案就是:改使用mouseenter!
看看下面這範例,你會豁然開朗。
http://jsfiddle.net/ZCWvJ/7/
一個container包著許多子元素的情境下,mouseover會當你在子元素之間移動時被觸發,而mouseenter不會!
也就是說,將程式碼改成底下這樣,就可以解決囉。
0 notes
chilin99999-blog · 9 years ago
Text
【CSS】文字破版處理
換行時,切斷單字
word-break: break-all;
換行時,不切斷單字(整個單字跳下一行)
word-wrap: break-word;
---
同pre
white-space: pre;
保留空白、無視換行
white-space: pre-wrap;
保留換行、無視空白
white-space: pre-line;
0 notes
chilin99999-blog · 9 years ago
Text
【MVC】專案Publish後,Code First的Seed方法未被呼叫
使用Code First建置Entity Framework時,
在NuGet的主控台輸入Enable-Migrations,便會建置Migrations資料夾。
資料夾裡有個Configuration.cs,裡面的Seed方法會在每次執行Update-Database時被呼叫。
但問題來了,若專案以File System方式發行,Seed方法便不會被呼叫。
該怎麼做呢?
其實步驟很簡單。
在Global.asax.cs放個Database.SetInitializer就搞定囉!
ps. ApplicationDbContext是我存取Database的Context,因人而異喲!
0 notes
chilin99999-blog · 9 years ago
Text
【CSS】文字閃爍
其實,不需要Javascript。
只要CSS就能讓文字閃爍了。
如底下的程式碼。
animation-duration 指run一個循環所需的時間。
animation-name: blink; 呼叫底下的 @keyframes blink。
animation-iteration-count: infinite; 表示無限循環。
@keyframes blink 裡可對每個時段點的透明度做調整。
如此,搞定。
0 notes
chilin99999-blog · 9 years ago
Text
【MVC】LINQ to Entities取得最近7天資料
想用LINQ取得資料庫裡,最近七天的資料,該怎麼做呢?
上網搜尋一下,應該會找到一些方法。
例如.
Where( m => m.Time.Subtract(DateTime.Now).Days==0)
Where( m => m.Time.ToString("yyyyMMdd")==DateTime.Now.ToString ("yyyyMMdd")
Where(d => d.Time > DateTime.Now.AddDays(-1))
很遺憾, 這些方法在LINQ to Entities都無法使用。
因為您會遇到一個錯誤:
Tumblr media
這是為什麼呢?
難道分享這些解法的網友們都是傻逼,搞錯了嗎?
其實不是。這些在許多LINQ的應用場合都是OK的。
因為LINQ to Entities最終得轉譯成SQL語法,而SQL語法並不是那麼彈性。
也就是說,那些C#方法全都 無 法 轉 譯。
那這樣就GG了嗎?人生充滿晦暗了嗎?
有個方法提供給大家。
先用變數,將七天前的今天存下來。
var Now = DateTime.Now.AddDays(-7);
而LINQ裡只使用普通的大於小於判斷句。
Where(d => d.Time > Now)
如此一來,在LINQ裡沒用到任何C#方法,而順利過關囉!
0 notes
chilin99999-blog · 9 years ago
Text
【MVC】非同步資料刷新與分頁切換(Ajax + Partial View)
情境:
實作留言板,同一個View能顯示留言、新增留言。
新增留言與切換分頁時,不必跳轉頁面,留言清單也能刷新。
請參考GitHub上的專案程式碼:
https://github.com/chilin99999/.net-MVC-MessageBoard-Ajax
首先,透過NuGet下載兩個套件:
Microsoft.JQuery.Unobtrusive.Ajax
PagedList.Mvc
分頁的使用方法,請參考 "大神MRKT的部落格"。
這篇文章的主軸在於,Ajax與Partial View的應用。
Step 1,
[ Views - Home - Index.cshtml ]
首先,引用Unobtrusive.Ajax的js檔。
Tumblr media
[ Views - Web.config ]
並在View的Web.config新增引用Model與分頁(不是專案的Web.config喲)
Tumblr media
Step 2,
[ Models - DatabaseModel ]
在Models資料夾新增檔案,建立ADO.NET實體資料模型。
我提供的程式碼以Code first的方式建立。
Step 3,
[ Controllers - HomeController ]
Controller裡包含三個方法。
Index直接return View()。
RenderPosts負責將留言清單以Partial View的方式渲染到網頁上。
NewPost負責新增留言,並導向RenderPosts(重新渲染留言清單)。
Step 4,
[ Views - Home - _MessageList.cshtml ]
開一個Partial View,存放顯示留言清單的邏輯。
分頁導覽列要給上 UpdateTargetId 屬性,以標示Partial View渲染的區域。
Step 5,
[ Views - Home - Index.cshtml ]
在Index.html以Ajax.BeginForm的方式建立form,以新增留言。
UpdateTargetId = "messages_block" 屬性代表要引入Partial View的div id。
Tumblr media
並使用RenderAction引入Partial View。
RenderAction 會先經由Controller的Action方法,因此渲染留言清單的程式碼要寫在這Action裡。
Tumblr media
Step 6,
[ Content - Index.css ]
[ Content - MessageList.css ]
最後,引入css做點修飾,就完工囉!
我提供的程式碼以功能展示為主,沒有美美的css,也沒有ViewModel做前端驗證。有興趣的各位再自己做修改囉~
---
2016/06/13
大神MRKT認為不使用ajax helper為佳。
因為JQuery等等的前端framework、library已經提供了強大的ajax語法,
而且ajax helper不利於前後端的權責分工。
以下提供個JQuery ajax的範例(截圖自另一個專案):
Tumblr media
success標示著ajax成功後要做的事,
透過 $(”#message_list_block”).html(data) 即可將Partial View刷新囉。
0 notes
chilin99999-blog · 9 years ago
Text
【MVC】Identity會員權限處理
MVC的Identity(創建專案時,選擇個別驗證)以Code First方式創建DB,
預設便包含數張表單以處理會員機制。
登入、註冊等常用功能不必我們憂心,Account Controller已幫我們做好所有該做的事。
但會員權限的部分則需要花點心思。
因為Identity並未幫我們處理權限機制!
其實程式碼並不難,但不知道方法還是會撞得頭破血流..
首先,打開Account Controller,Register這Action即是處理會員註冊所必須處理的事情。
if (result.Succeeded) 這區塊即是 "登入成功後要做的事"
我們先宣告RoleManager,利用其產生權限。
再利用UserManager將使用者加入對應的權限。
Tumblr media
就這樣,沒了 A______A
延伸閱讀。
如果想在DB一生成,就已經設定好管理員呢?
這就得在Migrations / Configuration.cs做設置(Code First設定檔)。
Configuration.cs裡,有個名為Seed的方法,該方法會在DB生成時被呼叫。
Tumblr media
如法炮製,宣告UserManager與RoleManager。
檢查權限後,再新增使用者並加入權限,收工。
---
2016/06/16
會員權限機制能正確地被建立起來了。
但該如何在View對會員權限做判定呢?
看以下這段程式碼應該就可以理解。 
值得注意的是,千萬,不要用這狗屎做權限判定!
Roles.IsUserInRole("Admin")
因為這狗屎在本機測試時,完全沒有問題。
但一架到IIS上時,就會吐出個伺服���無法連線的錯誤給你,
讓你Debug到瘋掉!
血淚史啊...
0 notes
chilin99999-blog · 9 years ago
Text
【JS】完美封裝function
Javascript雖然沒有class,但還是可以應用OOP的概念。
OOP其中一個核心思維是封裝。
讓使用者不必了解function內寫些什麼,就能應用!
許多情況,單純利用funtcion就能搞定。
但如果要操作物件,還得將物件的id或class傳遞進去,使用上就麻煩些。
此時,就是prototype登場的大好時機!
參考我github上的浮動區塊專案:
https://github.com/chilin99999/floatBlock
以prototype擴充物件的方法:
$.prototype.floatBlock = function(){ .... }
就能以$(".div").floatBlock(); 這樣的方式來呼叫。
如果要傳遞參數進function呢?
利用$.extend,可以實作出OOP多型的概念!
Tumblr media
以上圖來說,options擁有的參數會給入settings,後者覆蓋前者。
options沒給的參數,��以settings(預設)為主。
Tumblr media
也就是說,呼叫function給入參數時,不管給的參數數量多少都可以。
沒給的參數就會使用js的預設數值,大大增加使用上的便利性。
大家快將OOP的概念應用到JS開發上吧!
---
2016/06/01更新(感謝 xiantank 提供資訊):
最新的ECMAScript 6已支援class囉!
也支援用extend的方式繼承了。
瞧瞧這個吧.. http://es6-features.org/#ClassDefinition
是否有點面熟呢...TypeScript是你?
0 notes
chilin99999-blog · 9 years ago
Text
【JS】開發JS的好夥伴 - TypeScript
TypeScript是微軟開發的工具語言,最後會編譯出Javascript。
TypeScript有著更濃厚的物件導向特性,能實作class、interface、module!
而且向下相容Javascript。
簡單來說,在TypeScript寫Javascript的語法也完全沒問題!
來看個簡單的範例吧。
我在Visual Studio 2015新增TypeScript檔案(檔名為greet.ts)。
在Html檔案裡引入<script src="~/Scripts/Custom/greet.js"></script>
注意,引入的檔案是.js,不是.ts!
點擊方案總管的"顯示所有檔案",會發現編譯後,出現了greet.js。
Tumblr media
因此,我們照往常引入.js檔即可以。
接著,在greet.js裡寫入以下內容:
Tumblr media
喔喔喔熟悉的class出現了啊!
按下Run後,即可看到Hello World的出現囉!
0 notes