JavaWeb-前端基礎

前端基礎

  • 前端:我們網站的頁面,包括網站的樣式、圖片、影片等一切用戶可見的內容都是前端的內容。
  • 後端:處理網站的所有數據來源,比如我們之前從資料庫中查詢數據,而我們查詢的數據經過處理最終會被展示到前端,而用於處理前端數據的工作就是由後端來完成的。

相當於,前端僅僅是一層皮,它直接決定了整個網站的美觀程度,我們可以自由地編排頁面的布局,甚至可以編寫好看的特效;而靈魂則是後端,如何處理用戶的交互、如何處理數據查詢是後端的職責所在,我們前面學習的都是後端內容,而Java也是一門專註於後端開發的語言。

對於前端開發我們需要學習一些新的內容,只有了解了它們,我們才能編寫出美觀的頁面。

學習前端的目的只是為了讓同學們了解前後端的交互方式,在進行後端開發時思路能夠更加清晰,有關前端的完整內容學習,可以瀏覽其他前端知識教程。

我們在最開始講解網路編程時,提到了瀏覽器訪問伺服器,實際上瀏覽器訪問伺服器就是一種B/S結構( Browser/Server,瀏覽器/伺服器模式 ),而我們使用Java程式碼編寫的客戶端連接伺服器就是一種C/S結構( Client/Server架構,即客戶端/伺服器架構 )。

HTML頁面

我們前面學習了XML語言,它是一種標記語言,我們需要以成對標籤的格式進行填寫,但是它是專用於保存數據,而不是展示數據,而HTML恰恰相反,它專用於展示數據,由於我們前面已經學習過XML語言了,HTML語言和XML很相似,所以我們學習起來會很快。

第一個HTML頁面

我們前面知道,通過瀏覽器可以直接瀏覽XML文件,而瀏覽器一般是用於瀏覽HTML文件的,以HTML語言編寫的內容,會被瀏覽器識別為一個頁面,並根據我們編寫的內容,將對應的組件添加到瀏覽器窗口中。

我們一般使用Chrome、Safari、Microsoft Edge等瀏覽器進行測試,IE瀏覽器已經徹底淘汰了!

比如我們可以創建一個Html文件來看看瀏覽器會如何識別,使用IDEA也能編寫HTML頁面,我們在IDEA中新建一個Web模組,進入之後我們發現,項目中沒有任何內容,我們右鍵新建一個HTML文件,選擇HTML5文件,並命名為index,創建後出現:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

</body>
</html>

我們發現,它和XML基本長得一樣,並且還自帶了一些標籤,那麼現在我們通過瀏覽器來瀏覽這個HTML文件(這裡推薦使用內置預覽,不然還得來回切換窗口)

我們發現現在什麼東西都沒有,但是在瀏覽器的標籤位置顯示了網頁的名稱為Title,並且顯示了一個IDEA的圖標作為網頁圖標。

現在我們稍微進行一些修改:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>lbw的直播間</title>
</head>
<body>
    現在全體起立
</body>
</html>

再次打開瀏覽器,我們發現頁面中出現了我們輸入的文本內容,並且標題也改為了我們自定義的標題。

我們可以在設置->工具->Web瀏覽器和預覽中將重新載入頁面規則改為變更時,這樣我們使用內置瀏覽器或是外部瀏覽器,可以自動更新我們編寫的內容。

我們還可以在頁面中添加一個圖片,隨便將一張圖片放到html文件的同級目錄下,命名為image.xxx,其中xxx是後綴名稱,不要修改,我們在body節點中添加以下內容:

<img width="300" src="image.xxx" alt="劍光如我,斬盡牛雜">
<!--  注意xxx替換成對應的後綴名稱  -->

我們發現,我們的頁面中居然能夠顯示我們添加的圖片內容。因此,我們只需要編寫對應的標籤,瀏覽器就能夠自動識別為對應的組件,並將其展示到我們的瀏覽器窗口中。

我們再來看看插入一個B站的影片,很簡單,只需要到對應的影片下方,找到分享,我們看到有一個嵌入程式碼:

<iframe src="//player.bilibili.com/player.html?aid=333231998&bvid=BV1rA411g7q8&cid=346917516&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true" width="800" height="500"> </iframe>

每一個頁面都是通過這些標籤來編寫的,幾乎所有的網站都是使用HTML編寫頁面。

HTML語法規範

一個HTML文件中一般分為兩個部分:

  • 頭部:一般包含頁面的標題、頁面的圖標、還有頁面的一些設置,也可以在這裡導入css、js等內容。
  • 主體:整個頁面所有需要顯示的內容全部在主體編寫。

我們首先來看頭部,我們之前使用的HTML文件中頭部包含了這些內容:

<meta charset="UTF-8">
<title>lbw的直播間</title>

首先meta標籤用於定義頁面的一些元資訊,這裡使用它來定義了一個字符集(編碼格式),一般是UTF-8,下面的title標籤就是頁面的標題,會顯示在瀏覽器的上方。我們現在來給頁面設置一個圖標,圖標一般可以在字節跳動的IconPark網站找到://iconpark.oceanengine.com/home,選擇一個自己喜歡的圖標下載即可。

將圖標放入到項目目錄中,並命名為icon.png,在HTML頭部添加以下內容:

<link rel="icon" href="icon.png" type="image/x-icon" />

link標籤用於關聯當前HTML頁面與其他資源的關係,關係通過rel屬性指定,這裡使用的是icon表示這個文件是當前頁面圖標。

現在訪問此頁面,我們發現頁面的圖標已經變成我們指定的圖標樣式了。

現在我們再來看主體,我們可以在主體內部編寫該頁面要展示的所有內容,比如我們之前就用到了img標籤來展示一個圖片,其中每一個標籤都稱為一個元素:

<img width="300" src="image.xxx" alt="當圖片載入失敗時,顯示的文本">

我們發現,這個標籤只存在一個,並沒有成對出現,HTML中有些標籤是單標籤,也就是說只有這一個,還有一些標籤是雙標籤,必須成對出現,HTML中,也不允許交叉嵌套,但是出現交叉嵌套時,瀏覽器並不會提示錯誤,而是仍舊嘗試去解析這些內容,甚至會幫助我們進行一定程度的修復,比如:

<body>

    <iframe src="//player.bilibili.com/player.html?aid=333231998&bvid=BV1rA411g7q8&cid=346917516&page=1" width="800" height="500"
            scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true">
</body>
</iframe>

很明顯上面的程式碼已經出現交叉嵌套的情況了,但是依然能夠在瀏覽器中正確地顯示。

在主體中,我們一般使用div標籤來分割頁面:

<body>
    <div>我是第一塊</div>
    <div>我是第二塊</div>
</body>

通過使用div標籤,我們將整個頁面按行劃分,而高度就是內部元素的高度,那麼如果只希望按元素劃分,也就是說元素佔多大就劃分多大的空間,那麼我們就可以使用span標籤來劃分:

<body>
    <div>
        <span>我是第一塊第一個部分</span>
        <span>我是第一塊第二個部分</span>
    </div>
    <div>我是第二塊</div>
</body>

我們也可以使用p段落標籤,它一般用於文章分段:

<body>
    <p>
        你看這個彬彬啊,才喝幾罐就醉了,真的太遜了。 這個彬彬就是遜呀!
        聽你這麼說,你很勇哦? 開玩笑,我超勇的,超會喝的啦。
        超會喝,很勇嘛。身材不錯哦,蠻結實的嘛。
    </p>
    <p>
        哎,傑哥,你幹嘛啊。都幾歲了,還那麼害羞!我看你,完全是不懂哦!
        懂,懂什麼啊? 你想懂?我房裡有一些好康的。
        好康,是新遊戲哦! 什麼新遊戲,比遊戲還刺激!
    </p>
    <p>
        傑哥,這是什麼啊? 哎呦,你臉紅啦!來,讓我看看。
        不要啦!! 讓我看看嘛。 不要啦,傑哥,你幹嘛啊!
        讓我看看你法語正不正常啊!
    </p>
</body>

那麼如果遇到特殊字元該怎麼辦呢?和XML一樣,我們可以使用轉義字元:

點擊查看源網頁

注意:多個連續的空格字元只能被識別為一個,如果需要連續多個必須使用轉義字元,同時也不會識別換行,換行只會變成一個空格,需要換行必須使用br標籤。

通過了解了HTML的一些基礎語法,我們現在就知道一個頁面大致是如何編寫了。

HTML常用標籤

前面我們已經了解了HTML的基本語法規範,那麼現在我們就來看看,有哪些常用的標籤吧,首先是換行和分割線:

  • br 換行
  • hr 分割線
<body>
    <div>
        我是一段文字<br>我是第二段文字
    </div>
    <hr>
    <div>我是底部文字</div>
</body>

標題一般用h1到h6表示,我們來看看效果:

<body>
<h1>一級標題</h1>
<h2>二級標題</h2>
<h3>三級標題</h3>
<h4>四級標題</h4>
<h5>五級標題</h5>
<h6>六級標題</h6>
<p>我是正文內容,真不錯。</p>
</body>

現在我們來看看超鏈接,我們可以添加一個鏈接用於指向其他網站:

<a href="//www.bilibili.com">點擊訪問小破站</a>

我們也可以指定頁面上的一個錨點進行滾動:

<body>
<a href="#test">跳轉錨點</a>
<img src="image.jpeg" width="500">
<img src="image.jpeg" width="500">
<img src="image.jpeg" width="500">
<img src="image.jpeg" width="500">
<div id="test">我是錨點</div>
<img src="image.jpeg" width="500">
<img src="image.jpeg" width="500">
<img src="image.jpeg" width="500">
</body>

每個元素都可以有一個id屬性,我們只需要給元素添加一個id屬性,就使用a標籤可以跳轉到一個指定錨點。

我們接著來看看列表元素,這是一個無需列表,其中每一個li表示一個列表項:

<ul>
    <li>一號選項</li>
    <li>二號選項</li>
    <li>三號選項</li>
    <li>四號選項</li>
    <li>五號選項</li>
</ul>

我們也可以使用ol來顯示一個有序列表:

<ol>
    <li>一號選項</li>
    <li>二號選項</li>
    <li>三號選項</li>
    <li>四號選項</li>
    <li>五號選項</li>
</ol>

表格也是很重要的一種元素,但是它編寫起來相對有一點麻煩:

<table>
    <thead>
    <tr>
        <th>學號</th>
        <th>姓名</th>
        <th>性別</th>
        <th>年級</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>0001</td>
        <td>小明</td>
        <td>男</td>
        <td>2019</td>
    </tr>
    <tr>
        <td>0002</td>
        <td>小紅</td>
        <td>女</td>
        <td>2020</td>
    </tr>
    </tbody>
</table>

雖然這樣生成了一個表格,但是這個表格並沒有分割線,並且格式也不符合我們想要的樣式,那麼如何才能修改這些基礎屬性的樣式呢,我們就需要聊聊CSS了。

HTML表單

表單就像其名字一樣,用戶在頁面中填寫了對應的內容,點擊按鈕就可以提交到後台,比如登陸介面,就可以使用表單來實現:

一個網頁中最重要的當屬輸入框和按鈕了,那麼我們來看看如何創建一個輸入框和按鈕:

<label>
    我是輸入框
    <input type="text">
</label>

對於一個輸入框,我們一般會將其包括在一個lable標籤中,它和span效果一樣,但是我們點擊前面文字也能快速獲取輸入框焦點。

<body>
<div>登陸我們的網站</div>
<hr>
<div>
    <label>
        帳號:
        <input type="text">
    </label>
</div>
<div>
    <label>
        密碼:
        <input type="password">
    </label>
</div>
</body>

輸入框可以有很多類型,我們來試試看password,現在輸入內容就不會直接展示原文了。

創建一個按鈕有以下幾種方式,在學習JavaWeb時,我們更推薦第二種方式,我們後面進行登陸操作需要配合表單使用:

<button>登陸</button>
<input type="submit" value="登陸">
<input type="button" value="登陸">

現在我們就可以寫一個大致的登陸頁面了:

<body>
    <h1>登陸我們的網站</h1>
    <form>
        <div>
            <label>
                帳號:
                <input type="text" placeholder="Username...">
            </label>
        </div>
        <div>
            <label>
                密碼:
                <input type="password" placeholder="Password...">
            </label>
        </div>
        <br>
        <a href="//www.baidu.com">忘記密碼</a>
        <br>
        <br>
        <div>
            <input type="submit" value="登陸">
        </div>
    </form>
</body>

表單一般使用form標籤將其囊括,但是現在我們還用不到表單提交,因此之後我們再來講解表單的提交。

input只能實現單行文本,那麼如何實現多行文本呢?

<label>
    這是我們的文本框<br>
    <textarea placeholder="文本內容..." cols="10" rows="10"></textarea>
</label>

我們還可以指定默認的行數和列數,拖動左下角可以自定義文本框的大小。

我們還可以在頁面中添加勾選框:

<label>
    <input type="checkbox">
    我同意本網站的隱私政策
</label>

上面演示的是一個多選框,那麼我們來看看單選框:

<label>
    <input type="radio" name="role">
    學生
</label>
<label>
    <input type="radio" name="role">
    教師
</label>

這裡需要使用name屬性進行分組,同一個組內的選項只能選擇一個。

我們也可以添加列表讓用戶進行選擇,創建一個下拉列表:

<label>
    登陸身份:
    <select>
        <option>學生</option>
        <option>教師</option>
    </select>
</label>

默認選取的是第一個選項,我們可以通過selected屬性來決定默認使用的是哪個選項。

當然,HTML的元素遠不止我們所提到的這些,有關更多HTML元素的內容,可以自行了解。


CSS樣式

之前我們編寫的頁面非常基礎,我們只能通過一些很基本的屬性來排列我們的頁面元素,那麼如何實現更高度的自定義呢,我們就需要用到CSS來自定義樣式,首先我們創建一個名為style.css的文件。

首先在我們HTML文件的頭部添加:

<link href="style.css" rel="stylesheet">

我們在CSS文件中添加以下內容:

body {
    text-align: center;
}

我們發現,網頁的內容全部變為居中顯示了,這正是css在生效,相當於我們現在給頁面添加了自定義的樣式規則。

當然,我們也可以選擇不使用CSS,而是直接對某個元素添加樣式:

<body style="text-align: center;">
  ...

這樣的效果其實是等同於上面的css文件的,相當於我們直接把樣式定義在指定元素上。

也可以在頭部直接定義樣式,而不是使用外部文件:

<style>
    body {
        text-align: center;
    }
</style>

使用以上三種方式都可以自定義頁面的樣式,我們推薦使用還是第一種,不然我們的程式碼會很繁雜。

樣式的屬性是非常多的,我們不可能一個一個全部講完,影片中用到什麼再來講解什麼,如果同學們感興趣,可以自行下去了解。

CSS選擇器

我們首先來了解一下選擇器,那麼什麼是選擇器呢?我們想要自定義一個元素的樣式,那麼我們肯定要去選擇某個元素,只有先找到要自定義的元素,我們才能開始編寫樣式。

我們上面的例子中使用的就是標籤名選擇器,它可以快速選擇頁面中所有指定的的標籤,比如我們之前使用的就是body標籤,那麼就相當於頁面中所有的body元素全都使用此樣式,那麼我們現在來試試看選擇頁面中所有的input標籤:

input {
    width: 200px;
}

我們發現,頁面中所有的input元素寬度全部被設定為了200個像素(px是單位大小,代表像素,除了px還有emrem,他們是根據當前元素字體大小決定的相對大小,一般用於適配各種大小的瀏覽器窗口,這裡暫時不用)

樣式編寫完成後,如果只有一個屬性,可以不帶;若多個屬性則每個屬性後面都需要添加一個;

因此,一個標籤選擇器的格式為:

標籤名稱 {
  屬性名稱: 屬性值
}

我們還可以設定輸入框的字體大小、行高等:

input {
    width: 200px;
    font-size: 20px;
    line-height: 40px;
}

我們現在可以通過選擇器快速地去設置某個元素樣式了,那麼如何實現只設置某個元素的樣式呢,現在我們來看看,id選擇器,我們之前已經講解過了,每個元素都可以有一個id屬性,我們可以將其當做一個跳轉的錨點使用,而現在,我們可以使用css來進行定位:

我們先為元素添加id屬性:

<h1 id="title">登陸我們的網站</h1>

現在使用CSS選擇我們的元素,並設定一個屬性,選擇某個id需要在前面加上一個#

#title {
    color: red;
}

雖然id選擇器已經可以很方便的指定某個元素,但是如果我們希望n個但不是元素都被選擇,id選擇器就無法實現了,因為每個元素的id是唯一的,不允許出現重複id的元素,因此接著我們來講解一下類選擇器。

每個元素都可以有一個class屬性,表示當前元素屬於某個類(注意這裡的類和我們Java中的類概念完全不同)一個元素可以屬於很多個類,一個類也可以被很多個元素使用:

<form>
    <div >
        <label class="test">
            帳號:
            <input type="text" placeholder="Username...">
        </label>
    </div>
    <div>
        <label class="test">
            密碼:
            <input type="password" placeholder="Password...">
        </label>
    </div>
</form>

上面的例子中,兩個label元素都使用了test類(類名稱是我們自定義的),現在我們在css文件中編寫以下內容來以類進行選擇:

.test{
    color: blue;
}

我們發現,兩個標籤的文本內容都變為了藍色,因此使用類選擇器,能夠對所有為此類的元素添加樣式。注意在進行類選擇時,我們需要在類名前面加上.來表示。

組合選擇器和優先順序問題

我們也可以讓多個選擇器,共用一個css樣式:

.test, #title {
    color: red;
}

只需要並排寫即可,注意中間需要添加一個英文的逗號用於分割,我們也可以使用*來一次性選擇所有的元素:

* {
    color: red;
}

我們還可以選擇位於某個元素內的某個元素:

div label {
    color: red;
}

這樣的話,就會選擇所有位於div元素中的label元素。

當然,我們這裡只介紹了一些常用的選擇器,有關詳細的CSS選擇器可以查閱://www.runoob.com/cssref/css-selectors.html

我們接著來看一下選擇器的優先順序:

img

我們根據上面的資訊,來測試一下,首先編寫一下HTML文件:

<body>
    <div class="test" id="simple" style="color: blue">我是測試文本內容</div>
</body>

現在我們來編寫一下css文件:

.test {
    color: yellow;
}

#simple {
    color: red;
}

* {
    color: palegreen;
}

那麼現在我們可以看到,實際上生效的是我們直接編寫在標籤內部的內聯屬性,那麼現在我們依次進行移除,來看看它們的優先順序。

那麼如果我們希望某個屬性無視任何的優先順序,我們可以在屬性後面添加!important標記,表示此屬性是一個重要屬性,它的優先順序會被置為最高。

思考:那要是我每個選擇器的這個屬性後面都加一個!important會怎麼樣?

自定義邊距

我們來看看,如何使用css控制一個div板塊的樣式,首先編寫以下程式碼,相當於一個div嵌套了一個div元素:

<div id="outer">
    <div id="inner">
        
    </div>
</div>

現在編寫一下自定義的css樣式,我們將div設定為固定大小,並且背景顏色添加為綠色:

#outer {
    background: palegreen;
    width: 300px;
    height: 300px;
}

我們發現左側快速預覽頁面存在空隙,這是因為瀏覽器給我們添加了一個邊距屬性,我們只需要覆蓋此屬性並將其設定為0即可:

body {
    margin: 0;
}

現在我們給內部嵌套的div也設定一個大小,並將顏色設定為橙色:

#inner {
    background: darkorange;
    width: 100px;
    height: 100px;
}

現在我們發現內部的div元素位於右上角,我們還可以以百分比的形式來指定大小:

#inner {
    background: darkorange;
    width: 100%;
    height: 100%;
}

百分比會依照當前可用大小來進行分配,比如當前位於一個div內部,並且外部div元素是固定大小300px,因此100%就相當於使用了外部的全部大小,也是300px,現在內部元素完全將外部元素覆蓋了,整個元素現在呈現為橙色。

我們可以為一個元素設定邊距,邊距分為外邊距和內邊距,外部元素內邊距決定了內部元素與外部元素之間的間隔,我們來修改一下css樣式:

#outer {
    background: palegreen;
    width: 300px;
    height: 300px;
    padding: 10px;
}

我們發現,內部的div元素小了一圈,這是因為外部div元素設定了內邊距,上下左右都被設定為10px大小。

而我們發現,實際上我們在一開始也是將body的外邊距設定為了0,整個頁面跟瀏覽器窗口直接間隔0px的寬度。

編寫一個漂亮的登陸介面

現在我們就來嘗試編寫一個漂亮的登陸介面吧!


JavaScript語言

也稱為js,是我們整個前端基礎的重點內容,只有了解了JavaScript語言,我們才能了解前端如何與後端交互。

JavaScript與Java沒有毛關係,僅僅只是名字中包含了Java而已,跟Java比起來,它更像Python,它是一門解釋型語言,不需要進行編譯,它甚至可以直接在瀏覽器的命令窗口中運行。

它相當於是前端靜態頁面的一個補充,它可以讓一個普通的頁面在後台執行一些程式,比如我們點擊一個按鈕,我們可能希望執行某些操作,比如下載文件、頁面跳轉、頁面彈窗、進行登陸等,都可以使用JavaScript來幫助我們實現。

我們來看看一個簡單的JavaScript程式:

const arr = [0, 2, 1, 5, 9, 3, 4, 6, 7, 8]

for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length - 1; j++) {
        if(arr[j] > arr[j+1]){
            const tmp = arr[j]
            arr[j] = arr[j+1]
            arr[j+1] = tmp
        }
    }
}

window.alert(arr)

這段程式碼實際上就是實現了一個冒泡排序演算法,我們可以直接在頁面的頭部中引用此js文件,瀏覽器會在載入時自動執行js文件中編寫的內容:

<script src="test.js"></script>

我們發現JS的語法和Java非常相似,但是它還是和Java存在一些不同之處,而且存在很多陰間語法,那麼我們來看看JS的語法。

JavaScript基本語法

在js中,定義變數和Java中有一些不同,定義一個變數可以使用let關鍵字或是var關鍵字,IDEA推薦我們使用let關鍵字,因為var存在一定的設計缺陷(這裡就不做講解了,之後一律使用let關鍵字進行變數聲明):

let a = 10;
a++;
window.alert(a)

上面的結果中,我們得到了a的結果是11,也就是說自增和自減運算在JS中也是支援的,並且JS每一句結尾可以不用加分號。

js並不是Java那樣的強類型語言(任意變數的類型一定是明確的),它是一門弱類型語言,變數的類型並不會在一開始確定,因此我們在定義變數時無需指定變數的確切類型,而是在運行時動態解析類型:

let a = 10;
a = "HelloWorld!"
console.info(a)

我們發現,變數a已經被賦值為數字類型,但是我們依然在後續能將其賦值一個字元串,它的類型是隨時可變的。

很多人說,這種變態的類型機制是JS的一大缺陷。

世界上只有兩種語言:一種是很多人罵的,一種是沒人用的。

我們接著來看看,JS中存在的基本數據類型:

  • Number:數字類型(包括小數和整數)
  • String:字元串類型(可以使用單引號或是雙引號)
  • Boolean:布爾類型(與Java一致)

還包括一些特殊值:

  • undefined:未定義 – 變數聲明但不賦值默認為undefined

  • null:空值 – 等同於Java中的null

  • NaN:非數字 – 值不是合法數字,比如:

    window.alert(100/'xx')
    

我們可以使用typeof關鍵字來查看當前變數值的類型:

let a = 10;
console.info(typeof a)
a = 'Hello World'
console.info(typeof a)

JavaScript邏輯運算和流程式控制制

我們接著來看看js中的關係運算符,包括如下8個關係運算符:大於(>),小於(<),小於等於(<=),大於等於(>=),相等(),不等(!=),全等(=),不全等(!==)

其實關係運算符大致和Java中的使用方法一致,不過它還可以進行字元串比較,有點像C++的語法:

console.info(666 > 777)
console.info('aa' > 'ab')

那麼,相等和全等有什麼區別呢?

console.info('10' == 10)
console.info('10' === 10)

我們發現,在Java中,若運算符兩邊是不同的基本數據類型,會直接得到false,而JS中卻不像這樣,我們發現字元串的10居然等於數字10,而使用全等判斷才是我們希望的結果。

==的比較規則是:當操作數類型一樣時,比較的規則和恆等運算符一樣,都相等才相等,如果兩個操作數是字元串,則進行字元串的比較,如果裡面有一個操作數不是字元串,那兩個操作數通過Number()方法進行轉換,轉成數字進行比較。

因此,我們上面進行的判斷實際上是運算符兩邊都進行了數字轉換的結果進行比較,自然也就得到了true,而全等判斷才是我們在Java中認識的相等判斷。

我們接著來看邏輯運算,JS中包括&&、||、&、|、?:等,我們先來看看位運算符:

console.info(4 & 7)
console.info(4 | 7)

實際上和Java中是一樣的,那麼我再來看看邏輯運算:

console.info(true || false)

對於boolean變數的判斷,是與Java一致的,但是JS也可以使用非Boolen類型變數進行判斷:

console.info(!0)
console.info(!1)

和C/C++語言一樣,0代表false,非0代表true,那麼字元串呢?

console.info(!"a")
console.info(!"")

我們發現,空串為false,非空串為true,我們再來看看:

console.info(true || 7)
console.info(7 || true)

我們發現,前者得到的結果為true,而後者得到的結果卻是是7,真是滑天下之大稽,什麼鬼玩意,實際上是因為,默認非0都是true,而後者又是先判斷的7,因此會直接得到7而不是被轉換為true

那麼我們再來看看幾個特殊值默認代表什麼:

console.info(!undefined)
console.info(!null)
console.info(!NaN)

最後來使用一下三元運算符,實際上和Java中是一樣的:

let a = true ? "xx" : 20
console.info(a)

得益於JS的動態類型,emmm,三元運算符不一定需要固定的返回值類型。

JS的分支結構,實際上和Java是一樣的,也是使用if-else語句來進行:

if("lbwnb"){   //非空串為true
    console.info("!!!")
} else {
    console.info("???")
}

同理,多分支語句也能實現:

if(""){
    console.info("!!!")
} else if(-666){
    console.info("???")
} else {
    console.info("O.O")
}

當然,多分支語句也可以使用switch來完成:

let a = "a"
switch (a){
    case "a":
        console.info("1")
        break
    case "b":
        console.info("2")
        break
    case "c":
        console.info("3")
        break
    default:
        console.info("4")
}

接著我們來看看循環結構,其實循環結構也和Java相差不大:

let i = 10
while(i--){
    console.info("100")
}
for (let i = 0; i < 10; i++) {
    console.info("??")
}

JavaScript函數定義

JS中的方法和Java中的方法定義不太一樣,JS中一般稱其為函數,我們來看看定義一個函數的格式是什麼:

function f() {
    console.info("有一個人前來買瓜")
}

定義一個函數,需要在前面加上function關鍵字表示這是一個函數,後面跟上函數名稱和(),其中可以包含參數,在{}中編寫函數程式碼。我們只需要直接使用函數名+()就能調用函數:

f();

我們接著來看一下,如何給函數添加形式參數以及返回值:

function f(a) {
    console.info("得到的實參為:"+a)
    return 666
}

f("aa");

由於JS是動態類型,因此我們不必指明參數a的類型,同時也不必指明返回值的類型,一個函數可能返回不同類型的結果,因此直接編寫return語句即可。同理,我們可以在調用函數時,不傳參,那麼默認會使用undefined:

function f(a) {
    console.info("得到的實參為:"+a)
    return 666
}

f();

那麼如果我們希望不傳參的時候使用我們自定義的默認值呢?

function f(a = "6666") {
    console.info("得到的實參為:"+a)
    return 666
}

f();

我們可以直接在形參後面指定默認值。

函數本身也是一種類型,他可以被變數接收,所有函數類型的變數,也可以直接被調用:

function f(a = "6666") {
    console.info("得到的實參為:"+a)
    return 666
}

let k = f;
k();

我們也可以直接將匿名函數賦值給變數:

let f = function (str) {
    console.info("實參為:"+str)
}

既然函數是一種類型,那麼函數也能作為一個參數進行傳遞:

function f(test) {
    test();
}

f(function () {
    console.info("這是一個匿名函數")
})

對於所有的匿名函數,可以像Java的匿名介面實現一樣編寫lambda表達式:

function f(test) {
    test();
}

f(() => {
    console.info("可以,不跟你多bb")
})
function f(test) {
    test("這個是回調參數");
}

f(param => {
    console.info("接受到回調參數:"+param)
})

JavaScript數組和對象

JS中的數組定義與Java不同,它更像是Python中的列表,數組中的每個元素並不需要時同樣的類型:

let arr = [1, "lbwnb", false, undefined, NaN]

我們可以直接使用下標來訪問:

let arr = [1, "lbwnb", false, undefined, NaN]
console.info(arr[1])

我們一開始編寫的排序演算法,也是使用了數組。

數組還可以動態擴容,如果我們嘗試訪問超出數組長度的元素,並不會出現錯誤,而是得到undefined,同樣的,我們也可以直接往超出數組長度的地方設置元素:

let arr = [1, "lbwnb", false, undefined, NaN]
arr[5] = "???"
console.info(arr)

也可以使用pushpop來實現棧操作:

let arr = [1, "lbwnb", false, undefined, NaN]
arr.push("bbb")
console.info(arr.pop())
console.info(arr)

數組還包括一些其他的方法,這裡就不一一列出了:

let arr = [1, "lbwnb", false, undefined, NaN]
arr.fill(1)
console.info(arr.map(o => {
    return 'xxx'+o
}))

我們接著來看對象,JS中也能定義對象,但是這裡的對象有點顛覆我們的認知:

let obj = new Object()
let obj = {}

以上兩種寫法都能夠創建一個對象,但是更推薦使用下面的一種。

JS中的對象也是非常隨意的,我們可以動態為其添加屬性:

let obj = {}
obj.name = "傘兵一號"
console.info(obj)

同理,我們也可以給對象動態添加一個函數:

let obj = {}
obj.f = function (){
    console.info("我是對象內部的函數")
}

obj.f()

我們可以在函數內使用this關鍵字來指定對象內的屬性:

let name = "我是外部變數"
let obj = {}
obj.name = "我是內部變數"
obj.f = function (){
    console.info("name屬性為:"+this.name)
}

obj.f()

注意:如果使用lambda表達式,那麼this並不會指向對象。

除了動態添加屬性,我們也可以在一開始的時候指定對象內部的成員:

let obj = {
    name: "我是內部的變數",
  	f: function (){
        console.info("name屬性為:"+this.name)
    }
}

obj.f()

注意如果有多行屬性,需要在屬性定義後添加一個,進行分割!

JavaScript事件

當我們點擊一個頁面中的按鈕之後,我們希望之後能夠進行登陸操作,或是執行一些JS程式碼來實現某些功能,那麼這個時候,就需要用到事件。

事件相當於一個通知,我們可以提前設定好事件發生時需要執行的內容,當事件發生時,就會執行我們預先設定好的JS程式碼。

事件有很多種類型,其中常用的有:

  • onclick:點擊事件
  • oninput:內容輸入事件
  • onsubmit:內容提交事件

那麼如何為事件添加一個動作呢?

<input type="password" oninput="console.info('正在輸入文本')">

我們可以直接為一個元素添加對應事件的屬性,比如oninput事件,我們可以直接在事件的值中編寫js程式碼,但是注意,只能使用單引號,因為雙引號用於囊括整個值。

我們也可以單獨編寫一個函數,當事件發生時直接調用我們的函數:

function f() {
    window.alert("你輸入了一個字元")
}
<input type="password" oninput="oninput()">

僅僅了解了事件,還不足以實現高度自定義,我們接著來看DOM。

Document對象

當網頁被載入時,瀏覽器會創建頁面的文檔對象模型(Document Object Model),它將整個頁面的所有元素全部映射為JS對象,這樣我們就可以在JS中操縱頁面中的元素。

DOM HTML 樹

比如我現在想要讀取頁面中某個輸入框中的內容,那麼我們就需要從DOM中獲取此輸入框元素的對象:

document.getElementById("pwd").value

通過document對象就能夠快速獲取當前頁面中對應的元素,並且我們也可以快速獲取元素中的一些屬性。

比如現在我們可以結合事件,來進行密碼長度的校驗,密碼長度小於6則不合法,不合法的密碼,會讓密碼框邊框變紅,那麼首先我們先來編寫一個css樣式:

.illegal-pwd{
    border: red 1px solid !important;
    box-shadow: 0 0 5px red;
}

接著我們來編寫一下js程式碼,定義一個函數,此函數接受一個參數(元素本身的對象)檢測輸入的長度是否大於6,否則就將當前元素的class屬性設定為css指定的class:

function checkIllegal(e) {
    if(e.value.length < 6) {
        e.setAttribute("class", "illegal-pwd")   
    }else {
        e.removeAttribute("class")
    }
}

最後我們將此函數綁定到oninput事件即可,注意傳入了一個this,這裡的this代表的是輸入框元素本身:

<input id="pwd" oninput="checkIllegal(this)" type="password">

現在我們在輸入的時候,會自動檢查密碼是否合法。

既然oninput本身也是一個屬性,那麼實際上我們可以動態進行修改:

document.getElementById("pwd").oninput = () => console.info("???")

那麼,我們前面提及的window對象又是什麼東西呢?

實際上Window對象範圍更加廣闊,它甚至直接代表了整個窗口,當然也包含我們的Document對象,我們一般通過Window對象來彈出提示框之類的東西。

發送XHR請求

JS的大致內容我們已經全部學習完成了,那麼如何使用JS與後端進行交互呢?

我們知道,如果我們需要提交表單,那麼我們就需要將表單的資訊全部發送給我們的伺服器,那麼,如何發送給伺服器呢?

通過使用XMLHttpRequest對象,來向伺服器發送一個HTTP請求,下面是一個最簡單的請求格式:

let xhr = new XMLHttpRequest();
xhr.open('GET', '//www.baidu.com');
xhr.send();

上面的例子中,我們向伺服器發起了一次網路請求,但是我們請求的是百度的伺服器,並且此請求的方法為GET請求。

我們現在將其綁定到一個按鈕上作為事件觸發:

function http() {
    let xhr = new XMLHttpRequest();
    xhr.open('GET', '//www.baidu.com');
    xhr.send();    
}
<input id="button" type="button" onclick="http()">

我們可以在網路中查看我們發起的HTTP請求並且查看請求的響應結果,比如上面的請求,會返回百度這個頁面的全部HTML程式碼。

實際上,我們的瀏覽器在我們輸入網址後,也會向對應網站的伺服器發起一次HTTP的GET請求。

在瀏覽器得到頁面響應後,會載入當前頁面,如果當前頁面還引用了其他資源文件,那麼會繼續向伺服器發起請求,直到頁面中所有的資源文件全部載入完成後,才會停止。