1. 程式人生 > 其它 >計算機組成原理-全套視訊教程

計算機組成原理-全套視訊教程

只是初學vue時做的一些筆記留作記錄,沒什麼內容。

Vue

Vue (讀音 /vjuː/,類似於 view) 是一套用於構建使用者介面的漸進式JavaScript框架。與其它大型框架不同的是,Vue 被設計為可以自底向上逐層應用。Vue 的核心庫只關注檢視層,不僅易於上手,還便於與第三方庫或既有專案整合。另一方面,當與現代化的工具鏈以及各種支援類庫結合使用時,Vue 也完全能夠為複雜的單頁應用(SPA)提供驅動。

官網:Vue.js (vuejs.org)

Soc原則(關注點分離原則)

它只做檢視層HTML+CSS+JS :給使用者看,重新整理後臺給的資料

網路通訊:axios

頁面跳轉:vue-router

狀態管理:vuex

Vue-UI:ICE

前端三要素(簡述)

HTML(結構)+CSS(表現)+Javascript(行為)

HTML

CSS

CSS層疊樣式表是一門標記語言,並不是程式語言,因此不可以自定義變數,不可以引用等,換句話說就是不具備任何語法支援,它主要缺陷如下:

  • 語法不夠強大,比如無法巢狀書寫,導致模組化開發中需要書寫很多重複的選擇器;
  • 沒有變數和合理的樣式複用機制,使得邏輯上相關的屬性值必須以字面量的形式重複輸出,導致難以維護;

這就導致我們在工作中增加了許多工作量,所以前端人員會使用一種【CSS前處理器】來減少冗餘程式碼。提高程式碼的可維護星期,大大提高開發上的效率。

css前處理器

css前處理器定義了一種新的語言,其基本思想是用一種專門的程式語言,為CSS增加一些編碼的特性,將CSS作為目標生成檔案,然後開發者只要使用這種語言進行CSS的編碼工作。簡單來說就是 **"用一種專門的程式語言,進行Web頁面樣式設計,再通過編譯器轉化成正常的CSS檔案,以供專案使用” **。

常用的CSS前處理器有

  • SASS:基於Ruby,通過服務端處理,功能強大。解析效率高。需要學習Ruby語言,上手難度高於LESS。
  • LESS:基於 NodeJS,通過客戶端處理,使用簡單。功能比 SASS簡單,解析效率也低於sASS,但在實際開發中足夠了,所以我們後臺人員如果需要的話,建議使用LESS.

JavaScript

弱型別指令碼語言,目前用的是ES6的規範。

JavaScript框架:

  • jQuery
  • Angular
  • React
  • Vue
  • Axios(前端通訊框架,ajax)

UI框架

  • Ant-Design
  • ElementUI、iview、ice
  • Bootstrap
  • AmazeUI

JavaScript構建工具

  • Babel:js編譯工具
  • WebPack:模組打包器

學習Vue

什麼是MVVM

MVVM (Model-View-ViewModel)是一種軟體架構設計模式,由微軟WPF(用於替代WinForm,以前就是用這個技術開發桌面應用程式的和Silverlight(類似於Java Applet,簡單點說就是在瀏覽器上執行的 WPF)的架構師Ken Cooper和Ted Peters開發,是一種簡化使用者介面的事件驅動程式設計方式

MVVM源自於經典的MVC (Model-View-Controller)模式。MVVM 的核心是ViewModel層,負責轉換 Model中的資料物件來讓資料變得更容易管理和使用,其作用如下:

  • 該層向上與檢視層進行雙向資料繫結
  • 向下與Model層通過介面請求進行資料互動

MVVM模式的實現者

  • Model:模型層,在這裡表示JavaScript物件
  • View:檢視層,在這裡表示DOM(HTML操作的元素)
  • ViweModel:連線檢視和資料的中介軟體,Vue.js就是MVVM模式中的ViewModel的實現者

在MVVM架構中,是不允許資料和檢視直接通訊的,只能通過ViewModel來通訊,而ViewModel就是定義了一個Observer觀察者

  • ViewModel能夠觀察到資料的變化,並對檢視對應的內容進行更新
  • ViewModel能夠監聽到檢視的變化,並能夠通知資料發生改變

至此,我們就明白了Vue.js就是一個MVVM的實現者,他的核心就是實現類DOM監聽與資料繫結。

使用MVVM的好處

MVVM模式和MVC模式一樣,主要目的是分離檢視(View)和模型(Model),有幾大好處

  • 低耦合:檢視(View)可以獨立於Model變化和修改,一個ViewModel可以繫結到不同的View 上,當View變化的時候Model可以不變,當Model變化的時候View 也可以不變。
  • 可複用:你可以把一些檢視邏輯放在一個ViewModel裡面,讓很多View重用這段檢視邏輯。
  • 獨立開發:開發人員可以專注於業務邏輯和資料的開發(ViewModel),設計人員可以專注於頁面設計。
  • 可測試:介面素來是比較難於測試的,而現在測試可以針對ViewModel來寫。

ViewModel層

ViewModel是由前端開發人員組織生成和維護的檢視資料層。在這一層,前端開發者對從後端獲取的 Model資料進行轉換處理,做二次封裝,以生成符合View層使用預期的檢視資料模型。
需要注意的是ViewModel所封裝出來的資料檬型包括檢視的狀態和行為兩部分,而Model層的資料模型是隻包含狀態的

  • 比如頁面的這一塊展示什麼,那一塊展示什麼這些都屬於檢視狀態(展示)

  • 頁面載入進來時發生什麼,點選這一塊發生什麼,這一塊滾動時發生什麼這些都屬於檢視行為(互動)

檢視狀態和行為都封裝在了ViewModel裡。這樣的封裝使得ViewModel可以完整地去描述View層。
由於實現了雙向繫結,ViewModel的內容會實時展現在View層,這是激動人心的,因為前端開發者再也不必低效又麻煩地通過操縱DOM去更新檢視。
MVVM框架已經把最髒最累的一塊做好了,我們開發者只需要處理和維護ViewModel,更新資料檢視就會自動得到相應更新,真正實現事件驅動程式設計。
View層展現的不是 Model層的資料,而是 viewNodel的資料,由viewModel負責與 Model層互動,這就完全解耦了View層和 Model層,這個解耦是至關重要的,它是前後端分離方案實施的重要一環

第一個vue程式

我們的開發工具,一般vscode比較多,這裡我們使用idea,新建一個vue的資料夾,然後使用idea開啟,給我們的idea安上vue的外掛

(這裡安裝後可能會出現,新建時還是沒有Vue Component的情況,請見這個顯示Vue Component

下載地址

 <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
 <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>

這裡我們開發只要匯入CDN的第二個就行

創建出一個html的檔案

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--view層 模板-->
<div id="app">
    {{message}}
</div>
<!--匯入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js" ></script>
<script>
    var vm = new Vue({
        el:"#app",
        //Model:資料
        data:{
            message:"hello vue!"
        }
    })
</script>
</body>
</html>

之後在瀏覽器開啟

其中我們展示的div就是view,data就是我們的model,再來感受下其中的VM,右鍵出控制檯,輸入,vm.message="某某" ,回車,我們馬上就可以看到我們的檢視上進行了同步的更新,這就是我們的雙向資料繫結。

這裡可能不太好理解,我們平時修改網頁之後必須重新整理之後才能顯示出我們修改後的樣子,而這裡我們是動態重新整理的,不需要重新載入介面,只要修改model中的資料後,通過我們的ViewModel之後可以動態的更新我們View中資料。

這裡還可以使用vue中的 v-bind 標籤來繫結元素

<div id="app">
    <span v-bind:title="message">滑鼠懸浮我</span>
</div>
<!--匯入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js" ></script>
<script>
    var vm = new Vue({
        el:"#app",
        //Model:資料
        data:{
            message:"hello vue!"
        }
    })
</script>

這樣滑鼠懸浮在字型上是同樣也會出現我們的message

你看到的v-bind 等被稱為指令。指令帶有字首v-,以表示它們是Vue提供的特殊特性。可能你已經猜到了,它們會在渲染的DOM上應用特殊的響應式行為。在這裡,該指令的意思是:“將這個元素節點的title特性和Vue 例項的message屬性保持一致”。

v-if 、v-else

直接看下程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--view層 模板-->
<div id="app">
    <h1 v-if="ok">Yes</h1>
    <h1 v-else>No</h1>
</div>
<!--匯入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js" ></script>
<script>
    var vm = new Vue({
        el:"#app",
        //Model:資料
        data:{
            ok: true
        }
    })
</script>
</body>
</html>

我們同樣在控制檯進行呼叫來試試

還有v-else-if

<div id="app">
    <h1 v-if="type==='A'">A</h1>
    <h1 v-else-if="type==='B'">B</h1>
    <h1 v-else-if="type==='C'">C</h1>
    <h1 v-else="type==='D'">D</h1>
</div>
<!--匯入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js" ></script>
<script>
    var vm = new Vue({
        el:"#app",
        //Model:資料
        data:{
            type: 'A'
        }
    })
</script>

同樣可以在控制檯修改試試(注意這裡的===是指全等於,包括資料的型別也要相等)

v-for

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--view層 模板-->
<div id="app">
    <li v-for="(item,index) in items">
        {{item.message}}
    </li>
</div>
<!--匯入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js" ></script>
<script>
    var vm = new Vue({
        el:"#app",
        //Model:資料
        data:{
            items:[
                {message:"大家好"},
                {message: "你好"},
                {message: "我不好"}
            ]
        }
    });
</script>
</body>
</html>

事件處理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
<button v-on:click="sayHi">click</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js" ></script>
<script>
    var vm = new Vue({
        el:"#app",
        data:{
            message:"hello boy"
        },
        methods:{ //方法必須定義在Vue的method中,
            sayHi:function (){
                alert(this.message);
            }
        }
    })
</script>
</body>
</html>


Vue雙向資料繫結

什麼是雙向資料繫結

Vue.js 是一個MVVM框架,即資料雙向繫結,即當資料發生變化的時候,檢視也就發生變化,當檢視發生變化的時候,資料也會跟著同步變化。這也算是Vue.js 的精髓之處了。
值得注意的是,我們所說的資料雙向繫結,一定是對於UI控制元件來說的,非UI控制元件不會涉及到資料雙向繫結。單向資料繫結是使用狀態管理工具的前提。如果我們使用vuex,那麼資料流也是單項的,這時就會和雙向資料繫結有衝突。

在表單中使用雙向資料繫結

你可以用v-model指令在表單<input> , <textarea>及<select>元素上建立雙向資料繫結。它會根據控制元件型別自動選取正確的方法來更新元素。儘管有些神奇,但v-model本質上不過是語法糖。它負責監聽使用者的輸入事件以更新資料,並對一些極端場景進行一些特殊處理。
注意: v-model 會忽略所有表單元素的value、checked、selected 特性的初始值而總是將Vue例項的資料作為資料來源。你應該通過JavaScript在元件的data選項中宣告初始值!

現在我們嘗試完成我們在某處增添內容,在另一處也實時的展示我們的資料的一個案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    輸入的文字:<input type="text" v-model="message">{{message}}
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js" ></script>
<script>
    var vm = new Vue({
        el:"#app",
        data:{
            message: "123"
        }
    })
</script>
</body>
</html>

之後我們在控制檯上呼叫vm中的message的值或者直接在文字框中輸入值,都可以同時改變兩個地方的值。

關於單複選框

<div id="app">
    選擇性別:<input type="radio" name="sex" value="男" v-model="hi">男
            <input type="radio" name="sex" value="女" v-model="hi">女
    <p>選中了:{{hi}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js" ></script>
<script>
    var vm = new Vue({
        el:"#app",
        data:{
            hi: ''
        }
    })
</script>

關於下拉框

<div id="app">
    選擇:<select v-model="selected">
            <option disabled value="">請選擇</option>
            <option>A</option>
            <option>B</option>
            <option>C</option>
        </select>
    <p>選中了:{{selected}}</p>
</div>
<script>
    var vm = new Vue({
        el:"#app",
        data:{
            selected: ''
        }
    })
</script>

這個內容也就會跟著我們的所選的內容自動的改變

注意:如果v-model表示式的初始值未能匹配任何選項,<select>元素將被渲染為“未選中”狀態。在 iOS 中,這會使使用者無法選擇第一個選項。因為這樣的情況下,iOS不會觸發change事件。因此,更推薦像上面這樣提供一個值為空的禁用選項。

Vue元件

自定義標籤

    <div id="app">
        <qingzheng></qingzheng>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
    <script>
        //定義了一個名叫qingzheng的標籤
        Vue.component("qingzheng",{
            template:'<li>Hello</li>'
        });
        var vm = new Vue({
            el:"#app",
            data:{
            }
        })
    </script>

這裡我們只是寫了一個我們自己定義的標籤,就可以把我們自己所定義的元件放到頁面之中,元件就一個模板的意思

這裡我們右鍵新建一個Vue的檔案a.vue

<template>

</template>

<script>
export default {
  name: "a.vue"
}
</script>

<style scoped>

</style>

這是一個剛創建出來的vue的基本格式,其中最上面的<template>就是我們的模板的意思,其實就是我們的元件

那之後,我們可能就會發現,我們的前端專案只需要一個標籤就完成了,當然像其中的Hello的資料就要我們另外傳遞進去

    <div id="app">
        <!--元件:傳遞元件中的值:props-->
        <qingzheng v-for="item in items" v-bind:item1="item"></qingzheng>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
    <script>
        //定義了一個名叫qingzheng的標籤
        Vue.component("qingzheng",{
            props: ['item1'], //這裡必須通過props這個引數來接收我們的item,不用它是無法接收外面的引數的
            template:'<li>{{item1}}</li>'
        });
        var vm = new Vue({
            el:"#app",
            data:{
                items :["java","Linux","web"]
            }
        })
    </script>

網路通訊Axios

什麼是Axios

Axios是一個開源的可以用在瀏覽器端和Node”s的非同步通訊框架,它的主要作用就是實現 AJAX非同步通訊,其功能特點如下:

  • 從瀏覽器中建立XMLHttpRequests

  • 從node.js 建立http請求

  • 支援Promise APl[JS中鏈式程式設計]

  • 攔截請求和響應

  • 轉換請求資料和響應資料

  • 取消請求

  • 自動轉換JSON 資料

  • 客戶端支援防禦XSRF(跨站請求偽造)

GitHub :https://github.com/axios/axios

中文文件 :http://www.axios-js.com/

Vue的生命週期

Vue例項有一個完整的生命週期,也就是從開始建立、初始化資料、編譯模板、掛載DOM、渲染→更新→渲染、解除安裝等一系列過程,我們稱這是Vue的生命週期。通俗說就是Vue例項從建立到銷燬的過程,就是生命週期。

在頁面載入的時候他是先載入模板再載入資料進行渲染,如果我們的網速夠慢的話就可以看到這個過程,在這個過程中,我們可以在某個地方進行插入鉤子函式,完成我們要做的事

我們新建一個json檔案

{
  "name": "java",
  "url": "http://baidu.com",
  "page": 1,
  "isNonProfit":true,
  "address": {
    "street": "創業路",
    "city":"福建福州",
    "country": "中國"
  },
  "links": [
    {
      "name": "B站",
      "url": "https://www.bilibili.com/"
    },
    {
      "name": "4399",
      "url": "https://www.4399.com/"
    },
    {
      "name": "百度",
      "url": "https://www.baidu.com/"
    }
  ]
}

完成一個案例

<div id="vue">
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    var vm = new Vue({
        el:"#vue",
        mounted(){ //鉤子函式,鏈式程式設計 ES6
          axios.get('data.json').then(response=>(console.log(response.data)));
        }
    })
</script>

我們在控制檯可以看到他是可以取到其中的資料的

可以看到這也是非同步的請求,和Ajax沒什麼差別

這裡就是通過axios.get呼叫一個介面,然後獲得結果後,使用response來控制我們取得的資料,現在我們想將其在介面上渲染出來,我們就要將其返回到data中,

<div id="vue">
    <div>{{info.address.city}}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    var vm = new Vue({
        el:"#vue",
        data(){
          return{ //在這裡返回到data中
              //請求的返回引數合適,必須和json字串一樣
              info:{ //可以為null,但不能寫錯
                  name:null,
                  address:{
                      street:null,
                      city:null,
                      country:null
                  }
              }
          }
        },
        mounted(){ //鉤子函式,鏈式程式設計
          axios.get('data.json').then(response=>(this.info=response.data));
        }
    })
</script>

這裡還有一個閃爍的問題,就是可能會出現模板一閃而過的情況,這裡我們使用v-clock

    <style>
        [v-clock]{
            display: none;
        }
    </style>
</head>
<body>
<div id="vue" v-clock>
    <div>{{info.address.city}}</div>
</div>

如果我們要用a標籤取url,可以<a v-bind:href="info.url">百度</a>

計算屬性

計算屬性的重點突出在屬性兩個字上(屬性是名詞),首先它是個屬性其次這個屬性有計算的能力(計算是動詞),這裡的計算就是個函式;簡單點說,它就是一個能夠將計算結果快取起來的屬性(將行為轉化成了靜態的屬性),僅此而已;可以想象為快取!

我們這裡用個案例說下它這個快取

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <p>currentTime1 {{currentTime1()}}</p>
    <p>currentTime2 {{currentTime2}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js" ></script>
<script>
    var vm = new Vue({
        el:"#app",
        data:{
            message:"hello boy"
        },
        methods:{
            currentTime1:function(){
                return Date.now(); //返回一個時間戳
            }
        },
        computed:{ //計算屬性:methods,computed方法名不能重名,重名之後,只會呼叫methods中的方法
            currentTime2:function(){
                return Date.now(); //返回一個時間戳
            }
        }
    })
</script>
</body>
</html>

注意這裡的兩者的呼叫不同,methods中是呼叫方法,computed中是呼叫屬性,

我們可以看到我們每次呼叫time1的值都是在變化的,time2的值都是不變的,這是因為,此時的time2被快取起來了,已經是一個屬性值

  • methods:定義方法,呼叫方法使用currentTime1(),需要帶括號
  • computed:定義計算屬性,呼叫屬性使用currentTime2,不需要帶括號; this.message是為了能夠讓currentTime2觀察到資料變化而變化
  • 如何在方法中的值發生了變化,則快取就會重新整理!可以在控制檯使用vm.message="XXX" ,改變下資料的值,再次測試觀察效果!

結論:
呼叫方法時,每次都需要進行計算,既然有計算過程則必定產生系統開銷,那如果這個結果是不經常變化的呢?此時就可以考慮將這個結果快取起來,採用計算屬性可以很方便的做到這一點,計算屬性的主要特性就是為了將不經常變化的計算結果進行快取,以節約我們的系統開銷。

內容分發

在vue.js中我們使用<slot>元素作為承載分發內容的出口,作者稱其為插槽,可以應用在組合元件的場景中。仔細看下這個

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

<div id="app">
    <todo>
        <todo-title slot="todo-title" :title="title"></todo-title>
        <todo-items slot="todo-items" v-for="item in todoItems" :item="item"></todo-items>
    </todo>
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js" ></script>
<script>
    //slot:插槽
    Vue.component('todo',{
        template: '<div>\
                    <slot name="todo-title"></slot>\
                    <ul>\
                        <slot name="todo-items"></slot>\
                    </ul>\
                    </div>'
    });
    Vue.component("todo-title",{
        props:['title'],
        template: '<div>{{title}}</div>'
    });
    Vue.component("todo-items",{
        props:['item'],
        template: '<li>{{item}}</li>'
    });
    var vm = new Vue({
        el:"#app",
        data: {
            title: "語言列表",
            todoItems:['C++','Java','C','Go']
        }
    })
</script>
</body>
</html>

注意看整體的繫結流程,其中slot中通過name來繫結元件,slot感覺就是把元件組合起來,可以把某個自定義的元件插入到整體元件的某個地方,在整體元件的模板中設定插槽,在檢視層使用元件插槽的時候,要宣告使用所放置的slot,slot="todo-title" 注意這的:title="title"這個是v-bind的簡寫形式,v-on的簡寫是@。首先載入整個元件的模板,然後載入元件中的插槽,將插槽繫結上其他的元件,組合成一個整體的模板,之後把資料調出來,進行渲染。

自定義事件

現在我們要實現增加按鈕,點選後動態刪除列表中的某一項,Vue為我們提供了自定義事件的功能很好的幫助我們解決了這個問題;使用this.$emit('自定義事件名',引數)。

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

<div id="app">
    <todo>
        <todo-title slot="todo-title" :title="title"></todo-title>
        <todo-items slot="todo-items" v-for="(item,index) in todoItems" :item="item" :index="index"
                    v-on:remove="removeItems(index)" :key="index"></todo-items>
    </todo>
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js" ></script>
<script>
    //slot:插槽
    Vue.component('todo',{
        template: '<div>\
                    <slot name="todo-title"></slot>\
                    <ul>\
                        <slot name="todo-items"></slot>\
                    </ul>\
                    </div>'
    });
    Vue.component("todo-title",{
        props:['title'],
        template: '<div>{{title}}</div>'
    });
    Vue.component("todo-items",{
        props:['item','index'],
        //這個按鈕只能綁定當前元件裡的方法
        template: '<li>{{index}}--{{item}}<button @click="remove">刪除</button></li>',
        methods: {
            remove:function (index){
                //this.$emit() 自定義事件
                this.$emit('remove',index);
            }
        }
    });
    var vm = new Vue({
        el:"#app",
        data: {
            title: "語言列表",
            todoItems:['C++','Java','C','Go']
        },
        methods:{
            removeItems:function (index){
                console.log("刪除了"+this.todoItems[index]+"ok");
                this.todoItems.splice(index,1);//一次刪除一個元素
            }
        }
    })
</script>
</body>
</html>

看下這個圖來了解它,綁來綁去(暈

到這裡我們可以建立Vue的單頁面的應用了

入門小結

核心:資料驅動,元件化

優點:借鑑了AngulaJS的模組化開發和React的虛擬Dom,虛擬Dom就是把Dom操作放到記憶體中執行;

常用的屬性:

  • v-if
  • v-else-if
  • v-for
  • v-on 繫結事件,簡寫@
  • v-model 資料雙向繫結
  • v-bind給元件繫結引數,簡寫:

元件化

  • 組合元件slot插槽
  • 元件內部繫結事件需要使用到this.$emit("事件名",引數)
  • 計算屬性的特色,快取計算資料

遵循SoC關注度分離原則,Vue是純粹的檢視框架,並不包含,比如Ajax之類的通訊功能,為了解決通訊問題,我們需要使用Axios框架做非同步通訊;

Vue的開發都是要基於NodeJS,實際開發採用vue-cli腳手架開發,vue-router路由,vuex做狀態管理; Vue Ul,介面我們一般使用ElementUI(餓了麼出品),或者ICE(阿里巴巴出品!)來快速搭建前端專案

官網:

第一個vue-cli程式

什麼是vue-cli

vue-cli官方提供的一個腳手架,用於快速生成一個vue的專案模板;
預先定義好的目錄結構及基礎程式碼,就好比咱們在建立 Maven專案時可以選擇建立一個骨架專案,這個骨架專案就是腳手架,我們的開發更加的快速;

主要的功能:

  • 統一的目錄結構
  • 本地除錯
  • 熱部署
  • 單元測試
  • 整合打包上線

環境

自行安裝Node.js :http://nodejs.cn/download 和Git:https://git-scm/downloads

確認其安裝成功

可以安裝node.js淘寶映象加速器(cnpm)

#-g就是全域性安裝
npm install cnpm -g
#或使用如下語句解決npm速度慢的問題
npm install --registry=https://registry.npm.taobao.org

安裝vue-cli

cnpm install vue-cli -g
#測試是否安裝成功
#檢視可以基於哪些模板建立vue應用程式,通常我們選擇webpack
vue list

建立Vue程式

命令列到我們要建立專案的目錄後使用命令vue init webpack myvue 用webpack模板初始化一個名為myvue的專案

前面幾個直接預設回車,Vue Build選第一個,之後的都選NO就行

這樣我們的Vue專案是建立好了

說明:

  • Project name:專案名稱,預設回車即可
  • Project description:專案描述,預設回車即可· Author:專案作者,預設回車即可
  • lnstall vue-router:是否安裝 vue-router,選擇n不安裝(後期需要再手動新增)
  • Use ESLint to lint your code:是否使用ESLint做程式碼檢查,選擇n不安裝(後期需要再手動新增)
  • Set up unit tests:單元測試相關,選擇n不安裝(後期需要再手動新增)
  • Setup e2e tests with Nightwatch:單元測試相關,選擇n不安裝(後期需要再手動新增)
  • Should we run npm install for you after the,project has been created:建立完成後直接初始化,選擇n,我們手動執行;執行結果

初始化並執行

cd myvue
npm install  #安裝專案的所以依賴,執行完後我們的node_modules中就會增加很多的東西
npm run dev

我們執行完 npm install後就會多出一個node_modules這個目錄,我們可以將其類似的看成java專案中的maven ,其中的package.json檔案相當於java專案中的pom.xml檔案

我們通過在命令列使用npm run dev來啟動我們的專案,將執行在我們的8080埠

我們就可以在瀏覽器中進入localhost:8080

我們在idea中開啟此專案

我們也可以直接在idea中啟動我們的專案(如果不行可能是因為需要管理員許可權)

啟動之後都是使用Ctrl+C結束的

我們可以看到整個專案的入口是main.js它就是和最外面的index.html繫結在一起

Ctrl點選那個App就可以點進去看元件具體的內容

這是我們的index.html的主頁面,我們開發過程中不需要去動它。

WebPack

什麼是webpack

本質上,webpack 是一個現代JavaScript應用程式的靜態模組打包器(module bundler)。當webpack處理應用程式時,它會遞迴地構建一個依賴關係圖(dependency graph),其中包含應用程式需要的每個模組,然後將所有這些模組打包成一個或多個bundle.
Webpack 是當下最熱門的前端資源模組化管理和打包工具,它可以將許多鬆散耦合的模組按照依賴和規則打包成符合生產環境部署的前端資源。還可以將按需載入的模組進行程式碼分離,等到實際需要時再非同步載入。通過loader轉換,任何形式的資源都可以當做模組,比如CommonsJS、AMD、ES6、css、JSON、CoffeeScript、LESS等;
伴隨著移動網際網路的大潮,當今越來越多的網站已經從網頁模式進化到了WebApp模式。它們執行在現代瀏覽器裡,使用HTML5、CSS3、ES6等新的技術來開發豐富的功能,網頁已經不僅僅是完成瀏覽器的基本需求; WebApp通常是一個SPA (單頁面應用),每一個檢視通過非同步的方式載入,這導致頁面初始化和使用過程中會載入越來越多的JS程式碼,這給前端的開發流程和資源組織帶來了巨大挑戰。
前端開發和其他開發工作的主要區別,首先是前端基於多語言、多層次的編碼和組織工作,其次前端產品的交付是基於瀏覽器的,這些資源是通過增量載入的方式執行到瀏覽器端,如何在開發環境組織好這些碎片化的程式碼和資源,並且保證他們在瀏覽器端快速、優雅的載入和更新,就需要一個模組化系統,這個理想中的模組化系統是前端工程師多年來一直探索的難題。

模組化的演進

Script

<script src="module1.js"></script>
<script src="module2.js"></script>
<script src="module3.js"></script>

這是最原始的JavaScript檔案載入方式,如果把每一個檔案看做是一個模組,那麼他們的介面通常是暴露在全域性作用域下,也就是定義在 window物件中,不同模組的呼叫都是一個作用域。
這種原始的載入方式暴露了一些顯而易見的弊端:

  • 全域性作用域下容易造成變數衝突
  • 檔案只能按照<script>的書寫順序進行載入·開發人員必須主觀解決模組和程式碼庫的依賴關係
  • 在大型專案中各種資源難以管理,長期積累的問題導致程式碼庫混亂不堪

CommonJS

伺服器端的NodeJS遵循CommonsJS規範,該規範核心思想是允許模組通過require方法來同步載入所需依賴的其它模組,然後通過exports或 module.exports 來匯出需要暴露的介面。

require("module");
require("../module.js");
export .doStuff = function() {};
module.exports = someValue;

優點:

  • 伺服器端模組便於重用
  • NPM中已經有超過45萬個可以使用的模組包
  • 簡單易用

缺點:

  • 同步的模組載入方式不適合在瀏覽器環境中,同步意味著阻塞載入,瀏覽器資源是非同步載入的
  • 不能非阻塞的並行載入多個模組

實現

  • 服務端的NodeJS
  • Browserify,瀏覽器端的CommonsJS實現,可以使用NPM的模組,但是編譯打包後的檔案體積較大
  • modules-webmake,類似Browserify,但不如 Browserify靈活
  • wreq,Browserify的前身

AMD

Asynchronous Module Definition規範其實主要一個主要介面define(id?,dependencies?, factory);它要在宣告模組的時候指定所有的依賴dependencies,並且還要當做形參傳到 factory中,對於依賴的模組提前執行。

define("module",[ "dep1","dep2"],function(d1,d2)freturn someExportedvalue;});
require(["module", "../file.js"],function(module, file {});

優點

  • 適合在瀏覽器環境中非同步載入模組

  • 可以並行載入多個模組

缺點

  • 提高了開發成本,程式碼的閱讀和書寫比較困難,模組定義方式的語義不暢
  • 不符合通用的模組化思維方式,是一種妥協的實現

實現

  • RequireJs
  • curl

CMD

Commons Module Definition規範和AMD很相似,儘量保持簡單,並與CommonsJS和NodeJS的 Modules規範保持了很大的相容性。

優點

  • 依賴就近,延遲執行
  • 可以很容易在NodeJS中執行

缺點

  • 依賴SPM打包,模組的載入邏輯偏重

實現

  • Sea.js
  • coolie

ES6模組

EcmaScript6標準增加了JavaScript語言層面的模組體系定義。ES6模組的設計思想,是儘量靜態化,使編譯時就能確定模組的依賴關係,以及輸入和輸出的變數。CommonsJS和AMD模組,都只能在執行時確定這些東西。

import "jquery";
export function doStuff(){}
module "localModule" {}

優點

  • 容易進行靜態分析
  • 面向未來的EcmaScript標準

缺點

  • 原生瀏覽器端還沒有實現該標準
  • 全新的命令,新版的NodeJS才支援

實現

  • Babel

安裝Webpack

WebPack 是一款模組載入器兼打包工具,它能把各種資源,如JS、JSX、ES6、SASS、LESS.圖片等都作為模組來處理和使用。將ES6規範的程式碼打包成ES5規範的程式碼,然後所有瀏覽器都能執行。

npm install webpack -g
npm install webpack-cli -g

測試安裝成功,可以使用這個命令

webpack -v

webpack-cli -v

配置

建立webpack.config-js配置檔案

  • entry:入口檔案,指定WebPack 用哪個檔案作為專案的入口
  • output:輸出,指定WebPack把處理完成的檔案放置到指定路徑
  • module:模組,用於處理各種型別的檔案
  • plugins:外掛,如:熱更新、程式碼重用等resolve:設定路徑指向
  • watch:監聽,用於設定檔案改動後直接打包
module.exports = {
	entry:"",
	output: {
		path:"",
        filename:"",
    },
	module: {
		loaders : [
            {test: /\.js$/, loader: ""}
        ]
    },
	plugins: {},
    resolve: {},
 	watch: true   
}

使用webpack

1.建立專案
2.建立一個名為modules的目錄,用於放置JS模組等資原始檔
3.在modules下建立模組檔案,如hello.js,用於編寫JS模組相關程式碼

//暴露一個方法
exports.sayHi = function () {
    document.write("<h1>Hello world</h1>");
};

4.在modules下建立一個名為main.js的入口檔案,用於打包時設定entry 屬性

//require匯入一個模組,就可以呼叫這個模組中的方法了
var hello = require("./hello"); //匯入進來(java中的導包)
hello.sayHi(); //可以直接呼叫到其中的方法,模組化開發

5.在專案目錄下建立webpack.config.js 配置檔案,使用webpack命令打包

module.exports = {
    entry: "./modules/main.js",
    output: {
        filename:"./js/bundle.js" //一般規範的就是輸出到這裡
    }
};

之後我們的專案就會多出我們輸出的檔案

打包成功後,我們引入,我們新建一個index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <!--前端的模組化開發-->
    <script src="dist/js/bundle.js"></script>
</body>
</html>

在瀏覽器中開啟它就可以看到我們寫的內容

還可以使用webpack --watch命令來一直監聽我們的操作。

Vue-router路由

Vue Router是 Vue.js官方的路由管理。它和Vue.js 的核心深度整合,讓構建單頁面應用變得易如反掌。包含的功能有:

  • 巢狀的路由/視圖表
  • 模組化的、基於元件的路由配置
  • 路由引數.查詢、萬用字元
  • 基於Vue.js 過渡系統的檢視過渡效果
  • 細粒度的導航控制
  • 帶有自動啟用的Css class的連結
  • HTML5歷史模式或 hash模式,在IE9中自動降級
  • 自定義的滾動條行為

安裝

基於第一個vue-cli進行測試學習;先檢視node_modules中是否存在vue-router

vue-router是一個外掛包,所以我們還是需要用npm/cnpm來進行安裝的。開啟命令列工具,進入你的專案目錄,輸入下面命令。
npm install vue-router --save-dev
如果在一個模組化工程中使用它,必須要通過 Vue.use()明確地安裝路由功能:

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter);

我們將我們之前那個第一個vur-cli的程式中刪除一些檔案,使其到一個初始工程的樣子

其中App.vue

<template>
  <div id="app">

  </div>
</template>

<script>

export default {
  name: 'App'
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

其中main.js

import Vue from 'vue'
import App from './App'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  components: { App },
  template: '<App/>'
})

都刪到剩這些就夠了

接下來安裝vue-router npm install vue-router --save-dev

使用

我們可以直接在main.js中將其匯入使用

import Vue from 'vue'
import App from './App'
import VueRouter from 'vue-router'

Vue.config.productionTip = false

//顯示宣告使用VueRouter
Vue.use("VueRouter");

new Vue({
  el: '#app',
  components: { App },
  template: '<App/>'
})

我們執行專案,npm run dev 之後到localhost:8080 就可以看到我們的主頁,這時我們的主頁啥也沒有,但只要我們在App.vue中加上東西,他就能馬上部署上去,這也叫熱部署。

我們這裡來試著開發我們自己的元件Content.vue,其中簡要寫些內容

<template>
  <h1>內容頁</h1>
</template>

<script>
export default {
  name: "Content.vue"
}
</script>

<style scoped>

</style>

再來一個Main.vue

<template>
  <h1>首頁</h1>
</template>

<script>
export default {
  name: "Main.vue"
}
</script>

<style scoped>

</style>

我們新建一個router的目錄,其中新建一個index.js檔案,這是他的主配置檔案

import Vue from 'vue'
import VueRouter from 'vue-router'

import Content from "../components/Content"
import Main from "../components/Main"

//安裝路由
Vue.use(VueRouter);
//配置匯出路由
export default new VueRouter({
  routes:[
    {
      //路由路徑
      path:'/content',
      name: 'content',
      component: Content
    },
    {
      //路由路徑
      path:'/main',
      name: 'main',
      component: Main
    }
  ]
});

然後就是我們的main.js中加上路由配置(這裡匯入配置就不需要匯入路由了)

import Vue from 'vue'
import App from './App'
import router from './router' //自動掃描其中的路由配置

Vue.config.productionTip = false

new Vue({
  el: '#app',
  //配置路由
  router,
  components: { App },
  template: '<App/>'
})

最後就可以在App.vue中直接使用了

<template>
  <div id="app">
    <h1>Vue-Router</h1>
    <router-link to="/main">首頁</router-link>
    <router-link to="/content">內容頁</router-link>
    <router-view></router-view>
  </div>
</template>

<script>

export default {
  name: 'App'
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

其中router-link來控制路由的跳轉,相當於a標籤,router-view來控制顯示,就是將跳轉後的內容顯示出來。

啟動後

點選首頁和點選內容頁,就會分別展示其元件中的內容

我們分析下整個流程,建立自己的元件,然後加入的路由的配置檔案router/index.js中在其中配置其元件的路徑等資訊,然後在main.js中配置路由,之後就可以在App.vue中直接通過router-linkrouter-view來使用我們的各個元件,有點像servlet。

我們之後要新增元件的話,只需要建立自己的元件,然後在路由的配置檔案中加入並配置好路徑等資訊,即可在App.vue等地方使用它。

ElementUI

Element 餓了麼前端出品的一套 基於 Vue 2.0 的桌面端元件庫

官網: Element - 網站快速成型工具

例項

使用vue init webpack hello-vue 使用vue初始化建立一個叫hello-vue的webpack專案。

這樣一個初始化專案就好了。

#進入工程目錄
cd hello-vue
#安裝vue-router
npm install vue-router --save-dev
#安裝element- ui
npm i element-ui -S
#安裝依賴
npm instal1
#安裝SASS載入器
cnpm install sass-loader node-sass --save-dev
#啟動測試
npm run dev

Npm命令解釋:
npm install moduleName :安裝模組到專案目錄下
npm install -g moduleName : -g 的意思是將模組安裝到全域性,具體安裝到磁碟哪個位置,要看npm config prefix的位置
npm install -save moduleName : --save 的意思是將模組安裝到專案目錄下,並在package 檔案的dependencies節點寫入依賴,-S為該命令的縮寫
npm install -save-dev moduleName :--save-dev的意思是將模組安裝到專案目錄下,並在 package檔案的 devDependencies節點寫入依賴,-D為該命令的縮寫

我們啟動測試成功顯示預設vue主頁,就可以將其匯入idea了

匯入idea後,和之前一樣刪掉不用的東西,src/assets/logo.pngsrc/component/HelloWorld.vue以及App.vue中的一些內容。

其中在src下新建views和router資料夾,靜態資源都放在最外面的static資料夾中,views一般放檢視元件,components一般放一些功能元件,router中就是放路由的。

在views中創建出Main.vue

<template>
  <h1>首頁</h1>
</template>

<script>
export default {
  name: "Main.vue"
}
</script>

<style scoped>

</style>

建立一個登陸的元件Login.vue

<template>
  <div>
  <el-form ref="loginForm" :model="form" :rules="rules" label-width="80px" class="login-box">
    <h3 class="login-title">歡迎登入</h3>
    <el-form-item label=賬號" prop="username">
      <el-input type="text" placeholder="請輸入賬號" v-model="form.username"/>
    </el-form-item>
    <el-form-item label="密碼" prop="password">
      <el-input type="password" placeholder="請輸入密碼"v-model="form.password" />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" v-on:click="onSubmit('loginForm')">登入</el-button>
    </el-form-item>
  </el-form>Ⅰ
  <el-dialog
      title="溫馨提示"
      :visible.sync="dialogVisible"
      width="30%"
      :before-close="handleClose">
      <span>請輸入賬號和密碼</span>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="dialogVisible = false">確 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
  export default {
    name: "Login",
    data() {
      return {
        form: {
          username: '',
          password: ''
        },

        //表單驗證。需要在el-form-item元素中增加 prop屬性
        rules: {
          username: [
            {required: true, message: "賬號不可為空", trigger: 'blur'}
          ],
          password: [
            {required: true, message: "密碼不可為空", trigger: 'blur'}
          ]
        },

        //對話方塊顯示和隱藏
        dialogVisible: false
      }
    },
    methods: {
      onSubmit(formName) {
        //為表單繫結驗證功能
        this.$refs[formName].validate((valid) => {
          if (valid) {
            //使用vue-router路由到指定頁面,該方式稱之為程式設計式導航
            this.$router.push("/main");
          } else {
            this.dialogVisible = true;
            return false;
          }
        });
      }
    }
  }
</script>

<style lang="scss" scoped>
  .login-box{
    border: 1px solid #DCDFE6;
    width: 350px;
    margin: 180px auto;
    padding: 35px 35px 15px 35px;
    border-radius: 5px;
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    box-shadow:0 0 25px #909399;
  }
  .login-title {
    text-align: center;
    margin:0 auto 40px auto;
    color: #303133;
  }
</style>

在router資料夾下新建一個index.js,在這裡面進行路由的配置

import Vue from 'vue'
import Router from 'vue-router'

import Main from '../views/Main'
import Login from "../views/Login";

Vue.use(Router);

export default new Router({
  routes:[
    {
      path: '/main',
      component: Main
    },{
      path: '/login',
      component: Login
    }
  ]
});

然後就是在main.js中的配置

import Vue from 'vue'
import App from './App'

import router from './router'
//匯入element的東西
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(router);
Vue.use(ElementUI);

new Vue({
  el: '#app',
  router,
  render: h => h(App) //ElementUI
});

之後就是App.vue中的內容

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>

export default {
  name: 'App'
}
</script>

之後在命令列中執行npm run dev啟動 ,可能會發生如下的報錯

這是因為我們的sass-loader的版本太高了,這個我們可以將package.json中的sass-loader的版本調低一點(比如),然後再執行一下npm install (可能還會出現其他版本問題)

Login.vue會報錯的原因可能是最下面的style標籤加上了lang=scss,解決辦法:
1.去掉lang="scss",(我用的這個。。)
2.版本不相容問題,可以降低版本,注意:降低版本之後會遇到其他版本也需要降低的問題,然後繼續降低版本,,,

之後到 http://localhost:8080/#/login 就可以看到我們使用ElementUI做的登陸介面。

任意輸入內容,點選登陸即可跳轉到我們的/main的首頁。

路由巢狀

巢狀路由又稱子路由,在實際應用中,通常由多層巢狀的元件組合而成,URL中各段動態路徑也按某種結構對應巢狀的各層元件。

例項

在views中新建一個user目錄,其中新建一個元件Profile.vue

<template>
  <h1>個人資訊</h1>
</template>

<script>
  export default {
    name: "UserProfile"
  }
</script>

<style scoped>

</style>

和一個List.vue

<template>
  <h1>使用者列表</h1>
</template>

<script>
  export default {
    name: "UserList"
  }
</script>

<style scoped>

</style>

建立完善好Main.vue

<template>
  <div>
    <el-container>
      <el-aside width="200px">
        <el-menu :default-openeds="['1']">
          <el-submenu index="1">
            <template slot="title"><i class="el-icon-caret-right"></i>使用者管理</template>
            <el-menu-item-group>
              <el-menu-item index="1-1">
                <router-link to="/user/profile">個人資訊</router-link>
              </el-menu-item>
              <el-menu-item index="1-2">
                <router-link to="/user/list">使用者列表</router-link>
              </el-menu-item>
            </el-menu-item-group>
          </el-submenu>
          <el-submenu index="2">
            <template slot="title"><i class="el-icon-caret-right"></i>內容管理</template>
            <el-menu-item-group>
              <el-menu-item index="2-1">分類管理</el-menu-item>
              <el-menu-item index="2-2">內容列表</el-menu-item>
            </el-menu-item-group>
          </el-submenu>
        </el-menu>
      </el-aside>

      <el-container>
        <el-header style="text-align: right; font-size: 12px">
          <el-dropdown>
            <i class="el-icon-setting" style="margin-right: 15px"></i>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item>個人資訊</el-dropdown-item>
              <el-dropdown-item>退出登入</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
          </el-header>

        <el-main>
          <router-view />
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
  export default {
    name: "Main"
  }
</script>

<style scoped>
    .el-header {
      background-color: #36ba2a;
      color: #333;
      line-height: 60px;
    }
    .el-aside {
      color: #333;
    }
</style>

最後再在router/index.js中配置好路由

import Vue from 'vue'
import Router from 'vue-router'

import Main from '../views/Main';
import Login from "../views/Login";
import UserList from '../views/user/List';
import UserProfile from '../views/user/Profile';

Vue.use(Router);

export default new Router({
  routes:[
    {
      path: '/main',
      component: Main,
      children:[ //巢狀路由
        {path:'/user/profile',component:UserProfile},
        {path:'/user/list',component:UserList}
      ]
    },{
      path: '/login',
      component: Login
    }
  ]
});

現在我們就可以 npm run dev執行測試下,進到http://localhost:8080/#/main

點選個人資訊或使用者列表就可以相應的跳轉到我們之前設定的元件介面,網頁上的url也會改變成我們設定的url。

引數傳遞及重定向

我們的介面應該是根據不同的使用者引數從而展示不同的內容,這就要用到引數傳遞。下面例子

直接傳參

在Main.vue中進行修改

<el-menu-item index="1-1">
    <!--name 元件名,params 傳遞引數  v-bind繫結簡寫 :-->
      <router-link :to="{name:'UserProfile',params:{id:1}}">個人資訊</router-link>
</el-menu-item>

在index.js處

      path: '/main',
      component: Main,
      children:[ //巢狀路由
        {path:'/user/profile/:id',name:'UserProfile' ,component:UserProfile},
        {path:'/user/list',component:UserList}
      ]

然後我們試著將其在元件頁面中取得展示出來,Profile.vue

<template>
  <div>
    <h1>個人資訊</h1>
    {{ $route.params.id }}
  </div>
</template>

(注意:我們在template元件中寫的內容必須都要在某個標籤之中,不然會報錯)

之後我們執行測試下 http://localhost:8080/#/user/profile/1

將地址上的數字改成另外的內容,下面的展示也會做相應的改變。

我們在Main.vue中通過繫結到to,讓他變成一個物件去傳,然後傳給某個路由,給某個路由中的path來接收,然後在某個元件頁面通過{{route.params.XXXX}}來接收。

props傳參

還可以通過props來解耦,取得引數

這種方式,我們的Main.vue中不用改變,我們需要在index.js中設定下

{path:'/user/profile/:id',name:'UserProfile' ,component:UserProfile,props: true}

將其設定為true,從而支援引數傳遞

之前在前端元件Profile.vue呼叫的話,是通過元件來取得引數

<template>
  <div>
    <h1>個人資訊</h1>
<!--    {{ $route.params.id }}-->
    {{id}}
  </div>
</template>

<script>
  export default {
    props:['id'],
    name: "UserProfile"
  }
</script>

<style scoped>

</style>

這樣也是和之前一樣的效果。

重定向

我們在Main.vue再加上一個重新回到主頁的選項

<el-menu-item index="1-3">
  <router-link to="/goHome">回到首頁</router-link>
</el-menu-item>

我們只需要在router/index.js中設定下重定向即可,在route中再加上一個路徑的重定向

{
   path:'/goHome',
   redirect:'/main'
}

之後點選回到首頁後就可以回到我們一片空白的首頁。

我們把登陸的也連線一下,在Login.vue中將我們的username傳過來展示,修改下其中的onSubmit方法,將使用者名稱一起傳輸。

      onSubmit(formName) {
        //為表單繫結驗證功能
        this.$refs[formName].validate((valid) => {
          if (valid) {
            //使用vue-router路由到指定頁面,該方式稱之為程式設計式導航
            this.$router.push("/main/"+this.form.username);
          } else {
            this.dialogVisible = true;
            return false;
          }
        });
      }

之後在router/index.js中接收

    {
      path: '/main/:name',
      props:true,
      component: Main,
      children:[ //巢狀路由
        {path:'/user/profile/:id',name:'UserProfile' ,component:UserProfile,props: true},
        {path:'/user/list',component:UserList}
      ]
    }

這裡接收後,再Main.vue中接收使用即可,

<script>
  export default {
    props:['name'],
    name: "Main"
  }
</script>

在任意位置加一個span的標籤

          <el-dropdown>
            <i class="el-icon-setting" style="margin-right: 15px"></i>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item>個人資訊</el-dropdown-item>
              <el-dropdown-item>退出登入</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
          <span>{{name}}</span>

執行測試下,首先來到登陸介面http://localhost:8080/#/login

點選登陸進入系統後,可以看到右上角成功出現我們的名字。

路由模式與404

路由模式

路由模式有兩種

  • hash: 路徑帶# 符號,如http://localhost/#/login

  • history: 路徑不帶#符號,如 http://localhost/login

修改路由配置,程式碼如下:

export default new Router({
	mode: 'history',
	routes : []
});

404

當我們的介面找不到的時候,我們應該出現404的頁面

在views中建立404元件頁面NotFound.vue

<template>
  <div>
    <h1>404</h1>
    <h2>你的網頁走丟了。。。</h2>
  </div>
</template>

<script>
export default {
  name: "NotFound"
}
</script>

<style scoped>

</style>

再配置其路由設定

{
  path: '*', //訪問不到的就到*
  component: NotFound
}

執行測試

路由鉤子與非同步請求

  • beforeRouteEnter:在進入路由前執行
  • beforeRouteLeave:在離開路由前執行

他們其中都有三個引數(to,from,next),這個不能亂寫,固定的,beforeRouteEnter其實和過濾器一樣,在進入路由前執行。

<script>
  export default {
    props:['id'],
    name: "UserProfile",
    beforeRouteEnter:(to,from,next)=>{
      console.log("進入之前");
      next();
    },
    beforeRouteLeave:(to,from,next)=>{
       console.log("離開之前");
       next();
    }
  }
</script>

可以像這樣使用。

引數說明:

  • to:路由將要跳轉的路徑資訊.
  • from:路徑跳轉前的路徑資訊.
  • next:路由的控制引數
    • next()跳入下一個頁面
    • next('/path')改變路由的跳轉方向,使其跳到另一個路由
    • next(false)返回原來的頁面
    • next((vm)=>{ })僅在 beforeRouteEnter 中可用,vm是元件例項

在鉤子函式中使用非同步請求

安裝 Axios cnpm install --save axios vue-axios

在main.js中引入

import axios from 'axios'
import VueAxios from 'vue-axios'

Vue.use(VueAxios, axios)

這裡我們在static目錄下新建一個mock的目錄,我們一般將測試資料之類的東西放在這裡面

其中新建一個data.json

{
  "name": "java",
  "url": "http://baidu.com",
  "page": 1,
  "isNonProfit":true,
  "address": {
    "street": "創業路",
    "city":"福建福州",
    "country": "中國"
  },
  "links": [
    {
      "name": "B站",
      "url": "https://www.bilibili.com/"
    },
    {
      "name": "4399",
      "url": "https://www.4399.com/"
    },
    {
      "name": "百度",
      "url": "https://www.baidu.com/"
    }
  ]
}

這裡我們想要將這個資料在前端展示,我們是讓他在進入一個頁面前載入好資料,使用beforeRouteEnter這個鉤子函式。

<template>
  <div>
    <h1>個人資訊</h1>
    {{id}}
  </div>
</template>

<script>
  export default {
    props:['id'],
    name: "UserProfile",
    beforeRouteEnter:(to,from,next)=>{
      console.log("進入之前");
      //載入資料
      next(vm=>{ //直接拿到當前vm的例項物件
        vm.getData(); //進入路由之前執行getData
      });
    },
    beforeRouteLeave:(to,from,next)=>{
       console.log("離開之前");
       next();
    },
    methods:{
      getData: function (){
        this.axios({
          method:'get',
          url:'http://localhost:8080/static/mock/data.json'
        }).then(function (response){
          console.log(response);
        })
      }
    }
  }
</script>

<style scoped>

</style>

之後我們啟動系統進入這個頁面後就可以在輸出臺看到我們獲取的資料

其實直接這裡只是做一個轉接。