十三、idea 開發 vue

idea 中安裝 Vue 插件 (2023 版本已經無需安裝,自帶就有)

vue1與vue2的路由 以及vue2項目大概瞭解_#vue.js

然後使用 idea 打開之前創建的 vue 項目

vue1與vue2的路由 以及vue2項目大概瞭解_Vue_02

啓動項目

vue1與vue2的路由 以及vue2項目大概瞭解_#javascript_03

方案 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 就是自定義的組件


vue1與vue2的路由 以及vue2項目大概瞭解_#前端_04

創建後好,組件內部結構


vue1與vue2的路由 以及vue2項目大概瞭解_Vue_05

正常的寫代碼

<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 中使用

  • 哪裏使用組件,哪裏註冊
  • 註冊完,組件名當標籤用

vue1與vue2的路由 以及vue2項目大概瞭解_#前端_06

注意:

其中./ 是相對路徑,@是從根路徑

// @是從根路徑
import Demo1 from "@/components/Demo1.vue";

// ./ 是相對路徑
import Demo2 from "./components/Demo2.vue";

十五、Vue 組件間的參數傳遞 [熟悉]


15.1 父傳子 [熟悉]

父組件中使用子組件時,在標籤內設置屬性

vue1與vue2的路由 以及vue2項目大概瞭解_#javascript_07

傳遞是數字,布爾值需要 v-bind:【真實麻煩 】

傳遞是變量也需要 v-bind:

子組件中設置 props 接收傳遞過來的數據即可

vue1與vue2的路由 以及vue2項目大概瞭解_Vue_08

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>

執行流程解析

vue1與vue2的路由 以及vue2項目大概瞭解_Vue_09

十六、Vue-router 路由【重點】

16.1 介紹

路由的本質就是一種對應關係,比如説我們在 url 地址中輸入我們要訪問的 url 地址之後,瀏覽器要去請求這個 url 地址對應的資源。

那麼 url 地址和真實的資源之間就有一種對應的關係,就是路由。

vue1與vue2的路由 以及vue2項目大概瞭解_#javascript_10

根據不同的事件來顯示不同的頁面內容

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)

vue1與vue2的路由 以及vue2項目大概瞭解_Vue_11

使用命令:

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>

vue1與vue2的路由 以及vue2項目大概瞭解_#javascript_12

vue1與vue2的路由 以及vue2項目大概瞭解_數據_13

vue1與vue2的路由 以及vue2項目大概瞭解_Vue_14

16.5 演示:聲明式路由 [重點]

需求:新增一個按鈕 / 鏈接,點擊實現切換個人信息頁面

vue1與vue2的路由 以及vue2項目大概瞭解_數據_15

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 頁面中設置聲明式路由

vue1與vue2的路由 以及vue2項目大概瞭解_數據_16

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 // 跳轉到這個組件
        },

    ]

})

vue1與vue2的路由 以及vue2項目大概瞭解_數據_17

注意寫完 route 的 index.js 之後 沒用 一定找到 main.js 將 router 進行掛載

vue1與vue2的路由 以及vue2項目大概瞭解_#前端_18

16.5.4 設置路由填充位 (展現)

App.vue 中設置路由展示位<router-view>

在哪個頁面設置展示位<router-view> , 組件就在哪個頁面展示出來

vue1與vue2的路由 以及vue2項目大概瞭解_Vue_19

16.6 演示:編程式路由 [重點]

剛才演示的是聲明式路由,現在使用編程式路由

演示:公告頁面切換

vue1與vue2的路由 以及vue2項目大概瞭解_#javascript_20

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="">

vue1與vue2的路由 以及vue2項目大概瞭解_#前端_21

  • 這裏寫的是this.$router
  • 不是this.$route !!!!!!

16.6.3 src/router/index.js 設置路由規則

vue1與vue2的路由 以及vue2項目大概瞭解_#前端_22

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> |

在路由表的規則中設變量

vue1與vue2的路由 以及vue2項目大概瞭解_#前端_23

在 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 總結兩種傳參方式

vue1與vue2的路由 以及vue2項目大概瞭解_#前端_24

16.8 嵌套路由 [重點]

嵌套路由 | Vue Router (vuejs.org)

多層多級組件嵌套時的路由

vue1與vue2的路由 以及vue2項目大概瞭解_數據_25

需求:在個人中心組件中,再設置三個鏈接,可以點擊切換 [頭像 | 家庭信息 | 學校信息]

代碼:

創建三個組件頁面 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

vue1與vue2的路由 以及vue2項目大概瞭解_#javascript_26

設置路由填充 router-view

vue1與vue2的路由 以及vue2項目大概瞭解_#javascript_27

如果有路徑中有數據的話,子組件一樣可以取值

16.9 路由重定向 [瞭解]

官網資料: 重定向 | Vue Router (vuejs.org)

vue1與vue2的路由 以及vue2項目大概瞭解_#前端_28

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)

個人理解:路由元信息,就是在路由設置中,定義了一個數據,在路由過程帶上這個數據,做一些邏輯上的處理

定義路由元信息

vue1與vue2的路由 以及vue2項目大概瞭解_Vue_29

在路由守衞中取出

vue1與vue2的路由 以及vue2項目大概瞭解_數據_30