文章目錄
- 一、前端核心分析
-
- 1.VUE概述
- 2. 前端三要素
- 3. JavaScript架構
- 二、第一個Vue程式
-
- 1. 什麼是MVVM
- 2. 為什麼要使用MVVM
- 3. Vue 是 MVVM 模式的實作者
- 三、Vue基本文法
-
- 1. `v-bind`( : )
- 2. `v-if` `v-else`
- 3. `v-for`
- 4.`v-on`事件綁定(@click)
- 四、Vue雙向綁定`v-model`
-
- 1. 什麼是雙向綁定
- 2. 為什麼要實作資料的雙向綁定
- 3. 在表單中使用雙向資料綁定
- 五、Vue元件
- 六、Axios通信
-
- 1. 什麼是Axios
- 2. 為什麼要使用Axios
- 3. Vue計算屬性
- 七、内容分發 slot
- 八、自定義事件内容分發
- 九、第一個vue-cli項目
-
- 1. 什麼是vue-cli
- 2. 需要的環境
- 3. 安裝vue-cli
- 4. 第一個 vue-cli 應用程式
- 十、Webpack
-
- 1. 什麼是Webpack
- 2. 使用Webpack
- 十一、vue-router路由
-
- 1. 安裝
- 2. vue-router demo執行個體
- 十二、vue + ElementUI
- 十三、路由嵌套
- 十四、參數傳遞
-
- 1. Demo
- 2. 元件重定向
- 十五、路由鈎子與異步請求
-
- 1. 路由模式與 404
- 2. 路由鈎子與異步請求
- 3. 在鈎子函數中使用異步請求
筆記來源
狂神說
一、前端核心分析
Vue 的核心庫隻關注視圖層,友善與第三方庫或既有項目整合。
HTML + CSS + JS : 視圖 : 給使用者看,重新整理背景給的資料
網絡通信 : axios
頁面跳轉 : vue-router
狀态管理:vuex
Vue-UI : ICE , Element UI
1.VUE概述
Vue (讀音/vju/, 類似于view)是一套用于建構使用者界面的
漸進式架構
,釋出于2014年2月。與其它大型架構不同的是,Vue被設計為可以自底向上逐層應用。Vue的核心庫隻關注視
圖層
,不僅易于上手,還便于與第三方庫(如:
vue-router:
跳轉,
vue-resource:
通信,
vuex:
管理)或既有項目整合
2. 前端三要素
- HTML (結構) :超文本标記語言(Hyper Text Markup Language) ,決定網頁的結構和内容
- CSS (表現) :層疊樣式表(Cascading Style sheets) ,設定網頁的表現樣式
- JavaScript (行為) :是一種弱類型腳本語言,其源代碼不需經過編譯,而是由浏覽器解釋運作,用于控制網頁的行為
3. JavaScript架構
- jQuery: 大家熟知的JavaScript架構,優點是簡化了DOM操作,缺點是DOM操作太頻繁,影響前端性能;在前端眼裡使用它僅僅是為了相容IE6、7、8;
- Angular: Google收購的前端架構,由一群
開發,其特點是将背景的Java程式員
搬到了前端并增加了子產品化開發的理念,與微軟合作,采用TypeScript文法開發;對背景程式員友好,對前端程式員不太友好;最大的缺點是版本疊代不合理(如: 1代-> 2代,除了名字,基本就是兩個東西;截止發表部落格時已推出了Angular6)MVC模式
- React: Facebook出品,一款高性能的JS前端架構;特點是提出了新概念[
]用于減少真實DOM操作,在虛拟DOM
中模拟DOM操作,有效的提升了前端渲染效率;缺點是使用複雜,因為需要額外學習一門[JSX] 語言;記憶體
- Vue:一款漸進式JavaScript架構,所謂
就是逐漸實作新特性的意思,如實作子產品化開發、路由、狀态管理等新特性。其特點是漸進式
了Angular (子產品化)和React (虛拟DOM)的優點;綜合
- Axios :前端通信架構;因為Vue 的邊界很明确,就是為了處理DOM,是以
,此時就需要并不具備通信能力
使用一個額外
;當然也可以直接選擇使用jQuery提供的AJAX通信功能;通信架構與伺服器互動
前端三大架構:Angular、React、Vue
二、第一個Vue程式
1. 什麼是MVVM
MVVM (Model-View-ViewModel) 是一種軟體架構設計模式,由微軟WPF (用于替代WinForm,以前就是用這個技術開發桌面應用程式的)和Silverlight (類似于Java Applet,簡單點說就是在浏覽器上運作的WPF)的架構師Ken Cooper和Ted Peters 開發,是一種簡化使用者界面的事件驅動程式設計方式。由John Gossman (同樣也是WPF和Silverlight的架構師)于2005年在他的部落格上發表。
MVVM 源自于經典的MVC (ModI-View-Controller) 模式。MVVM的核心是ViewModel層,負責轉換Model中的資料對象來讓資料變得更容易管理和使用,其作用如下:
- 該層向上與視圖層進行雙向綁定
- 向下與Model層通過接口請求進行資料互動
2.Vue詳解一、前端核心分析二、第一個Vue程式三、Vue基本文法四、Vue雙向綁定v-model五、Vue元件六、Axios通信七、内容分發 slot八、自定義事件内容分發九、第一個vue-cli項目十、Webpack十一、vue-router路由十二、vue + ElementUI十三、路由嵌套十四、參數傳遞十五、路由鈎子與異步請求
2. 為什麼要使用MVVM
MVVM模式和MVC模式一樣,主要目的是分離視圖(View)和模型(Model),有幾大好處:
- 低耦合:視圖(View)可以獨立于Model變化和修改,一個ViewModel可以綁定到不同的View上,當View變化的時候Model可以不變,當Model變化的時候View也可以不變。
- 可複用:你可以把一些視圖邏輯放在一個ViewModel裡面,讓很多View重用這段視圖邏輯。
- 獨立開發:開發人員可以專注于業務邏輯和資料的開發(ViewModel),設計人員可以專注于頁面設計。
- 可測試:界面素來是比較難于測試的,而現在測試可以針對ViewModel來寫。
3. Vue 是 MVVM 模式的實作者
- Model : 模型層,在這裡表示JavaScript對象
- View : 視圖層,在這裡表示DOM (HTML操作的元素)
- ViewModel : 連接配接視圖和資料的中間件,Vue.js就是MVVM中的ViewModel層的實作者在MVVM架構中,是不允許資料和視圖直接通信的,隻能通過ViewModel來通信,而ViewModel就是定義了一個Observer觀察者
- ViewModel 能夠觀察到資料的變化,并對視圖對應的内容進行更新
-
ViewModel 能夠監聽到視圖的變化,并能夠通知資料發生改變
至此,我們就明白了,Vue.js 就是一個MVVM的
,他的核心就是實作了實作者
與DOM監聽
資料綁定
Vue線上cdn:
三、Vue基本文法
1. v-bind
( : )
v-bind
現在資料和DOM已經被建立了關聯,所有的東西都是響應式的。我們在控制台操作對象的屬性,界面可以實時更新。
我們可以使用
v-bind
來綁定元素屬性!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>狂神說Java</p>
<!--view層 模闆-->
<div id="app">
<span v-bind:title="message">滑鼠懸停幾秒鐘檢視此處動态綁定的提示資訊!</span>
</div>
</body>
<!--導入js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
message: "hello,vue"
}
})
</script>
</html>
2. v-if
v-else
v-if
v-else
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>狂神說Java</p>
<!--view層 模闆-->
<div id="app">
<h1 v-if="type==='A'">A</h1>
<h1 v-else-if="type==='B'">B</h1>
<h1 v-else>C</h1>
</div>
</body>
<!--導入js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
type: "A"
}
})
</script>
</html>
3. v-for
v-for
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>狂神說Java</p>
<!--view層 模闆-->
<div id="app">
<li v-for="item in items">
姓名:{{item.name}},年齡:{{item.age}}
</li>
</div>
</body>
<!--導入js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
items: [
{name: "zhangsan", age: 12},
{name: "lisi", age: 10},
{name: "wangwu", age: 16}
]
}
})
</script>
</html>
4. v-on
事件綁定(@click)
v-on
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>狂神說Java</p>
<!--view層 模闆-->
<div id="app">
<button v-on:click="sayHi">Click Me</button>
</div>
</body>
<!--導入js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
message: "你點我幹嘛?"
},
methods: {
//方法必須綁定在Vue的Methods對象中,v-on:事件
sayHi: (function (event) {
alert(this.message)
})
}
})
</script>
</html>
四、Vue雙向綁定 v-model
v-model
1. 什麼是雙向綁定
Vue.js是一個MVVM架構,即資料雙向綁定,即當資料發生變化的時候,視圖也就發生變化,當視圖發生變化的時候,資料也會跟着同步變化。這也算是Vue.js的精髓之處了。
值得注意的是,我們所說的資料雙向綁定,一定是對于UI控件來說的,非UI控件不會涉及到資料雙向綁定。單向資料綁定是使用狀态管理工具的前提。如果我們使用vuex,那麼資料流也是單項的,這時就會和雙向資料綁定有沖突。
2. 為什麼要實作資料的雙向綁定
在Vue.js 中,如果使用vuex ,實際上資料還是單向的,之是以說是資料雙向綁定,這是用的UI控件來說,對于我們處理表單,Vue.js的雙向資料綁定用起來就特别舒服了。即兩者并不互斥,在全局性資料流使用單項,友善跟蹤;局部性資料流使用雙向,簡單易操作。
3. 在表單中使用雙向資料綁定
你可以用
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>
<!--view層 模闆-->
<div id="app">
下拉框:
<select v-model="selected">
<option value="" disabled>-請選擇-</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<p>value:{{selected}}</p>
</div>
</body>
<!--導入js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
selected: ""
}
})
</script>
</html>
五、Vue元件
元件是可複用的
Vue
執行個體,說白了就是一組可以重複使用的模闆,跟JSTL的自定義标簽、Thymeleaf的th:fragment 等架構有着異曲同工之妙。通常一個應用會以一棵嵌套的元件樹的形式來組織:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view層 模闆-->
<div id="app">
<qinjiang v-for="item in items" v-bind:qin="item"></qinjiang>
</div>
</body>
<!--導入js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<script>
Vue.component("qinjiang",{
props: ['qin'],
template: '<li>{{qin}}</li>'
})
var vm = new Vue({
el: "#app",
data: {
items: ['Java','Python','Php']
}
})
</script>
</html>
六、Axios通信
1. 什麼是Axios
Axios是一個開源的可以用在浏覽器端和
NodeJS
的異步通信架構,她的主要作用就是實作AJAX異步通信,其功能特點如下:
- 從浏覽器中建立
XMLHttpRequests
- 從node.js建立http請求
- 支援Promise API [JS中鍊式程式設計]
- 攔截請求和響應
- 轉換請求資料和響應資料
- 取消請求
- 自動轉換JSON資料
-
用戶端支援防禦XSRF (跨站請求僞造)
GitHub
中文文檔
2. 為什麼要使用Axios
由于
Vue.js
是一個視圖層架構且作者(尤雨溪) 嚴格準守SoC (關注度分離原則),是以
Vue.js
并不包含Ajax的通信功能,為了解決通信問題,作者單獨開發了一個名為
vue-resource
的插件,不過在進入2.0 版本以後停止了對該插件的維護并推薦了
Axios
架構。少用jQuery,因為它操作Dom太頻繁 !
模拟Json資料:
{
"name": "weg",
"age": "18",
"sex": "男",
"url":"https://www.baidu.com",
"address": {
"street": "文苑路",
"city": "南京",
"country": "中國"
},
"links": [
{
"name": "bilibili",
"url": "https://www.bilibili.com"
},
{
"name": "baidu",
"url": "https://www.baidu.com"
},
{
"name": "cqh video",
"url": "https://www.4399.com"
}
]
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view層 模闆-->
<div id="vue">
<div>{{info.name}}</div>
<a v-bind:href="info.url">點我進入</a>
</div>
</body>
<!--1.導入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<!--導入axios-->
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js"></script>
<script>
var vm = new Vue({
el: "#vue",
data: {
items: ['Java','Python','Php']
},
//data:vm的屬性
//data():vm方法
data(){
return{
//請求的傳回參數,必須和json字元串一樣
info:{
name: null,
age: null,
sex: null,
url: null,
address: {
street: null,
city: null,
country: null
}
}
}
},
//鈎子函數,鍊式程式設計,ES6新特性
mounted(){
axios.get("../data.json").then(res => (this.info=res.data))
}
})
</script>
</html>
3. Vue計算屬性
計算屬性的重點突出在
屬性
兩個字上(屬性是名詞),首先它是個屬性其次這個屬性有
計算
的能力(計算是動詞),這裡的計算就是個函數;簡單點說,它就是一個能夠将計算結果緩存起來的屬性(将行為轉化成了靜态的屬性),僅此而已;可以想象為
緩存
!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view層 模闆-->
<div id="app">
<div>currentTime1: {{currentTime1()}}</div>
<div>currentTime2: {{currentTime2}}</div>
</div>
</body>
<!--導入js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
message: "hello,world!"
},
methods: {
currentTime1: function () {
return Date.now(); // 傳回一個時間戳
}
},
computed: {
//計算屬性:methods,computed 方法名不能重名,重名字後,隻會調用methods的方法
currentTime2: function () {
this.message;
// 傳回一個時間戳
return Date.now();
}
}
})
</script>
</html>
結論:
調用方法時,每次都需要進行計算,既然有計算過程則必定産生系統開銷,那如果這個結果是不經常變化的呢?此時就可以考慮将這個結果緩存起來,采用計算屬性可以很友善的做到這一點,計算屬性的主要特性就是為了将不經常變化的計算結果進行緩存,以節約我們的系統開銷.
七、内容分發 slot
在Vue.js中我們使用 元素作為承載分發内容的出口,作者稱其為插槽,可以應用在組合元件的場景中;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
<todo>
<todo-title slot="todo-title" v-bind:name="title"></todo-title>
<todo-items slot="todo-items" v-for="item in todoItems" v-bind:item="item"></todo-items>
</todo>
</div>
<!--1.導入vue.js-->
<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: ['name'],
template: '<div>{{name}}</div>'
});
Vue.component("todo-items", {
props: ['item'],
template: '<li>{{item}}</li>'
});
let vm = new Vue({
el: "#app",
data: {
//标題
title: "圖書館系列圖書",
//清單
todoItems: ['三國演義', '紅樓夢', '西遊記', '水浒傳']
}
});
</script>
</body>
</html>
==注意:==上面代碼script标簽中的let vm = new Vue(…)一定要放在标簽的最後面
八、自定義事件内容分發
通過以上代碼不難發現,資料項在Vue的執行個體中,但删除操作要在元件中完成,那麼元件如何才能删除Vue執行個體中的資料呢?此時就涉及到參數傳遞與事件分發了,Vue為我們提供了自定義事件的功能很好的幫助我們解決了這個問題;
使用
this.$emit (‘自定義事件名’,參數)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
<todo>
<todo-title slot="todo-title" v-bind:name="title"></todo-title>
<todo-items slot="todo-items" v-for="(item,index) in todoItems" v-bind:item="item"
v-bind:index="index" v-on:remove="removeItems(index)"></todo-items>
</todo>
</div>
<!--1.導入vue.js-->
<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: ['name'],
template: '<div>{{name}}</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)
}
}
});
let vm = new Vue({
el: "#app",
data: {
//标題
title: "圖書館系列圖書",
//清單
todoItems: ['三國演義', '紅樓夢', '西遊記', '水浒傳']
},
methods: {
removeItems: function (index) {
console.log("删除了"+this.todoItems[index]+"OK");
this.todoItems.splice(index,1);
}
}
});
</script>
</body>
</html>
九、第一個vue-cli項目
1. 什麼是vue-cli
vue-cli 官方提供的一個腳手架,用于快速生成一個 vue 的項目模闆;
預先定義好的目錄結構及基礎代碼,就好比咱們在建立 Maven 項目時可以選擇建立一個骨架項目,這個骨架項目就是腳手架,我們的開發更加的快速;
主要功能:
- 統一的目錄結構
- 本地調試
- 熱部署
- 單元測試
- 內建打包上線
2. 需要的環境
-
Node.js : http://nodejs.cn/download/
安裝就無腦下一步就好,安裝在自己的環境目錄下
- Git : https://git-scm.com/downloads
- 鏡像:https://npm.taobao.org/mirrors/git-for-windows/
确認nodejs安裝成功:
- cmd 下輸入
,檢視是否能夠正确列印出版本号即可!node -v
- cmd 下輸入
檢視是否能夠正确列印出版本号即可!npm-v
這個npm,就是一個軟體包管理工具,就和linux下的apt軟體安裝差不多!
npm 是 JavaScript 世界的包管理工具,并且是 Node.js 平台的預設包管理工具。通過 npm 可以安裝、共享、分發代碼,管理項目依賴關系。
安裝 Node.js 淘寶鏡像加速器(cnpm)
這樣子的話,下載下傳會快很多~
# -g 就是全局安裝
npm install cnpm -g
# 若安裝失敗,則将源npm源換成淘寶鏡像
# 因為npm安裝插件是從國外伺服器下載下傳,受網絡影響大
npm config set registry https://registry.npm.taobao.org
# 然後再執行
npm install cnpm -g
安裝的位置:C:\Users\Administrator\AppData\Roaming\npm
3. 安裝vue-cli
#在指令台輸入
cnpm install vue-cli -g
#檢視是否安裝成功
vue list
4. 第一個 vue-cli 應用程式
建立一個Vue項目,我們随便建立一個空的檔案夾在電腦上。
我這裡在D盤下建立一個目錄D:\Project\vue-study;
建立一個基于 webpack 模闆的 vue 應用程式
# 這裡的 myvue 是項目名稱,可以根據自己的需求起名
vue init webpack myvue
一路都選擇no即可;
初始化并運作
cd myvue
npm install
npm run dev
執行完成後,目錄多了很多依賴
十、Webpack
WebPack 是一款子產品加載器兼打包工具,它能把各種資源,如 JS、JSX、ES6、SASS、LESS、圖檔等都作為子產品來處理和使用。
npm install webpack -g
npm install webpack-cli -g
測試安裝成功: 輸入以下指令有版本号輸出即為安裝成功
webpack -v
webpack-cli -v
1. 什麼是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代碼,這給前端的開發流程和資源組織帶來了巨大挑戰。
前端開發和其他開發工作的主要差別,首先是前端基于多語言、多層次的編碼群組織工作,其次前端産品的傳遞是基于浏覽器的,這些資源是通過增量加載的方式運作到浏覽器端,如何在開發環境組織好這些碎片化的代碼和資源,并且保證他們在浏覽器端快速、優雅的加載和更新,就需要一個子產品化系統,這個理想中的子產品化系統是前端工程師多年來一直探索的難題。
2. 使用Webpack
- 先建立一個包 交由idea打開 會生成一個.idea檔案 那麼就說明該檔案就交由idea負責
- 在idea中建立modules包,再建立hello.js,hello.js 暴露接口 相當于Java中的類
//暴露一個方法
exports.sayHi = function () {
document.write("<h1>狂神說ES6</h1>>")
}
- 建立main.js 當作是js主入口 , main.js 請求hello.js 調用sayHi()方法
var hello = require("./hello");
hello.sayHi()
-
在主目錄建立webpack-config.js , webpack-config.js 這個相當于webpack的配置檔案
enrty請求main.js的檔案
output是輸出的位置和名字
module.exports = {
entry: './modules/main.js',
output: {
filename: './js/bundle.js'
}
}
- 在idea指令台輸入webpack指令(idea要設定管理者啟動)
- 完成上述操作之後會在主目錄生成一個dist檔案 生成的js檔案夾路徑為/ dist/js/bundle.js
-
在主目錄建立index.html 導入bundle.js
index.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="dist/js/bundle.js"></script>
</head>
<body>
</body>
</html>
十一、vue-router路由
Vue Router是Vue.js官方的路由管理器(路徑跳轉)。它和Vue.js的核心深度內建,讓建構單頁面應用變得易如反掌。包含的功能有:
- 嵌套的路由/視圖表
- 子產品化的、基于元件的路由配置
- 路由參數、查詢、通配符
- 基于Vue.js過渡系統的視圖過渡效果
- 細粒度的導航控制
- 帶有自動激活的CSS class的連結
- HTML5曆史模式或hash模式,在IE9中自動降級
- 自定義的滾動條行為
1. 安裝
基于第一個vue-cli進行測試學習;先檢視node_modules中是否存在 vue-router
vue-router 是一個插件包,是以我們還是需要用 npm/cnpm 來進行安裝的。打開指令行工具,進入你的項目目錄,輸入下面指令。
npm install vue-router --save-dev
安裝完之後去
node_modules
路徑看看是否有vue-router資訊 有的話則表明安裝成功。
2. vue-router demo執行個體
- 将之前案例由vue-cli生成的案例用idea打開
- 清理不用的東西 assert下的logo圖檔 component定義的helloworld元件 我們用自己定義的元件
-
清理代碼 以下為清理之後的代碼 src下的App.vue 和main.js以及根目錄的index.html
這三個檔案的關系是
調用index.html
調用main.js
index.html:App.vue
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>myvue</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
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">
<img src="./assets/logo.png">
<h1>迪師傅</h1>
<router-link to="/main">首頁</router-link>
<router-link to="/content">内容頁</router-link>
<router-link to="/kuang">Kuang</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</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>
-
在components目錄下建立一個自己的元件Content,Test,Main(這兩個和Content内容一樣的就不放示例代碼了
Content.vue:
<template>
<h1>内容</h1>
</template>
<script>
export default {
name: "Content"
}
</script>
<style scoped>
</style>
- 安裝路由,在src目錄下,建立一個檔案夾 : router,專門存放路由 index.js(預設配置檔案都是這個名字)
import Vue from "vue";
import VueRouter from "vue-router";
import Content from "../components/Content";
import Main from "../components/Main";
import Kuang from "../components/Kuang";
//安裝路由
Vue.use(VueRouter);
//配置導出路由
export default new VueRouter({
routes: [
{
//路由路徑
path: '/content',
name: 'content',
//跳轉的元件
component: Content
},
{
//路由路徑
path: '/main',
name: 'main',
//跳轉的元件
component: Main
},
{
//路由路徑
path: '/kuang',
name: 'kuang',
//跳轉的元件
component: Kuang
}
]
})
-
在main.js中配置路由
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中使用路由
App.vue:
<template>
<div id="app">
<img src="./assets/logo.png">
<h1>迪師傅</h1>
<router-link to="/main">首頁</router-link>
<router-link to="/content">内容頁</router-link>
<router-link to="/kuang">Kuang</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</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>
- 啟動測試一下 : npm run dev
- 項目結構圖&運作效果圖
2.Vue詳解一、前端核心分析二、第一個Vue程式三、Vue基本文法四、Vue雙向綁定v-model五、Vue元件六、Axios通信七、内容分發 slot八、自定義事件内容分發九、第一個vue-cli項目十、Webpack十一、vue-router路由十二、vue + ElementUI十三、路由嵌套十四、參數傳遞十五、路由鈎子與異步請求 2.Vue詳解一、前端核心分析二、第一個Vue程式三、Vue基本文法四、Vue雙向綁定v-model五、Vue元件六、Axios通信七、内容分發 slot八、自定義事件内容分發九、第一個vue-cli項目十、Webpack十一、vue-router路由十二、vue + ElementUI十三、路由嵌套十四、參數傳遞十五、路由鈎子與異步請求
十二、vue + ElementUI
根據之前建立vue-cli項目一樣再來建立一個新項目
- 建立一個名為 hello-vue 的工程
vue init webpack hello-vue
- 安裝依賴,我們需要安裝
、vue-router
、element-ui
和sass-loader
四個插件node-sass
# 進入工程目錄
cd hello-vue
# 安裝 vue-router
npm install vue-router --save-dev
# 安裝 element-ui
npm i element-ui -S
# 安裝依賴
npm install
# 安裝 SASS 加載器
cnpm install sass-loader node-sass --save-dev
# 啟動測試
npm run dev
- Npm指令解釋
-
:安裝子產品到項目目錄下npm install moduleName
-
:-g 的意思是将子產品安裝到全局,具體安裝到磁盤的哪個位置,要看 npm config prefix的位置npm install -g moduleName
-
:–save的意思是将子產品安裝到項目目錄下,并在package檔案的dependencies節點寫入依賴,-S為該指令的縮寫npm install moduleName -save
-
:–save-dev的意思是将子產品安裝到項目目錄下,并在package檔案的devDependencies節點寫入依賴,-D為該指令的縮寫npm install moduleName -save-dev
-
- 建立成功後用idea打開,并删除淨東西 建立views和router檔案夾用來存放視圖和路由
2.Vue詳解一、前端核心分析二、第一個Vue程式三、Vue基本文法四、Vue雙向綁定v-model五、Vue元件六、Axios通信七、内容分發 slot八、自定義事件内容分發九、第一個vue-cli項目十、Webpack十一、vue-router路由十二、vue + ElementUI十三、路由嵌套十四、參數傳遞十五、路由鈎子與異步請求 -
在views建立Main.vue
Main.vue:
<template>
<h1>首頁</h1>
</template>
<script>
export default {
name: "Main"
}
</script>
<style scoped>
</style>
-
在views中建立Login.vue視圖元件
Login.vue:(用的ElementUI中的代碼)
<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 的 vue-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中配置相關
main.js是index.html調用的 是以前面注冊的元件要在這裡導入
一定不要忘記掃描路由配置并将其用到new Vue中
main.js:
import Vue from 'vue'
import App from './App'
//掃描路由配置
import router from './router'
//導入elementUI
import ElementUI from "element-ui"
//導入element css
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中配置顯示視圖
App.vue :
<template>
<div id="app">
<router-link to="/login">login</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
- 測試運作
npm run dev
測試:在浏覽器打開 http://localhost:8080/#/login
如果出現錯誤: 可能是因為sass-loader的版本過高導緻的編譯錯誤,目前最高版本是8.0.2,需要退回到7.3.1 ;
去package.json檔案裡面的 "sass-loader"的版本更換成7.3.1,然後重新cnpm install就可以了;
十三、路由嵌套
嵌套路由又稱子路由,在實際應用中,通常由多層嵌套的元件組合而成。
-
建立使用者資訊元件,在 views/user 目錄下建立一個名為 Profile.vue 的視圖元件;
Profile.vue
<template>
<h1>個人資訊</h1>
</template>
<script>
export default {
name: "UserProfile"
}
</script>
<style scoped>
</style>
-
在使用者清單元件在 views/user 目錄下建立一個名為 List.vue 的視圖元件;
List.vue
<template>
<h1>使用者清單</h1>
</template>
<script>
export default {
name: "UserList"
}
</script>
<style scoped>
</style>
-
修改首頁視圖,我們修改 Main.vue 視圖元件,此處使用了 ElementUI 布局容器元件,代碼如下:
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 lang="scss">
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
</style>
-
配置嵌套路由修改 router 目錄下的 index.js 路由配置檔案,使用children放入main中寫入子子產品,代碼如下
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
}
]
});
- 路由嵌套效果圖
2.Vue詳解一、前端核心分析二、第一個Vue程式三、Vue基本文法四、Vue雙向綁定v-model五、Vue元件六、Axios通信七、内容分發 slot八、自定義事件内容分發九、第一個vue-cli項目十、Webpack十一、vue-router路由十二、vue + ElementUI十三、路由嵌套十四、參數傳遞十五、路由鈎子與異步請求
十四、參數傳遞
1. Demo
-
前端傳遞參數
此時我們在Main.vue中的route-link位置處 to 改為了 :to,是為了将這一屬性當成對象使用,注意 router-link 中的 name 屬性名稱 一定要和 路由中的 name 屬性名稱 比對,因為這樣 Vue 才能找到對應的路由路徑;
<!--name:傳元件名 params:傳遞參數,需要綁定對象:v-bind-->
<router-link v-bind:to="{name: 'UserProfile', params: {id: 1}}">個人資訊</router-link>
-
修改路由配置,增加props:true屬性
主要是router下的index.js中的 path 屬性中增加了 :id 這樣的占位符
{
path: '/user/profile/:id',
name: 'UserProfile',
component: UserProfile,
props:true
}
-
前端顯示
在要展示的元件Profile.vue中接收參數
Profile.vue:
<template>
<div>
個人資訊
{{ id }}
</div>
</template>
<script>
export default {
props: ['id'],
name: "UserProfile"
}
</script>
<style scoped>
</style>
- 運作
2.Vue詳解一、前端核心分析二、第一個Vue程式三、Vue基本文法四、Vue雙向綁定v-model五、Vue元件六、Axios通信七、内容分發 slot八、自定義事件内容分發九、第一個vue-cli項目十、Webpack十一、vue-router路由十二、vue + ElementUI十三、路由嵌套十四、參數傳遞十五、路由鈎子與異步請求
2. 元件重定向
重定向的意思大家都明白,但 Vue 中的重定向是作用在路徑不同但元件相同的情況下,比如:
在router下面index.js的配置
{
path: '/main',
name: 'Main',
component: Main
},
{
path: '/goHome',
redirect: '/main'
}
說明:這裡定義了兩個路徑,一個是 /main ,一個是 /goHome,其中 /goHome 重定向到了 /main 路徑,由此可以看出重定向不需要定義元件;
使用的話,隻需要在Main.vue設定對應路徑即可;
<el-menu-item index="1-3">
<router-link to="/goHome">回到首頁</router-link>
</el-menu-item>
十五、路由鈎子與異步請求
1. 路由模式與 404
路由模式有兩種
- hash:路徑帶 # 符号,如 http://localhost/#/login
-
history:路徑不帶 # 符号,如 http://localhost/login
修改路由配置,代碼如下:
export default new Router({
mode: 'history',
routes: [
]
});
404界面:
- 建立一個NotFound.vue視圖元件
<template>
<div>
<h1>404,你的頁面走丢了</h1>
</div>
</template>
<script>
export default {
name: "NotFound"
}
</script>
<style scoped>
</style>
- 修改路由配置index.js
import NotFound from '../views/NotFound'
{
path: '*',
component: NotFound
}
2. 路由鈎子與異步請求
beforeRouteEnter
:在進入路由前執行
beforeRouteLeave
:在離開路由前執行
在Profile.vue中寫:
export default {
name: "UserProfile",
beforeRouteEnter: (to, from, next) => {
console.log("準備進入個人資訊頁");
next();
},
beforeRouteLeave: (to, from, next) => {
console.log("準備離開個人資訊頁");
next();
}
}
參數說明:
- to:路由将要跳轉的路徑資訊
- from:路徑跳轉前的路徑資訊
- next:路由的控制參數
- next() 跳入下一個頁面
- next(’/path’) 改變路由的跳轉方向,使其跳到另一個路由
- next(false) 傳回原來的頁面
- next((vm)=>{}) 僅在 beforeRouteEnter 中可用,vm 是元件執行個體
3. 在鈎子函數中使用異步請求
- 安裝 Axios
cnpm install --save vue-axios
- main.js引用 Axios
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
-
準備資料 : 隻有我們的 static 目錄下的檔案是可以被通路到的,是以我們就把靜态檔案放入該目錄下。
資料和之前用的json資料一樣 需要的去上述axios例子裡
// 靜态資料存放的位置
static/mock/data.json
-
在 beforeRouteEnter 中進行異步請求
Profile.vue:
export default {
//第二種取值方式
// props:['id'],
name: "UserProfile",
//鈎子函數 過濾器
beforeRouteEnter: (to, from, next) => {
//加載資料
console.log("進入路由之前")
next(vm => {
//進入路由之前執行getData方法
vm.getData()
});
},
beforeRouteLeave: (to, from, next) => {
console.log("離開路由之前")
next();
},
//axios
methods: {
getData: function () {
this.axios({
method: 'get',
url: 'http://localhost:8080/static/mock/data.json'
}).then(function (response) {
console.log(response)
})
}
}
}
- 執行