前端基礎

  • 本文講前端三件套:HTML、CSS、JavaScript
  • React/Vue 框架入門,講組件化開發(fā)
  • 前端渲染模式:CSR、SSR 和 SSG,講編譯產物的區(qū)別和服務端渲染
  • Next.js 全棧開發(fā)入門,講全??蚣?/li>

不管前端框架怎么變、工具鏈怎么更新,瀏覽器只認識三樣東西:HTML、CSS、JavaScript。React、Vue、Next.js 最終都要編譯成這三者才能在瀏覽器里跑起來。

所以,理解這三件套各自做什么、怎么配合,是學習所有前端技術的起點。

HTML:頁面的骨架

HTML(HyperText Markup Language)的作用是定義頁面的結構和內容。你可以把它理解為頁面的骨架:這里放個標題、那里放個按鈕、下面是一段文字。

HTML 由各種標簽組成,標簽用尖括號包裹,大多數(shù)標簽成對出現(xiàn)(開始標簽 + 結束標簽),少數(shù)標簽(如<br> 換行、<img> 圖片、<input> 輸入框)不需要結束標簽,因為它們不包裹內容:

<h1>這是標題</h1>
<p>這是一段文字</p>
<button>點擊我</button>

<h1> 是開始標簽,</h1> 是結束標簽,中間夾的是內容。瀏覽器看到 <h1> 就知道這是個一級標題,會把文字渲染得又大又粗。
標簽可以嵌套,形成層級關系:

html
<div>
    <h2>用戶信息</h2>
    <p>姓名:張三</p>
    <p>職業(yè):工程師</p>
</div>

<div> 是一個通用的容器標簽,本身沒有視覺效果,純粹用來把相關的內容分組。你可以把它想象成一個透明的盒子,把幾個元素裝在一起方便統(tǒng)一管理。
一個完整的 HTML 文檔有固定的骨架結構:<!DOCTYPE html> 聲明這是 HTML5 文檔(固定寫法),<html> 是最外層容器,<head> 里放頁面元信息(標題、樣式引用等,不直接顯示),<body> 里放頁面可見的內容。
下面這個例子展示了最常見的 HTML 標簽,你可以直接編輯左側代碼,右側會實時顯示效果:

HTML 常見標簽
html
<!DOCTYPE html>
<html>
<body>
    <!-- 標題標簽:h1 最大,h6 最小 -->
    <h1>一級標題</h1>
    <h3>三級標題</h3>

    <!-- 段落和文本格式 -->
    <p>普通段落,可以包含 <strong>加粗</strong> 和 <em>斜體</em> 文字。</p>

    <!-- 鏈接和圖片 -->
    <a >這是一個鏈接</a>
    <br>
    <img src="https://placehold.co/200x80?text=HTML" alt="示例圖片">

    <!-- 列表 -->
    <ul>
        <li>無序列表項 1</li>
        <li>無序列表項 2</li>
    </ul>

    <!-- 表單元素 -->
    <input type="text" placeholder="這是輸入框">
    <button>這是按鈕</button>

    <!-- div 容器 -->
    <div>
        <p>這段內容被 div 包裹,方便分組管理。</p>
    </div>
</body>
</html>

你可能注意到了,純 HTML 頁面看起來很樸素:黑字白底,沒有任何美化。這就像一棟毛坯房,只有結構沒有裝修。要好看,得靠 CSS。

標簽的屬性

標簽上可以加屬性來提供額外信息。比如<a href="..."> 里的 href 指定鏈接地址,<img src="..."> 里的 src 指定圖片路徑。
有兩個屬性特別重要,后面會頻繁用到:
? id: 給元素起一個唯一的名字,方便 JavaScript 精確定位它。一個頁面里同一個 id 只能出現(xiàn)一次。
? class: 給元素分類,方便 CSS 批量設置樣式。多個元素可以有相同的 class。

html
<div id="user-profile">...</div>

<p class="highlight">這段文字需要高亮</p>
<p class="highlight">這段也需要高亮</p>

類比一下:id 像身份證號,全局唯一;class 像職業(yè)標簽,多個人可以是同一職業(yè)。

DOM 樹

瀏覽器解析 HTML 后,會在內部構建一棵樹形結構,叫做 DOM 樹(Document Object Model,文檔對象模型)。每個標簽對應樹上的一個元素節(jié)點,標簽里的文字會成為文本節(jié)點,嵌套關系就是父子關系。
比如這段 HTML:

html
<html>
<head></head>
<body>
    <h1>一級標題</h1>
    <div>
        <p>姓名:張三</p>
        <p>職業(yè):工程師</p>
    </div>
    <button>點擊</button>
</body>
</html>

瀏覽器解析后生成的 DOM 樹長這樣:
text

html
├── head
└── body
    ├── h1 ("一級標題")
    ├── div
    │   ├── p ("姓名:張三")
    │   └── p ("職業(yè):工程師")
    └── button ("點擊")

標簽的嵌套關系變成了樹的父子關系,<div> 包裹著兩個 <p>,所以 div 是父節(jié)點,兩個 p 是它的子節(jié)點。
這個概念現(xiàn)在了解就行,后面講 JavaScript 時你會看到,JS 操作頁面的本質就是在這棵 DOM 樹上進行增刪查改,比如給節(jié)點改個顏色,加點交互效果等等。

CSS:頁面的皮膚

CSS(Cascading Style Sheets)負責頁面的視覺呈現(xiàn):顏色、字體、大小、間距、布局,所有「看起來怎樣」的事情都歸它管。
CSS 的基本語法是「選擇器 + 樣式聲明」:

css
選擇器 {
    屬性: 值;
    屬性: 值;
}

選擇器決定「改誰的樣式」,花括號里的聲明決定「改成什么樣」。CSS 有三種最常用的選擇器:

css
/* 標簽選擇器:所有 <p> 標簽 */
p {
    color: gray;
}

/* class 選擇器:所有 class="highlight" 的元素(注意前面有個點) */
.highlight {
    background-color: yellow;
}

/* id 選擇器:id="title" 的那個元素(注意前面有個井號) */
#title {
    font-size: 32px;
}
?   標簽選擇器:管全局默認樣式
?   class 選擇器:管可復用的樣式類(實際開發(fā)中用得最多)
?   id 選擇器:管特定的唯一元素

除了在 <style> 標簽里用選擇器批量設置樣式,還可以直接在 HTML 標簽上寫 style 屬性,叫做行內樣式(inline style)

html
<p style="color: red; font-size: 20px;">這段文字是紅色的</p>

行內樣式只對當前這一個元素生效,優(yōu)先級比選擇器更高。一般不推薦大量使用,因為樣式散落在各個標簽里不好維護。

但后面你會看到,JavaScript 動態(tài)修改元素樣式時,本質上就是在設置行內樣式。

來看個實際效果,下面的例子里,給 HTML 結構加上了 CSS 樣式。你可以試著把 <style> 標簽里的內容刪掉一些,或者直接給 <p> 標簽加上 style 屬性,觀察 HTML 的變化:

CSS 樣式效果
html
<!DOCTYPE html>
<html>
<head>
    <style>
        body {
            font-family: sans-serif;
            max-width: 420px;
            margin: 0 auto;
            padding: 20px;
            background: #fafafa;
        }

        h2 {
            color: #333;
            border-bottom: 2px solid #4CAF50;
            padding-bottom: 8px;
        }

        /* class 選擇器:所有 class="card" 的元素 */
        .card {
            background: white;
            border: 1px solid #e0e0e0;
            border-radius: 8px;
            padding: 16px;
            margin: 12px 0;
        }

        /* .card 內部的 .name 元素(后代選擇器) */
        .card .name {
            font-size: 18px;
            font-weight: bold;
            color: #333;
        }

        .card .role {
            color: #888;
            font-size: 14px;
            margin-top: 4px;
        }

        button {
            background: #4CAF50;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 4px;
            font-size: 14px;
            cursor: pointer;
        }

        /* 偽類選擇器:鼠標懸停時的樣式 */
        button:hover {
            background: #45a049;
        }
    </style>
</head>
<body>
    <h2>團隊成員</h2>

    <div class="card">
        <p class="name">張三</p>
        <p class="role">前端工程師</p>
    </div>

    <div class="card">
        <p class="name">李四</p>
        <p class="role">后端工程師</p>
    </div>

    <button>添加成員</button>
</body>
</html>

可以用的 CSS 屬性非常多,所有頁面樣式相關的功能都歸 CSS 管,比如顏色、字體、間距、動畫、布局自動適配不同尺寸的屏幕等等。

不過現(xiàn)在你只需要理解 CSS 在 HTML 中發(fā)揮的作用,沒必要去背這些細節(jié)了,AI 工具對 CSS 的掌握程度很高,需要的時候給 AI 描述你想要的效果,它就能幫你生成相應的 CSS 代碼。

瀏覽器開發(fā)者工具

在繼續(xù)學 JavaScript 之前,先認識一個重要的工具。在任何網頁上按 F12(或右鍵 → 檢查),就能打開瀏覽器的開發(fā)者工具(DevTools)。這是前端開發(fā)最核心的調試工具,幾個常用面板:

?   Elements(元素):查看和實時編輯頁面的 HTML 和 CSS。你可以直接修改標簽內容、調整樣式,效果立即反映在頁面上(刷新后恢復)
?   Console(控制臺):執(zhí)行 JavaScript 代碼,查看報錯信息。前端調試最??吹木褪沁@個面板
?   Network(網絡):查看所有網絡請求,包括加載了哪些文件、請求了哪些 API、每個請求花了多長時間

動手試試

現(xiàn)在就在本頁面按 F12 打開控制臺,依次輸入以下命令,觀察頁面的變化:

javascript
// 查看當前頁面標題
document.title

// 把頁面所有段落文字變成紅色
// 等于給所有 <p> 標簽加上 style="color: red;" 屬性
document.querySelectorAll('p').forEach(el => el.style.color = 'red')

// 把本文的標題改掉
document.querySelector('h1').textContent = '被我用 JS 改了!'

刷新頁面讓瀏覽器重新渲染 HTML,即可撤銷這些修改。

你在 Console 里手動執(zhí)行的代碼,和寫在 <script> 標簽里的代碼效果完全一樣,區(qū)別只是一個手動執(zhí)行、一個頁面加載時自動執(zhí)行。

JavaScript:頁面的靈魂

HTML 搭好了骨架,CSS 畫好了皮膚,但頁面還是「死」的,點按鈕沒反應,輸入框里填了內容也不知道該干嘛。要讓頁面「活」起來,就需要 JavaScript。

JavaScript(簡稱 JS)負責頁面的行為和交互邏輯:點擊按鈕后發(fā)生什么、如何從后端獲取數(shù)據(jù)、怎么動態(tài)更新頁面內容。

JavaScript 的基礎語法(變量、函數(shù)、條件判斷等)可以參考 JavaScript 基礎入門系列教程,這里不重復講。我們重點看 JS 在瀏覽器里特有的能力:操作 DOM 和 響應用戶事件。

JS 代碼寫在 HTML 的 <script> 標簽里,瀏覽器遇到它就知道要執(zhí)行代碼了。前面說過,瀏覽器把 HTML 解析成一棵 DOM 樹,JavaScript 在瀏覽器里做的事情,本質上就是在這棵樹上增刪改查:通過 document.getElementById 找到某個元素,修改它的文本、樣式、屬性;通過監(jiān)聽 click、input 等事件,響應用戶的操作。

來看一個實際例子,感受一下 JavaScript 如何讓頁面「活」起來:

JavaScript DOM 操作
html
<!DOCTYPE html>
<html>
<head>
    <style>
        body {
            font-family: sans-serif;
            max-width: 400px;
            margin: 0 auto;
            padding: 20px;
        }

        .greeting {
            font-size: 24px;
            color: #333;
            margin: 16px 0;
            padding: 12px;
            background: #f0f0f0;
            border-radius: 8px;
            min-height: 30px;
        }

        input {
            font-size: 16px;
            padding: 8px 12px;
            border: 2px solid #ddd;
            border-radius: 4px;
            width: 200px;
        }

        input:focus {
            border-color: #4CAF50;
            outline: none;
        }

        button {
            font-size: 14px;
            padding: 8px 16px;
            margin: 4px;
            cursor: pointer;
            color: white;
            border: none;
            border-radius: 4px;
        }

        .green { background: #4CAF50; }
        .blue { background: #2196F3; }
        .orange { background: #FF9800; }

        .btn-group { margin-top: 12px; }

        .color-box {
            width: 100%;
            height: 40px;
            border-radius: 8px;
            margin-top: 12px;
            /* 顏色變化時有 0.3 秒的過渡動畫 */
            transition: background-color 0.3s;
            background: #e0e0e0;
        }
    </style>
</head>
<body>
    <h3>實時問候</h3>
    <input type="text" id="name-input" placeholder="輸入你的名字">
    <div class="greeting" id="greeting">你好,請輸入名字</div>

    <h3>切換顏色</h3>
    <div class="btn-group">
        <button class="green" onclick="changeColor('#4CAF50')">綠色</button>
        <button class="blue" onclick="changeColor('#2196F3')">藍色</button>
        <button class="orange" onclick="changeColor('#FF9800')">橙色</button>
    </div>
    <div class="color-box" id="color-box"></div>

    <script>
        // 監(jiān)聽輸入事件:每次輸入內容變化時自動更新問候語
        let nameInput = document.getElementById('name-input');
        let greeting = document.getElementById('greeting');

        nameInput.addEventListener('input', function() {
            let name = nameInput.value;
            if (name) {
                greeting.textContent = '你好,' + name + '!';
            } else {
                greeting.textContent = '你好,請輸入名字';
            }
        });

        // 點擊按鈕切換顏色
        function changeColor(color) {
            let box = document.getElementById('color-box');
            box.style.backgroundColor = color;
        }
    </script>
</body>
</html>

如果你習慣了后端或腳本語言的編程模式,初次接觸前端 JS 代碼可能有點奇怪。

后端代碼從第一行開始往下執(zhí)行,做完一件事接著做下一件。但前端不太一樣,頁面加載完之后,就一直在等著用戶操作,用戶做了什么,代碼才響應什么。

這就引出了前端編程最核心的模式:回調函數(shù)(callback)

你不是在頁面完成加載的時候立即執(zhí)行這段代碼,而是把這段代碼「注冊」到某個事件上,等事件發(fā)生時瀏覽器會自動調用它。

比如按鈕上的 onclick="changeColor('#4CAF50')" 就是一個回調,意思是「當用戶點擊這個按鈕時,執(zhí)行 changeColor 函數(shù)」。你不需要寫代碼去檢測用戶有沒有點擊,瀏覽器會幫你盯著,點了就調用。

nameInput.addEventListener('input', function() {...}) 也是同樣的思路。addEventListener 的意思是給輸入框注冊一個回調:每當輸入內容發(fā)生變化,就執(zhí)行后面這個函數(shù),通過 greeting.textContent = ... 把問候語實時更新到頁面上。

回調函數(shù)內部做的事情,就是前面說的 DOM 操作。比如 changeColor 函數(shù)通過 box.style.backgroundColor = color 給元素設置行內樣式,輸入框的回調則通過 greeting.textContent = ... 修改元素的文本內容,這樣就能在頁面上實時看到效果。

到這里,你已經了解了前端三件套各自的職責。接下來看看它們是怎么配合工作的。

三劍客合體

HTML 搭骨架、CSS 畫皮膚、JavaScript 加靈魂。來看一個完整的例子,把三者的協(xié)作串起來。
下面是一個計數(shù)器,功能很簡單:點按鈕增減數(shù)字。但麻雀雖小五臟俱全,HTML、CSS、JS 各司其職:

HTML/CSS/JS 計數(shù)器
html
<!DOCTYPE html>
<html>
<head>
    <style>
        /* CSS:定義樣式 */
        .container {
            text-align: center;
            margin-top: 40px;
            font-family: sans-serif;
        }
        .counter {
            font-size: 48px;
            color: #333;
            margin: 20px 0;
        }
        button {
            font-size: 16px;
            padding: 10px 20px;
            margin: 5px;
            cursor: pointer;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
        }
        button:hover {
            background-color: #45a049;
        }
    </style>
</head>
<body>
    <!-- HTML:定義結構 -->
    <div class="container">
        <h1>簡單計數(shù)器</h1>
        <div class="counter" id="count">0</div>
        <button onclick="increment()">增加</button>
        <button onclick="decrement()">減少</button>
        <button onclick="reset()">重置</button>
    </div>

    <script>
        // JavaScript:定義行為
        let count = 0;

        function increment() {
            count++;
            updateDisplay();
        }

        function decrement() {
            count--;
            updateDisplay();
        }

        function reset() {
            count = 0;
            updateDisplay();
        }

        function updateDisplay() {
            document.getElementById('count').textContent = count;
        }
    </script>
</body>
</html>

串一下這個例子的完整流程:

1   HTML 部分:<button onclick="increment()">增加</button> 創(chuàng)建了一個按鈕,onclick 屬性告訴瀏覽器「點擊時調用 JavaScript 的 increment() 函數(shù)」。<div id="count">0</div> 創(chuàng)建了一個顯示數(shù)字的區(qū)域,id="count" 給它起了個名字,方便 JS 定位。
2   CSS 部分:button { background-color: #4CAF50; color: white; } 讓所有按鈕變成綠底白字,button:hover 定義了鼠標懸停時背景色變深,.counter { font-size: 48px; } 讓數(shù)字顯示得很大。
3   JavaScript 部分:當用戶點擊「增加」按鈕時,increment() 函數(shù)被調用:先執(zhí)行 count++ 讓變量加 1,然后調用 updateDisplay(),通過 document.getElementById('count') 找到那個顯示數(shù)字的 <div>,把它的文本內容更新為新的數(shù)值。

動手試試:把按鈕的 background-color 改成 #2196F3(藍色),然后修改 increment() 函數(shù)讓每次增加 2,看看效果。

文件分離

上面為了演示方便把 CSS 和 JavaScript 都寫在了 HTML 文件里,但實際項目中它們通常是獨立的文件。HTML 通過 <link> 引入 CSS,通過 <script src> 引入 JavaScript。

下面把計數(shù)器拆成三個獨立文件,點擊左側的文件名可以切換查看。功能和前面完全一樣,只是代碼組織方式變了:

文件分離:HTML + CSS + JS
index.html
html
<!DOCTYPE html>
<html>
<head>
    <!-- 引入外部 CSS 文件 -->
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="container">
        <h1>簡單計數(shù)器</h1>
        <div class="counter" id="count">0</div>
        <button onclick="increment()">增加</button>
        <button onclick="decrement()">減少</button>
        <button onclick="reset()">重置</button>
    </div>
    <!-- 引入外部 JavaScript 文件 -->
    <script src="app.js"></script>
</body>
</html>
styles.css (內容見上方 <style> 標簽內)
app.js (內容見上方 <script> 標簽內)

分成獨立文件的好處是結構更清晰,而且多個頁面可以共享同一個 CSS 或 JS 文件。

瀏覽器的加載流程

瀏覽器從上到下解析 HTML,遇到 CSS 和 JS 的引用時發(fā)起下載請求,多個文件可以并行下載,但它們對頁面渲染的影響不同:

?   CSS 會阻塞渲染:瀏覽器要等 CSS 下載完才開始畫頁面
?   同步 JS 會阻塞 HTML 解析:遇到 <script> 標簽時暫停解析,等腳本下載并執(zhí)行完才繼續(xù)

如果你打開瀏覽器的開發(fā)者工具(F12),切到 Network(網絡)面板,刷新頁面,會看到請求列表:第一個通常是 HTML 文件,緊接著是若干 .css 和 .js 文件。

如果一個網站加載比較慢,你會看到一個典型的過程:

1   首先是一段白屏(瀏覽器在等 CSS 下載完才開始渲染)
2   然后頁面結構和樣式一起出現(xiàn),但點擊按鈕可能沒有反應(JS 還在加載中,交互邏輯還沒就緒)
3   最后等 JS 加載完畢,頁面才能正常使用。

這也是為什么 <link> 標簽通常放在 <head> 里(讓 CSS 盡早開始下載),而 <script> 標簽通常放在 <body> 末尾或加上 defer 屬性(避免阻塞 HTML 解析)。

現(xiàn)代項目更推薦用 <script defer src="app.js"> 放在 <head> 里,瀏覽器會并行下載腳本,等 HTML 解析完再執(zhí)行。

小結

瀏覽器只認識 HTML、CSS、JavaScript 這三樣東西。

?   HTML 定義頁面有什么內容
?   CSS 定義這些內容長什么樣
?   JavaScript 定義用戶操作后發(fā)生什么

不管前端技術怎么發(fā)展、框架怎么更新?lián)Q代,最終到了瀏覽器這一層,還是這三者在協(xié)作。理解了這個基礎,后面學 React、Vue 這些框架就不會迷糊了,因為框架只是幫你更高效地組織這三者,本質沒變。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Doctype作用? 嚴格模式與混雜模式如何區(qū)分?它們有何意義? 聲明位于文檔中的最前面,處于 標簽之前。告知瀏覽...
    空城皆是舊夢閱讀 722評論 0 3
  • 1.幾種基本數(shù)據(jù)類型?復雜數(shù)據(jù)類型?值類型和引用數(shù)據(jù)類型?堆棧數(shù)據(jù)結構? 基本數(shù)據(jù)類型:Undefined、Nul...
    伯納烏的追風少年閱讀 26,137評論 2 46
  • 1.幾種基本數(shù)據(jù)類型?復雜數(shù)據(jù)類型?值類型和引用數(shù)據(jù)類型?堆棧數(shù)據(jù)結構? 基本數(shù)據(jù)類型:Undefined、Nul...
    極樂君閱讀 5,878評論 0 106
  • 1.行內元素和塊級元素?img算什么?行內元素怎么轉化為塊級元素? 行內元素:和有他元素都在一行上,高度、行高及外...
    極樂君閱讀 2,601評論 0 20
  • 1、<img> 的title 和alt 有什么區(qū)別 alt屬性和title屬性相同點: 它們都會出現(xiàn)浮層,顯示自己...
    糖醋魚_閱讀 1,003評論 0 2

友情鏈接更多精彩內容