一、知識回顧-Vue2項目基礎操作與環境配置
1.1 項目啟動
- 項目打開方式:直接將項目文件夾(如
my-app
)拖拽到 Visual Studio Code(推薦編輯器),避免拖拽父級文件夾,防止路徑混亂。 - 啟動命令:
- 進入項目根目錄(必須與
package.json
同級),打開終端執行啟動命令。 - 默認命令:
npm run serve
(命令定義在package.json
的scripts
字段中)。 - 命令變體:部分項目可能使用
npm run dev
或npm run start
,需以實際項目package.json
中的配置為準(例:若scripts: {"dev": "vue-cli-service serve"}
,則執行npm run dev
)。
- 進入項目根目錄(必須與
- 服務管理:
- 關閉服務:終端中按
Ctrl+C
(Mac 為Command+C
),輸入y
確認。 - 重啟服務:需先關閉現有服務,再重新執行啟動命令,不可直接開新終端啟動(避免端口占用)。
- 終端切換:VS Code 可通過右側標簽頁切換多個終端實例。
- 關閉服務:終端中按
1.2 淘寶鏡像配置
- 作用:解決從國外 npm 倉庫下載依賴速度慢的問題(國內服務器定期同步國外倉庫代碼,形成鏡像副本)。
- 切換邏輯:
- 自動切換:當系統檢測到下載速度過慢時,會提示是否切換至淘寶鏡像。
- 適用場景:僅在下載速度慢時配置,正常網絡環境可無需設置(鏡像內容與原倉庫完全一致,不影響功能)。
- 主動配置步驟:
- 打開終端,執行配置命令:
npm config set registry https://registry.npm.taobao.org
。 - 驗證配置:執行
npm config get registry
,若返回淘寶鏡像地址則配置成功。 - 注意事項:配置后下載地址會永久變更,如需恢復默認倉庫,執行
npm config set registry https://registry.npmjs.org
。
- 打開終端,執行配置命令:
1.3 項目訪問與常見問題
- 訪問方式:啟動成功后,終端會輸出本地地址(如
http://localhost:8080/
),在瀏覽器中輸入該地址即可訪問項目。 - 禁止直接訪問 HTML:項目運行在集成服務器環境,直接雙擊
public/index.html
無法正常加載(依賴 Webpack 打包的模塊化資源)。 - 常見啟動錯誤排查:
- 錯誤場景 1:在父目錄或子目錄(如
src
)執行啟動命令 → 解決方案:切換到package.json
所在的根目錄。 - 錯誤場景 2:命令不存在(如
npm run dev
報錯)→ 解決方案:查看package.json
的scripts
字段,確認正確命令。 - 錯誤場景 3:端口占用 → 解決方案:終端按
Ctrl+C
關閉占用端口的服務,或重啟終端。
- 錯誤場景 1:在父目錄或子目錄(如
二、項目文件結構與 SPA 概念
2.1 核心目錄解析
目錄/文件 | 作用與說明 | 注意事項 |
---|---|---|
node_modules | 存放通過npm install 下載的所有依賴包(如 Vue、Vue Router) | 通常無需修改內部代碼,若需修改源碼需謹慎(升級依賴可能覆蓋修改) |
public | 靜態文件目錄,存放項目唯一的 HTML 文件(單頁應用核心) | 包含index.html (掛載點)和favicon.ico (瀏覽器標簽圖標) |
src | 核心開發目錄,所有業務代碼在此編寫 | 開發的核心區域,需熟練掌握子目錄功能 |
src/assets | 存放靜態資源(圖片、字體文件等) | 建議按類型分類(如assets/images 、assets/fonts ) |
src/components | 存放公共復用組件(如導航欄、按鈕、彈窗等) | 組件文件建議用 PascalCase 命名(如Navbar.vue ) |
src/store | 與 Vuex 相關的狀態管理目錄(用于多組件數據共享,后續章節講解) | 初期可忽略,需使用 Vuex 時再配置 |
src/App.vue | 項目根組件,所有頁面組件最終嵌套在該組件中 | 單文件組件的典型示例,包含template 、script 、style 三部分 |
src/main.js | 項目入口文件,建立所有 JS 文件的依賴關系鏈 | 所有自定義 JS 必須直接/間接被該文件引入,否則無法生效 |
2.2 SPA 與 MPA 對比(單頁應用 vs 多頁應用)
對比維度 | 單頁應用(SPA) | 多頁應用(MPA) |
---|---|---|
核心特點 | 只有 1 個 HTML 文件,頁面切換不刷新整體 | 多個獨立 HTML 文件,跳轉時加載新頁面 |
切換方式 | 通過前端路由(如 Vue Router)動態替換內容 | 通過超鏈接(<a> 標簽)跳轉新頁面 |
用戶體驗 | 流暢(類似桌面/移動端 App) | 跳轉時有加載延遲,體驗較割裂 |
開發復雜度 | 需處理路由、狀態管理,復雜度較高 | 無需路由,僅需處理頁面間數據傳遞(如 URL 參數) |
SEO 優化 | 較差(內容動態渲染,搜索引擎難抓取) | 較好(每個頁面獨立 HTML,易被抓取) |
適用場景 | 后臺管理系統、移動端 App、數據看板 | 新聞網站、電商平臺(如京東)、博客 |
三、核心文件深度解析
3.1 入口文件 main.js
main.js
是項目的“入口大門”,所有 JS 依賴最終通過它關聯,其核心作用是創建 Vue 實例并掛載到頁面。
核心代碼解析(Vue 2 示例)
// 1. 導入 Vue 核心包(從 node_modules 中查找)
import Vue from 'vue'
// 2. 導入根組件 App.vue(相對路徑,需加 ./)
import App from './App.vue'
// 3. 導入路由實例(后續路由章節配置,可選)
// import router from './router'// 4. 關閉生產環境的錯誤提示(上線時隱藏控制臺報錯,避免暴露代碼問題)
Vue.config.productionTip = false// 5. 創建 Vue 實例
new Vue({// router, // 路由實例(可選,需配置路由時添加)render: h => h(App) // 渲染根組件 App(h 是 createElement 的簡寫,用于創建虛擬 DOM)
}).$mount('#app') // 掛載到 index.html 中 id 為 app 的元素(等效于配置 el: '#app')
關鍵知識點
- 依賴鏈規則:若自定義 JS 文件(如
src/a.js
)未被main.js
直接/間接引入(例:main.js
引入c.js
,c.js
引入a.js
),則該文件功能不會生效(Webpack 打包時會忽略未引入的文件)。 render
函數作用:Vue 根組件需通過render
函數渲染子組件(非根組件可通過components
注冊后直接使用),h(App)
表示將App
組件轉換為虛擬 DOM 并渲染。- 掛載方式對比:
- 傳統方式:
new Vue({ el: '#app' })
(直接指定掛載點)。 - 推薦方式:
$mount('#app')
(更靈活,可動態控制掛載時機)。
- 傳統方式:
3.2 靜態文件 public/index.html
該文件是項目唯一的 HTML 載體,所有 Vue 組件最終都會渲染到這個文件中。
核心代碼解析
<!DOCTYPE html>
<html lang=""><head><meta charset="utf-8"><!-- 適配移動端 --><meta name="viewport" content="width=device-width,initial-scale=1.0"><!-- 頁面標題(由 Webpack 動態注入,配置在 package.json 中) --><title><%= htmlWebpackPlugin.options.title %></title></head><body><!-- 1. Vue 應用的掛載點:所有組件內容最終渲染到這里 --><div id="app"></div><!-- 2. 兼容性提示:瀏覽器禁用 JS 時顯示 --><noscript><strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><!-- 3. JS 自動注入:Webpack 打包時會將編譯后的 JS 文件(如 main.js)自動插入這里,無需手動加 <script> 標簽 --></body>
</html>
關鍵知識點
- 自動注入機制:HTML 中未顯式引入
main.js
,但 Webpack 會在打包時將所有依賴的 JS 合并并注入到<body>
末尾,確保 DOM 加載完成后執行 JS。 - 掛載點作用:
id="app"
的div
是 Vue 實例的“容器”,Vue 會將虛擬 DOM 渲染為真實 DOM 并替換該容器內的內容。
四、單文件組件(.vue)詳解
單文件組件(SFC)是 Vue 的核心特性,將組件的模板(HTML)、邏輯(JS)、樣式(CSS) 封裝在一個.vue
文件中,結構清晰且便于維護。
4.1 基本結構與要求
一個完整的單文件組件必須包含template
、script
,style
可選(若無需樣式可省略)。
標準結構示例(Demo.vue
)
<template><!-- 模板:必須有且只有一個根元素(通常用 div 包裹) --><div class="demo-container"><h1>{{ title }}</h1><p>{{ content }}</p></div>
</template>
<script>
// 邏輯:通過 export default 導出組件配置對象
export default {// 組件名稱(建議與文件名一致,PascalCase 命名,非必需但便于調試)name: 'Demo',// 數據定義:必須是函數(避免組件復用時數據污染),返回對象data() {return {title: '單文件組件示例',content: '這是組件的動態內容'}},// 生命周期鉤子(可選,如組件創建后執行)created() {console.log('Demo 組件已創建')}
}
</script>
<style scoped>
/* 樣式:scoped 表示樣式僅作用于當前組件(避免全局污染) */
.demo-container {width: 80%;margin: 0 auto;padding: 20px;border: 1px solid #eee;
}
h1 {color: #42b983; /* Vue 主題色 */
}
</style>
核心要求
template
規則:- 必須包含一個根元素(若有多個同級元素,需用
div
、template
等標簽包裹),否則會觸發 ESLint 錯誤。 - 支持 Vue 指令(如
v-for
、v-if
、v-bind
)和插值語法({{ 變量 }}
)。
- 必須包含一個根元素(若有多個同級元素,需用
script
規則:- 必須通過
export default
導出組件配置對象(否則無法被其他組件引入)。 data
必須是函數(返回對象),而非直接定義對象(原因:組件復用后,每個實例會擁有獨立的數據副本,避免數據共享污染)。
- 必須通過
style
規則:- 若需樣式隔離,添加
scoped
屬性(原理:Webpack 會給組件內所有 DOM 元素添加唯一data-v-xxx
屬性,樣式選擇器會自動匹配該屬性,如.demo-container[data-v-123]
)。 - 支持預處理器(如 SCSS):需安裝對應依賴(如
node-sass
、sass-loader
),并在style
標簽中指定語言(例:<style lang="scss" scoped>
)。
- 若需樣式隔離,添加
4.2 組件引入與注冊
組件需先引入、再注冊,最后才能在模板中使用,流程如下(以App.vue
引入Demo.vue
為例):
步驟 1:引入組件
在父組件(如App.vue
)的script
中,通過import
語法引入子組件:
// App.vue 的 script 部分
import Demo from './components/Demo.vue' // 相對路徑:從當前目錄下的 components 文件夾引入 Demo.vue
步驟 2:注冊組件
在export default
的components
選項中注冊引入的組件:
export default {name: 'App',components: {Demo // 等價于 Demo: Demo(ES6 簡寫,鍵和值同名時可省略值)}
}
步驟 3:使用組件
在父組件的template
中,使用組件標簽(支持兩種寫法):
<template><div id="app"><!-- 寫法 1:kebab-case(推薦,符合 HTML 標簽命名規范) --><demo></demo><!-- 寫法 2:PascalCase(與組件名一致,Vue 支持但不推薦在 HTML 中使用) --><!-- <Demo></Demo> --></div>
</template>
命名規范
- 組件文件名:PascalCase(如
UserProfile.vue
),便于區分組件和普通文件。 - 組件標簽:在模板中使用kebab-case(如
<user-profile>
),符合 HTML 標簽的小寫命名習慣。 - 避免使用保留字(如
div
、button
)作為組件名,防止與原生標簽沖突。
4.3 樣式作用域與深度選擇器
1. scoped
的局限性
- 當組件中使用
scoped
后,樣式僅作用于當前組件的 DOM,無法修改子組件的樣式(子組件的 DOM 沒有當前組件的data-v-xxx
屬性)。 - 例:若
App.vue
中用了scoped
,無法直接修改Demo.vue
中.demo-container
的樣式。
2. 深度選擇器(解決子組件樣式修改)
若需修改子組件樣式,可使用深度選擇器(不同預處理器語法不同):
- 原生 CSS:使用
>>>
(例:>>> .demo-container { color: red; }
)。 - SCSS/LESS:使用
/deep/
(例:/deep/ .demo-container { color: red; }
)。 - Vue 3 中:使用
:deep()
(例::deep(.demo-container) { color: red; }
)。
示例(App.vue
修改Demo.vue
樣式)
<!-- App.vue 的 style 部分 -->
<style scoped>
/* 使用深度選擇器修改 Demo 組件的 .demo-container 樣式 */
>>> .demo-container {border-color: red;
}
</style>