Kurt Hsu's blog

The Rails developer in taiwan.


  • 首頁

  • 標籤

  • 分類

  • 歸檔

[CSS]我看到的浮動元素(float)與clear

發表於 2017-03-31 更新於 2019-08-20 分類於 CSS

在工作上遇到了要製作像Line一樣的聊天畫面,起先以為很簡單,但沒想到一路上學了超多東西XD,之前就一直很想知道clear: both;是幹嘛的,這次有了更深入的了解。

clear在MDN就可以查到他有很多屬性,這次就分享最常用的clear: both;就好(其實過程中我也只用到這個)。

浮動元素

什麼是浮動元素?網路上有很多專業解釋,但在這裡我用我觀察和測試的結果用白話解釋。

浮動元素就是把該元素抓起來漂浮在上面,聽起來很抽象吧?你可以想像一條橡皮筋綁著一疊紙錢,此時橡皮筋就像一個tag,一個容器(div, p, span…等等)之類的而他的大小被他裡面的紙錢(elements)撐大,而你紙錢從橡皮筋裡面抽出來的動作就像是給他float的特性,他在橡皮筋上面了,而橡皮筋因為裡面的紙錢被抽出來而失去了原來的大小。

但這畢竟不是照著物理世界行動的東西,所以他有下列一些特性:

1.擁有至右或至左的特性(因為float最常用的屬性是left和right而已)。
2.對容器不具實體(就像上述橡皮筋與紙錢的比喻)。
3.本身像內聯元素(inline element)一樣排列。
4.會與同層的內聯元素(inline element)連結。

這是我觀察的四個特性,一個一個解釋很簡單,但一次要面對兩個特性以上的話就會變得很危險,所以建議使用float的時候最好越單純越好,不要一次觸發他太多特性會很難維護,會很想把筆電折成兩半XD。

直接來看範例(或者點我看線上實作):

html
1
2
3
4
5
6
<div class="wrapper">
<div class="box">stone</div>
<div class="floater">ff ff ff ff ff </div>
<div class="floater">ff ff ff ff ff </div>
<div class="box">stone2</div>
</div>

css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.wrapper{
border: 1px solid blue;
padding: 10px;
width: 200px
}
.floater {
border: 1px solid;
width: 20px;
float: left;
}
.box {
width: 100px;
border: 1px solid red;
}

螢幕快照 2017-03-31 上午10.39.39.png

首先看充滿ff的黑色框框是我使用float: left;讓他產生第一點特性的至右。

再來可以看到他對他的容器有藍色框框的wrapper並沒有實質的佔體積,所以黑色框框是直接超出藍色框框的並沒有把它撐大。

第三是他像內聯元素一樣排排站好,就像這種tag一樣,可以看到兩個黑色框框是站在一起的。

最後一點很有趣,他會跟別人的內聯元素結合!你可以看到如果第二個紅色框框的stone2還有空間讓兩個黑色框框置入,他會挪出空間,並且右讓黑色框框符合他第一點的特性讓他至左。

再來如果剛剛第二個紅色框框的stone2並沒有空間讓他置入呢?
他會迫使stone2的內聯元素換行所以會撐大stone2的紅色框框。
稍微改一下CSS裡的box屬性修改就會有下面效果:

css
1
2
3
4
.box {
width: 60px;
border: 1px solid red;
}

螢幕快照 2017-03-31 上午10.38.55.png

stone2被撐大了!
那如果我強制設定紅色框框的高度不讓他被撐大呢?

css
1
2
3
4
5
.box {
width: 60px;
height: 40px;
border: 1px solid red;
}

螢幕快照 2017-03-31 上午10.38.35.png

天阿,雖然紅色框框的區塊元素(block element)排列特性是正確的,但裡面的內聯元素卻被搞到離家出走了!!

如果還有人可以這樣子維護和開發的下去我真的會很欽佩他,如果是我到這裡就會想要砍掉重練了XD,所以說在使用浮動元素的時候最好是用單純的使用越好,不要一次使用它太多特性。

clear

首先可以直接去觀察MDN提供的幾個範例玩玩看。

我觀察出的特性:

clear可以把一個元素左右邊的浮動元素清除掉,所謂的清除掉並不是刪除他,而是一個王不見王的感覺,不是你換行就是我要換行,反正不是在同一行就對了!

clear使用的情況很多,這邊只分享我遇到的問題,我想要做一個類似像賴聊天的泡泡框,當然做左邊的沒有問題,最大的問題是右邊的泡泡框。

所以我需要把裡面的一個區塊至右,並且因為區塊內的元素多寡大小而自動向左邊變寬或變長,最後外面的容器也要隨著裡面的區塊改變高度,所以統計一下我要做的事情:

1.容器(wrapper)隨著區塊的大小改變高度,這裡用padding: 10px;可以做到。
2.區塊可以隨著裡面元素的多寡大小自動變更寬或長,這裡用display: inline-block;可以做到。
3.我需要把區塊至右,而且區塊是向左邊變寬,這裡用float: right;可以做到。

那我們來開心寫code吧!

html
1
2
3
4
5
6
<div class="wrapper">
<div class="block">
text<br>
I real want succeed
</div>
</div>

css
1
2
3
4
5
6
7
8
9
10
.wrapper{
width: 200px;
border:1px solid black;
padding:10px;
}
.block {
border: 1px solid blue;
display: inline-block;
float: right;
}

螢幕快照 2017-03-31 上午11.10.17.png

發生什麼事情了!???
為什麼我的wrapper包不住它!?
我想想阿靠就只是因為float的第一個特性讓他撐不開容器而已,換個屬性也可以囉!於是…

display: absolute;會產生跟float一樣的漂浮特性。
失敗。

把泡泡框margin和padding到最右邊後但是泡泡框是往右邊長。
失敗。

做一個區塊元素去比照這個泡泡框的高度一起長高?我好像找不到這個方法…XD。
失敗中的失敗。

想來想去查來查去剛好看到了有人說clear這個方法可以撐開因為float而撐不開的容器!
只要在容器最後面加上一個擁有clear: both;的tag就行了!

於是乎…:

html
1
2
3
4
5
6
7
<div class="wrapper">
<div class="block">
text<br>
I real want succeed
</div>
<div class="clear"></div>
</div>

css
1
2
3
4
5
6
7
8
9
10
11
12
13
.wrapper{
width: 200px;
border:1px solid black;
padding:10px;
}
.block {
border: 1px solid blue;
display: inline-block;
float: right;
}
.clear {
clear: both;
}

螢幕快照 2017-03-31 上午11.10.06.png

終於做出我要的效果了…這是眼淚嗎??
終於可以告老返鄉了~耶~~!!

最後也推薦看看這個部落客寫的详解CSS float属性哦!

[JavaScript - Udemy] Hoisting(創造與提升)

發表於 2017-03-29 更新於 2019-08-20 分類於 JavaScript

之前在Udemy的平台上趁特價買了JavaScript全攻略:克服JS的奇怪部分的中文課程,似乎是直接翻譯JavaScript: Understanding the Weird Parts的英文課程,在英文課程裡使用者回饋的評價算是很不錯的。

#Hoisting(創造與提升)

這個階段是Javascript在初始化的時候會執行的動作。
當Javascript在一行一行執行程式碼以前,會先空出記憶體把所有變數和函示創造出來,但是先沒有放值進去。

我們直接看看範例(console.log後有斜線註解的地方代表有執行成功並寫出結果):

1
2
3
4
5
6
var a = 'Hi!';
function b () {
console.log('Is b!'); //"Is b!"
}
console.log(a); //"Hi!"
b();

到這邊不難理解Js從第一行執行到最後一行會發生什麼事情以及他的特性,那如果把程式碼換個位置呢?

1
2
3
4
5
6
console.log(a); //undefined
b();
var a = 'Hi!';
function b () {
console.log('Is b!'); //"Is b!"
}

第一行的console.log(a)並不是print出"Hi!"而是undefined,這是因為Javascript在初始化只會先空出記憶體去創造變數和函示,直到執行到給予該變數(例如:var a = ‘Hi!’;)。

以我們人類的看得懂的程式碼角度來看,Javascript在Hoisting的階段做了下列事情:

1
2
3
4
var a;
function b () {
console.log('Is b!');
}

但如果我們沒有先創造創造變數的話Javascript就會報錯囉!
例如改變剛剛的例子把var a = 'Hi!';這行拿掉:

1
2
3
4
5
6
console.log(a);
//錯誤:Uncaught ReferenceError: a is not defined
b();
function b () {
console.log('Is b!');
}

##執行環境
再來要順便淺談一下執行環境問題,Javascript的Hoisting是在該環境唷!譬如剛剛的程式碼是在全域環境,此時Hoisting在全域環境的有本來就有的window和this之外有自己創的變數a和函示b,如果創造的變數不是在全域環境而是在函示裡面呢?(順帶一提現在開始是我個人推測、測試與驗證XD)

1
2
3
4
5
6
7
8
9
console.log(a); //undefined
b();
console.log(c);
//錯誤:Uncaught ReferenceError: a is not defined
var a = 'Hi!';
function b () {
var c = 'Yo!';
console.log('Is b!'); //"Is b!"
}

此時在執行console.log(c);時又報錯了因為全域與函示是不同的環境,所以在Hoisting的時候找不到變數c可以創造,所以程式碼再改寫一下:

1
2
3
4
5
6
7
b(); //"Is b!"
function b () {
console.log(c); //undefined
var c = 'Yo!';
console.log(c); //"Yo!"
console.log('Is b!'); //"Is b!"
}

我們發現函示裡面Hoisting運行的方式跟全域的方式是一樣的,那我們來做個執行順序的統整吧!

1
2
3
4
5
6
7
8
9
console.log(a); //undefined
b();
var a = 'Hi!';
console.log(a); //"Hi!"
function b () {
var c = 'Yo!';
console.log(c); //"Yo!"
console.log('Is b!'); //"Is b!"
}

Hoisting沒問題之後再依造Javascript一行一行執行程式碼的特性,我們得出在console裡print出的順序為:undefined > "Yo!" > "Is b!" > "Hi!"

執行環境的地方是個人測試與淺見,如有觀念錯誤或更好的解釋方法歡迎留言糾正一下囉!

[JavaScript]map取代push取得Json裡的資料問題紀錄

發表於 2017-03-22 更新於 2019-08-20 分類於 JavaScript

map取代push實例

今天跟一起寫code的群組討論到JS世界裡盡量不要去使用直接改變變數的function,例如這邊的push,雖然我還不太懂切確的觀念是什麼不過還是分享一下朋友教的寫法,這種方法似乎比較精簡也直觀。

先紀錄我原本的寫法,在接取api的資料經常會碰到這種Json格式,我想要取得每個物件的name:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var apiArray = [
{
name: 'Kurt',
age: 25
},
{
name: 'Andy',
age: 40
},
{
name: 'Maggie',
age: 20
},
{
name: 'Mary',
age: 35
}];
var nameArray = [];
for (var key in apiArray) {
nameArray.push(apiArray[key].name);
}
console.log(nameArray); //["Kurt", "Andy", "Maggie", "Mary"]

朋友教我使用map去擷取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var apiArray = [
{
name: 'Kurt',
age: 25
},
{
name: 'Andy',
age: 40
},
{
name: 'Maggie',
age: 20
},
{
name: 'Mary',
age: 35
}];
var nameArray = apiArray.map(function(obj){
return obj.name;
});
console.log(nameArray); //["Kurt", "Andy", "Maggie", "Mary"]

兩種方法在這種小地方或許看不出來,但就直觀維護上這種方法看到return obj.name就大略知道在做什麼事情了。

[JavaScript] split 分割字串

發表於 2017-03-22 更新於 2019-08-20 分類於 JavaScript

split(分割字串)

Syntax(語法):

1
str.split([separator[, limit]]);

參考文章:Mozilla Developer Network(MDN)

字串分割完會變成陣列

直接看範例:

1
2
3
var stringToSplit = 'apple and banana are my favorite fruits.';
var arrayAfterSplit = stringToSplit.split(' ');
console.log(arrayAfterSplit); //["apple", "and", "banana", "are", "my", "favorite", "fruits."]

這時候要取得哪一個想要的字串只需要使用separator[index]就行囉!

當然我們可以分割再分割

1
2
3
4
5
6
7
var stringToSplit = "?id=12345678&passwd=00000000";
//在這裡我只要12345678這個字串時要做兩次分割
var arrayAfterSplit = stringToSplit.split('=');
console.log(arrayAfterSplit); //["?id", "12345678&passwd", "00000000"]
//這時候做第二次切割
var theIdNumber = arrayAfterSplit[1].split('&')[0];
console.log(theIdNumber); //"12345678"

選擇切出幾塊字串

使用方法:
split(separator, number);
直接看範例:

1
2
3
var stringToSplit = 'apple and banana are my favorite fruits.';
var arrayAfterSplit = stringToSplit.split(' ', 3); //只取三塊
console.log(arrayAfterSplit); //["apple", "and", "banana"]

搭配.join()更換字元

在MDN的範例裡面我發現有趣的東西是搭配.join()可以做到更換字元的效果:

1
2
3
var stringToSplit = 'apple and banana are my favorite fruits.';
var arrayAfterSplit = stringToSplit.split(' ').join('/');
console.log(arrayAfterSplit); //"apple/and/banana/are/my/favorite/fruits."

要注意這裡console.log出來的不是陣列又變回字串了!
join裡的東西會自動填入剛剛split的切割位置。

小記

會遇到這個問題是因為我遇到要利用網址(URL)取得使用者的id,這樣讓使用者在點進去網址的時候可以利用這個id得到他的資料,所以會搭配到var currentLocation = window.location;這個方法,例如網址為:
https://somecompany.com/somepage?id=123456
此時一進去這個連結我要用123456這個id去接取api初始化屬於該使用者的頁面資料:

1
2
3
4
var currentLocation = window.location;
console.log(currentLocation); //https://somecompany.com/somepage?id=123456
var arrayAfterSplit = stringToSplit.split('=');
console.log(arrayAfterSplit[1]); //"123456"

這樣就可以取得id囉,當然window.location取得的狀況有很多種所以一開始一定要先console.log下來看一下。

HTML Email(電子郵件內網頁) 問題紀錄

發表於 2017-03-21 更新於 2019-08-20 分類於 HTML Email

麻煩的outlook電子郵件網頁

繼上一篇文章後續還是踩到了一些雷,再來紀錄一下。

line-height

上篇文章有提到這個屬性還被大多數瀏覽器和信箱支持,但在用程式開啟的outlook裡面它不是不支持,而是如果寫在<table>這個tag裡的話他不支持(囧)。

也就是說瀏覽器打開的話下面例子是ok的:

1
2
3
4
5
6
<table style="line-height:20px;">
<tr>
<td>element</td>
<td>element</td>
</tr>
</table>

但在程式打開的outlook不支持寫在<table>裡所以我們要改寫成:

1
2
3
4
5
6
<table>
<tr>
<td style="line-height:10px;">element</td>
<td style="line-height:10px;">element</td>
</tr>
</table>

可不可以寫在<tr>上我還沒測試過,因為每一次測試都是要從主管那更新所以我不好意思一直測試XD,再來在同一個<tr>的tag裡面是否只需要寫一個<td>就好也不得知,總之照著個方式寫是ok的哦!

超連結<a>的文字顏色

如果想要改變點下超連結之後的顏色,也就是做到Visited的動作以前我們可以用選擇器來辦到:

1
2
3
.somelink:visited {
color: #fff;
}

但是inline style卻沒有這種寫法,我們只能在tag裡面使用!important強制讓他一直維持一種顏色:

1
<a style="text-decoration:none; color: #fff !important;" href="#">element</a>

參考這篇Stack overflow

當然在遊覽器上看都沒問題,只不過問題又出在程式上開啟的outlook….,我用線上產生的html可行(國外有網站是可以線上排版後幫你產生html)但自己做的html卻失敗,於是我直接把按鈕做成一個圖片檔放上去了。

總之最後終於把html email告一段落了~

HTML Email(電子郵件內網頁)

發表於 2017-03-20 更新於 2019-08-20 分類於 HTML Email

HTML Email

這陣子第一次碰到要做一個可以當Email發送的HTML檔案,感覺有中文解說的網站不多(也許是我關鍵字下得不好),總之如果打HTML Email是可以找尋到國外不少資源,再來介紹我當中遇到的每個地雷。

完全使用inline style控制style

第一次遇到這個工作時我天真的以為不就跟平常瀏覽器用的HTML一樣把HTML和CSS做分離,設計師還出圖的很簡單應該一下做完了。

沒錯是一下就做完了,但是完全不能使用!!!

因為在每個個大郵件他們都有自己的CSS,所以會把你傳送檔案裡有CSS的屬性大多都會擋掉,所以要考慮各大瀏覽器的相容度之外,每個郵件的相容度是不一樣的(gmail, outlook打開的效果不一樣),所以要回歸最原始最基本的做法:

1
<div style="width: 100px;height: 100px;border: 1px solid black;"></div>

以上就是inline style的寫法,記得完全避諱使用class,雖然網路上有些人似乎有成功使用選擇器去input(就是寫class的做法),但我自己試過幾個是失敗的。

盡量完全使用table

為什麼要用table呢?因為在email中很多的CSS屬性是不相容的,像是position, float等竟然不能使用啊!變成說我們的切版只能實實在在地用table硬刻出來了,雖然我們的padding, margin在大部分的郵件還是有效的,但如果是要寄給outlook的郵件就不建議使用了!待會會解釋。

特殊的形狀一律使用圖片取代

什麼意思呢?
因為我們的border-radius, rotate等等也都不太能使用了,所以有什麼特殊的圖形盡量上傳到網路上用<img src="#">這個tag去實現吧!

重新認識基本的table屬性

雖然table可以稍微切版,形狀可以直接使用圖片,但平常我們要把東西調精準的話table一定不夠啊!一定要搭配margin和padding甚至position等等,為什麼不能使用呢?

剛剛提過position是完全不用考慮了,但如果要寄給outlook的話margin和padding也是不建議的哦!那怎麼辦?我們還有原始的table屬性可以使用!

  • cellpadding
  • cellspacing
  • border
  • line-height
  • align
  • valign
  • colspan
    這幾個原生屬性要好好利用哦,可以把內文位置再加以調整的工具不多了啊!
    所以說HTML Email的版面也不要太複雜了

大部分前四個屬性我都會直接灌在table上面了

1
2
<table style="width: 100%;font-size:14px;line-height:30px;" cellpadding="0" cellspacing="0" border="0">
</table>

再搭配chrome的開發者工具就很好先做初始調整了。

非瀏覽器開啟的outlook不吃<div>這個tag

非瀏覽器開啟的outlook不吃<div>這個tag
非瀏覽器開啟的outlook不吃<div>這個tag
非瀏覽器開啟的outlook不吃<div>這個tag
這個太哭夭了我要講三遍,如果有在用公司郵件的大多都會接觸到這個工具,就是outlook不一定在瀏覽器上開啟,他本身就有一個程式是打開郵件的,這個程式不吃<div>這個tag!!!
也就是說在<div>裡面加上的style會完全忽略!千萬要小心!

總結

所以如果要做大部份郵件、瀏覽器甚至是程式打開的outlook都正常的HTML Email,照著上面的步驟應該就不會出太大的問題摟!

至於有沒有更多的屬性可以用或更好的做法那肯定是有的,只是我就沒再多做研究下去囉!這是我第一次遇到的HTML Email功課,希望能幫大家能避開一些地雷。XD

還有續集~請點我看文章。

3/22補充:感謝FB上Front-End Developers Taiwan社團有人分享的HTML Email適應表網站

[Angular-1]ng-class問題紀錄1

發表於 2017-03-20 更新於 2019-08-21 分類於 Angular , Angular1

ng-class
這次我遇到的情況是想再controller控制一個變數,讓ng-class去判斷這個變數的內容改變他的CSS,但是是用Jquery的Listener去觸發。

先參考一些我在網路上查到的用法:
Angular官方網站
Day22- 入門AngularJS筆記-AngularJS指令(19) ng-class

第一件事情是我想說ng-class如果成立的話能否直接蓋掉原本本的class:
設定html

1
2
3
4
5
6
7
<table>
<tr>
<td class="inputTd" ng-class="{'InputTooShort': tableInputTooShort}">
<input id="userInput" model="tableInput" />
<td>
</tr>
</table>

設定JS

1
2
3
4
5
6
7
8
$scope.tableInputTooShort = false;
$('#userInput').bind('focusout', function ($scope) {
if(tableInput.length < 3) {
$scope.tableInputTooShort = true;
}else {
$scope.tableInputTooShort = true;
}
});

設定CSS

1
2
3
4
5
6
.inputTd {
border: 1px solid #999;
}
.InputTooShort {
border: 2px solid red !important;
}

此時出現很神奇的Bug,每當我輸入的字串小於三個字元並且滑鼠點出input去觸發他的focusout,$scope.tableInputTooShort這個變數會變成true沒錯,但是這個tag的class並沒有更新,反而是我再點入input輸入格隨意輸入換刪除一個字元他的class才會更新為InputTooShort這個CSS,反之,當他被InputTooShort這個CSS更新後我把字元輸入到三個以上後點出input讓focusout把$scope.tableInputTooShort這個變數會變成false時class依然沒有更新,也是要再我重新點回input刪除或輸入任意字元才會更新為inputTd,但這不是我要的效果,我希望的是觸發focusout之後,的CSS就應該要更新了。

起初以為是判斷式的關係,但我試了很多判斷式還是都一樣,目前功力太淺也還找不出原因,只好再直接求助Angular的驗證式:
設定html

1
2
3
4
5
6
7
8
9
<table ng-form="form">
<tr>
<td class="inputTd" ng-class="form.pathDepartAddr$error.minlength ? 'InputTooShort' : 'inputTd'">
<input id="userInput" model="tableInput"
name="pathDepartAddr"
ng-minlength="3" />
<td>
</tr>
</table>

其實這樣就直接也省下JS的程式碼了,雖然是成功有效果但我最初的希望會是點出格子外後才觸發更新CSS,但如果使用這個方法的話會比較像onchange一樣的效果,只要輸入或刪除任意字元就會一直觸發和刷新這個CSS。

form.pathDepartAddr$error.minlength可以參考我之前文章的解釋,值得注意的是雖然在input裡面我是寫ng-minlength=”3”,但是在ng-class裡面只有寫minlength不用加上ng-這串。

[JavaScript]淺談this

發表於 2017-01-23 更新於 2020-05-25 分類於 JavaScript

這幾天從研究apply和call之類的函示,突然發現JavaScript的觀念差得可以,建構子、this等等方法十分陌生,這些東西在我工作其實使用的場合真的很少,加上現在框架和語法糖的發展讓很多事情語意化的很理所當然,但我認為站在前端的場合上面還是要多懂得一些JavaScript的精神和觀念。

這篇主要討論基本的this,建議可以先了解我前一篇的文章初探建構子,雖然不懂也沒關係,但他們確實是息息相關。

this指向於調用該函式之物件

這個經常看到卻又很模糊的東西是什麼呢?
有的人說是執行『此次』時的屬性,有人說他像免洗餐具每次都會像是重新使用,第二次使用的人會是拿到一副新碗筷跟上次使用的人是完全不一樣的東西,網路上我有找到一篇解釋得蠻好的文章。

他解釋為:this指向於調用該函式之物件。

簡單的公式就是物件.函式(),此函式裡有我們自創的this。
使用以上公式觀察下面例子:

1
2
3
4
5
6
7
8
9
10
11
var singer = {
words: '摩擦!摩擦!',
say: function(){ console.log(this.words); }
};
singer.say(); //"摩擦!摩擦!"

var singer = {
words: '似魔鬼的步伐',
say: function(){ console.log(this.words); }
};
singer.say(); //"似魔鬼的步伐"

所以函示接在哪個物件的後面this就是指向該物件的內容囉!!

這邊菜鳥提醒一下this一定是在『方法』裡面,我之前實在對類別和方法的用法感到很困惑,沒想到還是工作兩個月後才有顯著的理解XD,詳情可以參考上一篇初探建構子。

再來當函式前面沒有接物件的話,this會指向全域物件。
像這樣子獨立出現:函式。

1
2
3
4
5
var words = '原來你是我最想留住的幸運';
var sing = function () {
console.log(this.words);
}
sing(); //'原來你是我最想留住的幸運'

當sing()這個函式前面沒有接著物件的話程式會判斷是接取最外面的東西。

接下來比較常見的小問題

1
2
3
4
5
6
7
8
9
10
11
12
var words = '你存在我深深的腦海裡';
var obj = {
words: '我心裡有針要喊煞嘸聲',
sing: function(){
console.log(this.words);
var sing = function(){
console.log(this.words);
}
sing(); //'你存在我深深的腦海裡'
}
};
obj.sing(); //'我心裡有針要喊煞嘸聲'

主要都是看接什麼物件而唱出什麼歌詞,那有一個有趣的玩法可以讓this保留下來。

延續上面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var words = '你存在我深深的腦海裡';
var obj = {
words: '我心裡有針要喊煞嘸聲',
sing: function(){
console.log(this.words);
var that = this; //我把這個this存到變數that裡面了!
console.log(that); //出現完整的obj物件
var sing = function(){
console.log(that.words); //這裡的that帶著
}
sing(); //'我心裡有針要喊煞嘸聲'
}
};
obj.sing(); //'我心裡有針要喊煞嘸聲'

JavaScript有個有趣的小地方是存到變數that的那行程式碼裡的this,會是指向本身物件的this唷!
所以再來我使用它的時候他會是指向obj這個物件的。
下面的那行console.log也可以顯示出這個this是指哪個物件。

參考文章:#Javascript:this用法整理
我只是用比較有趣的例子敘述XD。

[JavaScript]初探建構子(Constructor)

發表於 2017-01-19 更新於 2019-08-20 分類於 JavaScript

學JS這麼久了一直對建構子的觀念很模糊,剛好前陣子尋找技術文章又有提到,自己再來深入了解終於比較理解了,網路上很許多非常好的解釋,但為了防範老人痴呆自己也想來下手寫一篇分享。

MDN的介紹就已經非常不錯,趕時間的直接參考這篇吧XD。

在原生的JS世界,我們經常創造很多物件,即使是超級簡單的:

1
2
3
4
5
6
var Person = {
name: 'Kurt',
age: 18,
skill: 'Keep cool'
}
console.log(Person); //print出Person這個東西骨子裡到底裝了些什麼

這樣我定義了一個Person名叫Kurt有年齡和一個可以裝酷的技能,但是我想做二十個人組成一個棒球隊,我就必須宣告二十次這種物件,那有沒有更好的方法呢?

我們請小叮噹幫我們做出一個人類製造機吧!!

1
2
3
4
5
6
7
8
function makePerson (name) {
console.log(name + '出生惹!');
}

var Kurt = new makePerson ('Kurt'); //Kurt出生惹!
var Maggie = new makePerson ('Maggie'); //Maggie出生惹!
console.log(Kurt); //Object {}
console.log(Maggie); //Object {}

我做了一個人類製造機(function)叫makePerson,這個就是大家所謂的『類別』,他可以拿來製造真實的人類(先不要討論Kurt也可以是一隻狗的名字,這樣我會很困擾)。
但是!!這個人類製造機(function)並不是一個實體的人類(物件)唷!!有注意到我在使用這個人類製造機的時候前面加了new嗎?這時候的Kurt才是一個真正的人類(物件),你才可以對他做修改,賦予他彩色或是黑白的人生,因為到目前為止他是一個什麼都沒有的人類(全空的物件),最後兩行console後print出來的結果是Object {}。

好,身為一個良好的棒球隊要年齡適中,各有各的特長使之各司其職,所以我們要來給我們製造出來的人類(物件)一些特長了(屬性)。

我們針對Kurt延續程式碼:

1
2
3
4
5
6
7
8
9
function makePerson (name) {
console.log(name + '出生惹!');
}

var Player1 = new makePerson ('Player1'); //Kurt出生惹!
Kurt.name = 'Kurt';
Kurt.age = 18;
Kurt.skill = 'keep cool';
console.log(Player1); //Object {age: 18, name: "Kurt", skill: "keep cool"}

這邊可以看到我先製造Player1的人類(物件),我後天訓練讓大家要叫他Kurt(name),給了他現在很適合打棒球的18歲年齡(age),還有讓他在球場上一直保持冷靜的技能(skill),剛剛後天訓練的東西我們稱之為『屬性』。

可是這邊有個問題,慣老闆不會喜歡我們花這麼多力氣去後天訓練這些球員(每個物件都要一個一個去定義是很麻煩的事情),我們希望他一加入棒球隊就是個適合打棒球的人,那最棒的事情就是他打從娘胎出來就會打棒球了,沒錯,慣老闆就是這麼任性。

所以我們要改良人類製造機,讓一出廠的人類就有他的名字,年齡和技能,於是乎….:

1
2
3
4
5
6
7
8
function makePerson (name, age, skill) {
this.name = name;
this.age = age;
this.skill = skill;
}

var Player1 = new makePerson ('Kurt', 18, 'Keep cool');
console.log(Player1); //Object {age: 18, name: "Kurt", skill: "keep cool"}

新型的人類製造機如上,只要我們製造(new)人類(物件)的時候把後面的參數填正確位置,一出生的人類馬上就可以上場打棒球囉!

好,現在你可以先製造個二十位未成年少女組成一個棒球隊了?

言歸正傳,慣老闆覺得這樣可以直接製作適合打棒球的人還不夠有競爭力,所以他希望從第一棒到第九棒,救援投手到候補球員,甚至是打掃棒球茶水間的大嬸都有擊出全壘打的能力,畢竟還沒做到這一步之前球隊都是有進步空間的,阿只要球隊還有進步空間在慣老闆的眼裡都是一隻還不夠有競爭力的球隊,所以我們要想個『方法』。

再延續之前的程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function makePerson (name, age, skill) {
this.name = name;
this.age = age;
this.skill = skill;
}

makePerson.prototype.yesBoss = function() {
console.log('擊出全壘打,得分!');
};

var Player1 = new makePerson ('Kurt', 18, 'Keep cool');
Player1.yesBoss(); //擊出全壘打,得分!
console.log(Player1);
/*Object {
age: 18,
name: "Kurt",
skill: "Keep cool",
yesBoss: function () {
console.log('擊出全壘打\uFF0C得分\uFF01');
}
}*/

撰寫新的程式碼,在人類製造機(類別)後面加上.prototype就可以打造製造機專屬的『方法』,方法的名稱也是自己定義的,在這邊我取名為yesBoss(是的老闆)。

只要以後由這個人類製造機製造出來的人類使用這個方法就可以打出全壘打了,但一定要是此製造機(類別)製造出來的人類(物件)唷!

接下來只要慣老闆不斷的使用yesBoss就可以讓自己旗下的未成年少女和茶水間大嬸得分到對手不要不要的,每場屌打對手二十幾分,金錢,名聲,地位和權利全部都接收,那這些肯定都是慣老闆的功勞啊!!

[Angular-1]ng-key鍵盤事件

發表於 2016-12-19 更新於 2019-08-20 分類於 Angular , Angular1

今天想要做一個按下Enter就可以執行Submit的事件,最常見到的地方就是登入的時候,我們帥氣快速的打完帳號密碼一定會Combo接Enter鍵登入吧!其實這是JS的事件唷!

沒想到這麼簡單的東西我會卡了四個小時,滿滿的大心得記錄一下吧XD。

原生Javascript的onkey事件

JS的原生事件有三種:
onkeyup:釋放鍵盤觸發
onkeydown:按下鍵盤觸發
onkeypress:按下鍵盤後釋放觸發

我並沒有很深入研究使用情況,我在想onkeydown和onkeypress使用場合在一次要按多顆鍵(onkeydown)或者是單顆鍵(onkeypress),今天主要用登入表單的例子示範最基本的實作就好。

index.html
1
2
3
4
5
<form action="#" method="post">
請輸入帳號<input type="text" name="username" onkeypress="goLogin(evt);">
請輸入密碼<input type="text" name="password" onkeypress="goLogin(evt);">
<input type="submit" value="登入">
</form>

以上就是最簡單的登入表格囉,並且我直接在input裡面加入inline function,也就是說當使用者游標正在那兩個input裡面的時候只要按下鍵盤再放開會一直不斷執行goLogin()這個function,然後千萬不要忘記要給他一個變數讓等等的JS去判斷我們按下什麼鍵。

app.js
1
2
3
4
5
function (evt) {
if (evt.keyCode == 13) {
dosomething...
}
};

JS的function裡面要給他一個變數讓外部的直帶進去,而keyCode則是用onkeypress產生出來的東西的原生屬性,Enter鍵的這個值會是13,鍵盤對應表在網路上有很多資源,例如這篇。

onkeypress當然也可以從外部呼叫,例如我在JS做一個事件:

app.js
1
2
3
4
var userinput = document.GetElementById("username");
userinput.onkeypress = function (evt) {
dosomething...
};

AngularJs的onkey事件

AngularJs的方法其實大同小異,只是官網寫的三種教學竟然不一致讓我少看最重要的那一篇,他把我最想知道的用法寫在ng-keyup而已太扯了。

總之剛剛上面原生講的三種事件換寫為下面三種:
onkeyup=ng-keyup
onkeydown=ng-keydown
onkeypress=ng-keypress

再來直接用剛剛基本的登入頁面做示範:

index.html
1
2
3
4
5
<form>
請輸入帳號<input type="text" ng-model="count.username" onkeypress="goLogin($event);">
請輸入密碼<input type="text" ng-model="count.password" onkeypress="goLogin($event);">
<input type="submit" value="登入">
</form>

而JS裡面則差不多一樣

app.js
1
2
3
4
5
$scope.goLogin = function (keyValue) {
if (keyValue.keyCode == 13) {
dosomething...
}
};

Angular的ng-model方便之處在這邊就不多談,最重要要注意的是goLogin(\$event)我裡面待的變數是Angular原生的$event唷!!!!!!!!!

總之他們兩個一定要搭配就是了,而鍵盤的直也一樣用keyCode就叫得出來囉!

雖然這其實有人帶的話簡單的要命,但有時候真的鬼打牆卡住就真的是卡很久XD,今天真的是有撞牆到啦,但搞定就是很開心!

1…131415…18

Kurt Hsu

Progress One Percent Every Day
171 文章
55 分類
163 標籤
RSS
© 2020 Kurt Hsu
由 Hexo 強力驅動 v3.8.0
|
主題 – NexT.Muse v7.3.0