十三、idea 開發 vue
idea 中安裝 Vue 插件 (2023 版本已經無需安裝,自帶就有)
然後使用 idea 打開之前創建的 vue 項目
啓動項目
方案 1: 點擊旁邊按鈕啓動
方案 2: 下方終端輸入命令 npm run serve
如上,如果腳本改成 dev, 那麼就需要改成命令為 npm run dev
idea 中的終端無法執行 npm run serve 啓動項目,提示 npm 不是內部或外部命令
解決方案 1: 以管理員身份啓動 idea, 打開項目運行
解決方案 2: 不要使用 powershell, 也就是 ps 方式執行 cmd, 換成默認的 cmd
十四、單文件組件【重點】
14.1 介紹
以前
以前是創建了很多.html 的文件組成一個完整項目
現在
vue 項目中是隻有一個頁面,是一種 spa (單頁面程序)
如何實現,一個頁面實現整個項目?
就是使用各種組件組裝成一個頁面. ****
但是,昨天學的組件
使用 Vue.component 來定義全局組件,緊接着用 new Vue ({el: '#app'}) 在每個頁面內指定一個容器元素。或者在 Vue 對象內本地註冊組件
這種方式在很多中小規模的項目中運作的很好,在這些項目裏 JavaScript 只被用來加強特定的視圖。
但當在更復雜的項目中,或者你的前端完全由 JavaScript 驅動的時候,下面這些缺點將變得非常明顯:
- 全局定義 (Global definitions) 強制要求每個 component 中的命名不得重複
- 字符串模板 (String templates) 缺乏語法高亮,在 HTML 有多行的時候,需要用到醜陋的
\- 不支持 CSS (No CSS support) 意味着當 HTML 和 JavaScript 組件化時,CSS 明顯被遺漏
- 沒有構建步驟 (No build step) 限制只能使用 HTML 和 ES5 JavaScript,而不能使用預處理器,如 Pug (formerly Jade) 和 Babel
現在
文件擴展名為 **.vue** 的 single-file components (單文件組件) 為以上所有問題提供瞭解決方法,並且還可以使用 webpack 或 Browserify 等構建工具。
單文件組件的組成結構:
- template 組件的模塊區域 (html)
- script 業務邏輯區域 (js)
- style 樣式區域 (css)
14.2 使用
在工程的 src/components 下創建一個 Demo1 單文件 Demo1 就是自定義的組件
創建後好,組件內部結構
正常的寫代碼
<template>
<!-- 組件的模板,要求只能有一個根元素 -->
<div>
<h1>組件的模板</h1>
<p>取出數據: {{ msg }}</p>
<button @click="dianji">按鈕</button>
<p>計算屬性: {{ reverseMsg }}</p>
</div>
</template>
<script>
export default {
name: "Demo1", // 組件的名稱
data() { // 組件的data數據,只能是函數,不能是對象,且必須返回一個對象,數據放在return的對象中
return {
msg: '組件的data數據'
}
},
methods: {
dianji() {
alert("按鈕被點擊了")
}
},
// 組件的計算屬性
computed: {
reverseMsg() {
return this.msg.split('').reverse().join('')
}
}
}
</script>
<style scoped>
div{
color: red;
}
</style>
組件定義完畢後,需要在其他頁面使用
在 HomeView.vue 中使用
- 哪裏使用組件,哪裏註冊
- 註冊完,組件名當標籤用
注意:
其中./ 是相對路徑,@是從根路徑
// @是從根路徑
import Demo1 from "@/components/Demo1.vue";
// ./ 是相對路徑
import Demo2 from "./components/Demo2.vue";
十五、Vue 組件間的參數傳遞 [熟悉]
15.1 父傳子 [熟悉]
父組件中使用子組件時,在標籤內設置屬性
傳遞是數字,布爾值需要 v-bind:【真實麻煩 】
傳遞是變量也需要 v-bind:
子組件中設置 props 接收傳遞過來的數據即可
15.2 子傳父 [瞭解]
使用組件中的 props 屬性是無法完成子組件向父組件傳值的
那麼,如果需要子組件向父組件傳遞值該如何做?
- Vue 提供了方案: 在子組件中使用自定義事件向父組件傳遞數據.
具體步驟
- 1. 子組件通過 **$emit** 函數將數據發給父組件
this.$emit (' 父組件中使用子組件時定義的事件名 ', 數據)
- 2. 父組件在使用子組件的時候,定義一個 @事件,這個事件名是 $emit 中自定義的事件名
- 3. 父組件中,需要設計這個 @事件的響應函數,函數中設計參數,這個參數就是子組件傳遞過來的數據
需求:子組件中設置輸入框,輸入完,點擊按鈕,將數據傳遞給父組件
<template>
<div>
我是子組件Son,我收到了父組件的參數:
姓名:{{name}}
年齡:{{age}}
老家:{{home}} <br>
<input type="text" v-model="num">
<button @click="sendNum">發送給父組件</button>
</div>
</template>
<script>
export default {
name: "Son",
props:["age","name","home"],
data() {
return {
num:null
}
},
methods: {
sendNum(){
// 1 子組件向父組件傳遞數據,使用事件觸發
// this.$emit("父組件中自定義的事件名",要傳遞的數據)
this.$emit("receiveData",this.num)
}
}
}
</script>
<style scoped>
</style>
父組件中,在子組件標籤定義自定義事件準備接收子組件發來的數據
<template>
<div>
<h2>我是Father組件</h2>
<span>從兒子組件傳遞過來的數據:{{num}}</span>
<!-- 這裏是Father組件,使用子組件son-->
<!-- 給組件傳參,就是設置自定義屬性 -->
<!--@receiveData是自定義事件-->
<Son :age="18" name="曹丕" :home="home"
@receiveData="getSonNum"></Son>
</div>
</template>
<script>
import Son from "@/views/Son.vue";
export default {
name: "Father",
components: {Son},
data() {
return {
home:"魏國許都",
num:null
}
},
methods: {
getSonNum(num){
console.log("我是Father組件,我收到了子組件傳遞過來的數據:",num)
this.num = num;
}
}
}
</script>
<style scoped>
</style>
執行流程解析
十六、Vue-router 路由【重點】
16.1 介紹
路由的本質就是一種對應關係,比如説我們在 url 地址中輸入我們要訪問的 url 地址之後,瀏覽器要去請求這個 url 地址對應的資源。
那麼 url 地址和真實的資源之間就有一種對應的關係,就是路由。
根據不同的事件來顯示不同的頁面內容
16.2 Vue 的路由 (先了解,學過後再回頭細看!!!)
Vue 默認屬於單頁面的程序,主要通過 URL 中的 hash 來實現不同頁面之間的切換。這種切換方式稱作前端路由。
Vue 中使用路由的方式,現在是通過使用 Vue 的核心插件 VueRouter 實現的
Vue Router的核心作用
- 跳轉/切換頁面
- 聲明式 (寫標籤)
- <router-link to="要跳轉的組件名稱">
- 編程式 (寫代碼)
- this.$router.push("要跳轉的組件名稱")
- 跳轉攜帶數據
- 聲明式導航傳遞參數通過路徑拼接的
- /about/1001
- 在index.js的路徑中 通過/about/:id 綁定數據
- 接收 this.$router.params.參數名
- 編程式導航實現傳遞參數
- 傳遞 this.$router.push({path:'路徑',query:{參數名:值,...}})
- 接收 this.$router.query.參數名
- 路由模式
- hash模式:監聽瀏覽器地址hash值變化,執行相應的js切換網頁;
- history模式:利用history API實現url地址改變,網頁內容改變;
- 它們最明顯的區別就是hash會在瀏覽器地址後面增加#號
16.3 安裝路由模塊
介紹 | Vue Router (vuejs.org)
使用命令:
npm install vue-router
# 如果報錯,可能是npm版本過高,存在兼容性問題,那麼使用如下命令
npm install --legacy-peer-deps vue-router@3.5.2
npm install --legacy-peer-deps vue-router@3.1.3
ps: 今天練習過一次以後,後續在創建項目時可以直接選擇路由部分內容,創建出的項目直接就配置好了
16.4 解讀 AboutView 和 HomeView 的路由
- 路由入口/切入點
- 聲明式寫標籤開始路由
- 或者是編程式寫js開始路由
- 路由匹配規則/映射表
- src/router/index.js
- 展現該頁面(路由的出口)
- <router-view>
16.5 演示:聲明式路由 [重點]
需求:新增一個按鈕 / 鏈接,點擊實現切換個人信息頁面
16.5.1 創建 MyInfo.vue
路由頁面建議創建在 **src/views/** 下
components 文件夾下是公共組件
views 文件夾下是 路由組件
<template>
<div>
<h1>MyInfo</h1>
<p>這是個人信息頁面</p>
<img src="../assets/James.png" alt="詹姆斯高斯林">
</div>
</template>
<script>
export default {
name: "MyInfo",
data() {
return {}
},
methods: {}
}
</script>
<style scoped>
</style>
16.5.2 設置路由入口
在 App.vue 頁面中設置聲明式路由
16.5.3 設置映射規則
在 **/src/router/index.js** 文件
填充以下內容
import Vue from 'vue';
import Router from 'vue-router';
import myInfo from "@/views/MyInfo.vue";
Vue.use(Router)//引入路由
export default new Router({
// 路由規則
routes: [
{
path: '/home',//路由地址
name: 'Home',
component: () => import('@/views/Home.vue') // 跳轉到這個組件
},
{
path: '/info',//路由地址
name: 'MyInfo',
component: myInfo // 跳轉到這個組件
},
]
})
注意寫完 route 的 index.js 之後 沒用 一定找到 main.js 將 router 進行掛載
16.5.4 設置路由填充位 (展現)
App.vue 中設置路由展示位<router-view>
在哪個頁面設置展示位<router-view> , 組件就在哪個頁面展示出來
16.6 演示:編程式路由 [重點]
剛才演示的是聲明式路由,現在使用編程式路由
演示:公告頁面切換
16.6.1 創建公告頁 Note.vue
<template>
<div>
<h1>公告頁面</h1>
<ul>
<li>“東風-5C燒餅 吸引範圍覆蓋全網”新</li>
<li>空軍航空開放活動最新劇透來了</li>
<li>公安部公佈10起網絡違法犯罪案例</li>
</ul>
</div>
</template>
16.6.2 設置路由入口 (編程式路由)
App.vue 設置標籤,綁定事件,事件觸發函數,函數內編寫代碼實現路由
this.$router.push ("/ 路徑")
這個函數的作用類似 <router-link to="">
- 這裏寫的是this.$router
- 不是this.$route !!!!!!
16.6.3 src/router/index.js 設置路由規則
16.6.4 bug: 第一次點擊跳轉沒事,再點一次報錯
解決:
- 方式 1: 設置異常捕獲
// 在router中的index.js中加上以下代碼,注意加在use之前寫
const routerPush = VueRouter.prototype.push;
VueRouter.prototype.push = function (location) {
return routerPush.call(this, location).catch((err) => {});
};
方式 2:
在編程式是路由,即 this.$router.push () 修改成這樣
const currentRoute = this.$router.currentRoute;
if (currentRoute.path !== '/note') {
this.$router.push({
path:"/note"
})
}
16.7 路由跳轉時參數的傳遞
16.7.1 聲明式路由傳參 (路徑裏面拼數據)
演示 App.vue 中將數據傳遞給 MyInfo.vue
在路由跳轉時路徑中傳參
<!--演示聲明式路由傳參數
1) 路徑中設置參數
2) 路由映射規則中設置變量承載參數
3) 可以在組件中通過$route.params獲取參數
-->
<router-link to="/info/9527" tag="button">Info信息</router-link> |
在路由表的規則中設變量
在 MyInfo.vue 中接參
使用 this.$route.params.xxx 接收參數
<template>
<div>
<h1>MyInfo</h1>
<p>這是個人信息頁面</p>
<!--獲取路由參數,此處的id是路由映射規則中設置的變量-->
<p>當前路由參數id: {{ this.$route.params.id }}</p>
<p>當前路由參數id: {{ uid }}</p>
<img src="../assets/James.png" alt="詹姆斯高斯林">
</div>
</template>
<script>
export default {
name: "MyInfo",
data() {
return {
uid: this.$route.params.id
}
},
methods: {}
}
</script>
<style scoped>
</style>
16.7.2 編程式路由傳參
演示 App.vue 中將數據傳遞給 Note.vue
App.vue 的編程跳轉 js 中設置要傳遞的數據
methods:{
toNote(){
this.$router.push({
path:"/note",
query: { //通過query攜帶數據,最終url /note?username=老王&password
username:"曹植"
}
})
// 詳情看路由官方文檔説明https://v3.router.vuejs.org/zh/guide/essentials/navigation.html
}
}
Note.vue 中接收參數
<template>
<div>
<h1>網站公告</h1>
<span>username --> {{username}}</span>
</div>
</template>
<script>
export default {
name: "Note",
data:function(){
return {
username:this.$route.query.username
// 注意是query,因為是按照路徑方式發送,注意查看瀏覽器url
}
}
}
</script>
16.7.3 總結兩種傳參方式
16.8 嵌套路由 [重點]
嵌套路由 | Vue Router (vuejs.org)
多層多級組件嵌套時的路由
需求:在個人中心組件中,再設置三個鏈接,可以點擊切換 [頭像 | 家庭信息 | 學校信息]
代碼:
創建三個組件頁面 Touxiang.vue,Family.vue,School.vue
.... 省略過程
在 MyInfo 組件中設置路由鏈接發出請求路徑,並且設置路由填充位
<p>這是個人信息頁面</p>
<hr>
<nav>
<!-- 導航鏈接,設置子路由,
/info/8888 , 是為了匹配路由規則中定義的變量:id
-->
<router-link to="/info/8888/school">學校信息</router-link> |
<router-link to="/info/8888/family">家庭信息</router-link> |
<router-link to="/info/8888/avatar">頭像信息</router-link> |
</nav>
<router-view></router-view>
在 router/index.js 中設置 myinfo 組件的子路由 children
設置路由填充 router-view
如果有路徑中有數據的話,子組件一樣可以取值
16.9 路由重定向 [瞭解]
官網資料: 重定向 | Vue Router (vuejs.org)
16.10 路由守衞 (導航守衞) [重要 | 讀懂作用]
官方資料: 導航守衞 | Vue Router (vuejs.org)
自己理解:很像 java 攔截器,這裏攔截的路由的進程
路由守衞又分為
- 前置路由守衞 router.beforeEach (to,form,next)
- 後置路由守衞 router.afterEach
// 創建VueRouter對象,其中配置路由信息
const router = new VueRouter({...})
// 前置路由守衞,即跳轉頁面前生效,一般都是驗證身份/權限
router.beforeEach((to, from, next) => {
console.log("to,要路由取的目的頁面",to)
console.log("from,從哪個路由出的",from)
// 相當於放行
next()
// 讓這次路由去/login路徑
// next("/login")
})
router.afterEach((to, from) => {
console.log("後置守衞")
})
// 導出該對象
export default router
16.11 路由元信息 [瞭解]
官方資料: 路由元信息 | Vue Router (vuejs.org)
個人理解:路由元信息,就是在路由設置中,定義了一個數據,在路由過程帶上這個數據,做一些邏輯上的處理
定義路由元信息
在路由守衞中取出