Vue教程路由以及axios的使用
目錄
- 前言
- 安裝
- 目錄結構
- 起步
- Vue模板語法
- Vue條件語句
- Vue循環語句
- Vue事件處理
- Vue表單綁定
- Vue組件
- Prop
- Vue自定義事件、指令
- **自定義事件**
- **自定義指令**
- Vue路由
- VueAjax
- npm下載axios:
- 全局引入axios
- 例子
- axios API
- axios跨域問題
- 封裝axios
- 結束
前言
如果你不想看這里,那么可以直接跳到后面去。
在官網開了Vue.js和Vue CLI的官方文檔,也只介紹了在普通html項目怎么使用,現在我自己整理了下,各個模塊在基于webpack的Vue項目中的使用。相關介紹也可以去官網查看,本文僅介紹使用方法,因為也是新手小白,有錯誤的地方還請多多指正。本問有些地方引用了菜鳥教程的在線編輯器,在這里感謝菜鳥教程做出的貢獻。
安裝
Node 版本要求
Vue CLI 需要 Node.js 8.9 或更高版本 (推薦 8.11.0+)。你可以使用 nvm 或 nvm-windows在同一臺電腦中管理多個 Node 版本。
關于舊版本
Vue CLI 的包名稱由 vue-cli 改成了 @vue/cli。 如果你已經全局安裝了舊版本的 vue-cli(1.x 或 2.x),你需要先通過 npm uninstall vue-cli -g 或 yarn global remove vue-cli 卸載它。
安裝好Node.js后就可以開始Vue的起步了。
因為要連接國外的資源,所以會下載的手會很慢。請保持網速。
淘寶鏡像
解決這個情況可以使用淘寶的鏡像以及命令cnpm,但是有時候會出問題,安裝時保證npm版本大于3.0
查看npm版本:
$ npm -v升級npm:
$ npm install npm -g安裝cnpm:
$ npm install -g cnpm --registry=https://registry.npm.taobao.org安裝完成后就可以用cnpm代替npm了。一下教程使用的還是npm。
開始
首先使用命令安裝vue:
$ npm install vue查看是否安裝成功,本命令為查看版本:
$ vue --version安裝全局Vue CLI
$ npm install --global vue-cli創建一個vue項目,vueweb為項目名稱,你也可以在安裝的時候更改,注意項目名稱里面不要有大寫字母,也不要使用中文。
$ vue init webpack vueweb注意,這里會有一些配置,我來解釋一下(#后面為我的注釋,不要輸入進去):
? Project name (vueweb) # 項目名稱,括號中為默認名稱,回車即可 ? Project description (A Vue.js project) # 項目描述信息,回車即可 ? Author 1419908068 <1419908068@qq.com> # 項目作者,默認即可 ? Vue build standalone # 好像是打包的時候用的,回車即可 ? Install vue-router?(Y/N)Y # 是否安裝vue-router,建議:Y ? Use ESLint to lint your code? (Y/N) # 是否使用ESLint驗證,建議:N,否則后面因為格式會出很多問題。 ? Set up unit tests(Y/N) Yes # 是否安裝單元測試,沒什么用,建議:N ? Setup e2e tests with Nightwatch(Y/n)? #是否安裝E2E測試框架NightWatch,建議:N # 項目創建后是否要為你運行“npm install”?這里選擇包管理工具 # 選項有三個(上下箭頭選擇,回車即為選定)建議 : yes use npm Should we run 'npm install' for you after the project has been created?# 使用npm yes,use npm# 使用yarn yes,use yarn# 自己操作 no,I will handle that myself安裝完成后就可以開發了,當然任何開發都少不了開發工具,這里推薦使用HBuilder,占用體積小,功能強大。當然也可以使用微軟的Visual Studio,但是這個占用內存太大了。本教程使用的是HBuilder X 2.4.4.
測試是否安裝成功
打開HBuilder然后倒入項目vueweb,右鍵項目選擇外部命令/插件,再點擊npm run dev
如果報一下錯誤:
> vueweb@1.0.0 dev D:\文件\JavaWebx項目\vueTest\vueweb> webpack-dev-server --inline --progress --config build/webpack.dev.conf.js'webpack-dev-server' 不是內部或外部命令,也不是可運行的程序 或批處理文件。 npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! vueweb@1.0.0 dev: `webpack-dev-server --inline --progress --config build/webpack.dev.conf.js` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the vueweb@1.0.0 dev script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above.npm ERR! A complete log of this run can be found in: npm ERR! C:\Users\Administrator\AppData\Roaming\npm-cache\_logs\2019-12-10T13_06_55_461Z-debug.log不要慌運行npm install,等待安裝完畢之后,在點擊npm run dev
在瀏覽器輸入http://localhost:8080
顯示該頁面即可。
目錄結構
| build | 項目構建(webpack)相關代碼 |
| config | 配置目錄,包括端口號等。我們初學可以使用默認的。 |
| node_modules | npm 加載的項目依賴模塊 |
| src | 這里是我們要開發的目錄,基本上要做的事情都在這個目錄里。里面包含了幾個目錄及文件:assets: 放置一些圖片,如logo等。components: 目錄里面放了一個組件文件,可以不用。App.vue: 項目入口文件,我們也可以直接將組件寫這里,而不使用 components 目錄。main.js: 項目的核心文件。 |
| static | 靜態資源目錄,如圖片、字體等。 |
| test | 初始測試目錄,可刪除 |
| .xxxx文件 | 這些是一些配置文件,包括語法配置,git配置等。 |
| index.html | 首頁入口文件,你可以添加一些 meta 信息或統計代碼啥的。 |
| package.json | 項目配置文件。 |
| README.md | 項目的說明文檔,markdown 格式 |
現在我們來修改一些配置:
在src/router/index.js中的export default new Router({后面添加mode:‘history’,這樣可以讓路徑上的#去掉。
找到src/components/HelloWorld.vue,我們在學習路由(router)之前就以HelloWorld.vue頁面為模板進行開發
這個時候瀏覽器頁面會顯示為這樣,不用管他:
起步
使用之前有一些注意事項需要說明一下:
所有頁面文件后綴必須為.vue,后面會講到怎么使用
Vue文件中基本要有的三個標簽:template、script、style`
Vue模板語法
Vue.js 使用了基于 HTML 的模板語法,允許開發者聲明式地將 DOM 綁定至底層 Vue 實例的數據。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循規范的瀏覽器和 HTML 解析器解析。
插值
數據綁定最常見的方式就是用雙大括號來顯示,代碼中{{ msg }}中的msg與下面data中的msg相互綁定。下面msg屬性發生改變,那么插值處的內容也會更新。
<template><div class="hello"><h1>{{ msg }}</h1> </div> </template><script> export default {name: 'HelloWorld',data () {return {msg: 'Welcome to Your Vue.js App'}} } </script>嘗試一下
雙大括號僅僅顯示的是普通文本,如果想輸出正在的HTML,那么需要使用v-html指令:
<template><div class="hello"><p>這是普通文本:{{ msg }}</p><p>這是HTML:<span v-html="msg"></span></p></div> </template><script>export default {name: 'HelloWorld',data() {return {msg: '<span style = "color:red"> Welcome<span>'}}} </script>嘗試一下
HTML屬性的值應使用v-bind指令來改變。
<template><div class="hello"><label for="r1">修改背景顏色</label><input type="checkbox" v-model="use" id="r1"><label for="r2">隱藏</label><input type="checkbox" v-model="hidd" id="r2"><p v-bind:class="{'class1': use}" v-bind:hidden="hidd"><span v-html="msg"></span></p></div> </template><script>export default {name: 'HelloWorld',data() {return {msg: '<span style = "color:red"> Welcome<span>',use : false,hidd: false}}} </script><!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped>.class1{background-color: #B5D592;} </style>嘗試一下
以下實例判斷 class1 的值,如果為user為 true 使用 class1 類的樣式,否則不使用,hidd為true則使用hidden屬性,否則不使用。
JavaScript表達式
Vue中提供了完全的JavaScript表達式的支持。
嘗試一下
Vue.js 允許你自定義過濾器,被用作一些常見的文本格式化。由"|"指示,使用過濾器完成和上面一樣的想過:
<template><div class="hello">{{ ok | filter1 }}<br/><!--三元運算-->{{ message }}<br/><!--反向輸出--></div> </template><script>export default {name: 'HelloWorld', data() {return {message: 'vijar-wang.github.io',ok: false}},filters:{filter1:function(value){// value為 | 前面的值if(value){value = 'ok的值為true'}else{value = 'ok的值為false'}return value},filter2:function(value){value = value.split('').reverse().join('')return value;}}} </script><!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>嘗試一下
Vue條件語句
Vue提供v-if指令來判斷元素是否渲染,同時還有v-else表示else,v-else-if表示if else,但是注意else必須緊跟在v-if下面,否則不會渲染。
<template><div class="hello"><h1 v-if="ok">Yes</h1><h2 v-else-if="!ok">No</h2><h2 v-else>{{ok}}</h2></div> </template><script>export default {name: 'HelloWorld', data() {return {ok: true}}} </script><!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>嘗試一下
還有v-show來判斷是否渲染
<h1 v-show="ok">Hello!</h1>Vue循環語句
Vue的循環使用v-for指令,v-for指令需要以site in sites的形式的語法,sites是數組,site是迭代元素的別名。使用命令時加載需要遍歷的標簽上即可。
<template><ul><li v-for="(week,index) in weeks">{{index}}:{{week}}</li></ul> </template><script>export default {name: 'HelloWorld',data() {return {weeks: ['Monday', "Tuesday", "Wednesday", 'Thursdat', 'Friday', 'Staurday', 'Sunday']}}} </script><!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped>ul li {list-style: none;} </style>嘗試一下
渲染結果:
- 0:Monday
- 1:Tuesday
- 2:Wednesday
- 3:Thursdat
- 4:Friday
- 5:Staurday
- 6:Sunday
關鍵詞computed,在處理一些復雜邏輯時是很有用的,
<template><div><p>原始字符串: {{ message }}</p><p>計算后反轉字符串: {{ reversedMessage }}</p></div> </template><script>export default {name: 'HelloWorld',data() {return {message: 'vijar-wang.github.io'}},computed: {reversedMessage: function() {return this.message.split('').reverse().join('')}}} </script><!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>嘗試一下
渲染結果
原始字符串: vijar-wang.github.io
計算后反轉字符串: oi.buhtig.gnaw-rajiv
# Vue監聽屬性可以通過 watch 來響應數據的變化
<template><div>千米 : <input type="text" v-model="kilometers">米 : <input type="text" v-model="meters"></div> </template><script>export default {name: 'HelloWorld',data() {return {kilometers: 0,meters: 0}},watch: {kilometers: function(val) {this.kilometers = val;this.meters = this.kilometers * 1000},meters: function(val) {this.kilometers = val / 1000;this.meters = val;}}} </script><!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>嘗試一下
Vue事件處理
可以用 v-on 指令監聽 DOM 事件,并在觸發時運行一些 JavaScript 代碼。
點擊事件
<template><div><button v-on:click="kilometers++">點擊第{{kilometers}}次</button></div> </template><script>export default {name: 'HelloWorld',data() {return {kilometers: 0}}} </script><!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style> 點擊第 0次 [嘗試一下](https://www.runoob.com/try/try.php?filename=vue2-v-on3)除了點擊事件,還有其他事件修飾
<!-- 阻止單擊事件繼續傳播 --> <a v-on:click.stop="doThis"></a><!-- 提交事件不再重載頁面 --> <form v-on:submit.prevent="onSubmit"></form><!-- 修飾符可以串聯 --> <a v-on:click.stop.prevent="doThat"></a><!-- 只有修飾符 --> <form v-on:submit.prevent></form><!-- 添加事件監聽器時使用事件捕獲模式 --> <!-- 即元素自身觸發的事件先在此處理,然后才交由內部元素進行處理 --> <div v-on:click.capture="doThis">...</div><!-- 只當在 event.target 是當前元素自身時觸發處理函數 --> <!-- 即事件不是從內部元素觸發的 --> <div v-on:click.self="doThat">...</div><!-- 點擊事件將只會觸發一次 --> <a v-on:click.once="doThis"></a>按鍵處理
<!-- 只有在 `keyCode` 是 13 時調用 `vm.submit()` --> <input v-on:keyup.13="submit">各按鍵的值如下:
| 48到57 | 0到9 |
| 65到90 | a到z(A到Z) |
| 112到135 | F1到F24 |
| 8 | BackSpace(退格) |
| 9 | Tab |
| 13 | Enter(回車) |
| 20 | Caps_Lock(大寫鎖定) |
| 32 | Space(空格鍵) |
| 37 | Left(左箭頭) |
| 38 | Up(上箭頭) |
| 39 | Right(右箭頭) |
| 40 | Down(下箭頭) |
但是記住每個keyCode時很不容易的,Vue 為最常用的按鍵提供了別名,使用方法:
<template><div><!-- <button v-on:click="kilometers++">點擊第{{kilometers}}次</button> -->測試enter:<input v-on:keyup.enter="enterKey()" /><br/>測試spaceKey:<input v-on:keyup.space="spaceKey()" /><br/>測試escKey:<input v-on:keyup.esc="escKey()" /><br/>測試delete:<input v-on:keyup.delete="deleteKey()" /><br/></div> </template><script>export default {name: 'HelloWorld',data() {return {kilometers: 0,meters: 0}},methods:{enterKey(){ alert("你按下了enter鍵")},spaceKey(){ alert("你按下了space鍵")},escKey(){ alert("你按下了esc鍵")},deleteKey(){ alert("你按下了delete鍵")}}} </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>全部的按鍵別名:
- .enter
- .tab
- .delete (捕獲“刪除”和“退格”鍵)
- .esc
- .space
- .up
- .down
- .left
- .right
可以通過全局 config.keyCodes 對象自定義按鍵修飾符別名:
// 可以使用 `v-on:keyup.f1`Vue.config.keyCodes.f1 = 112向上面的按鍵監聽可以改為動態的監聽
<template><div></div> </template><script>export default {name: 'HelloWorld',data() {return {kilometers: 0,meters: 0}},created() {document.onkeydown = function(e){var key = window.event.keyCode;if(key == 13){alert("按下了enter");}else if(key == 32){alert("按下了Space");}}}} </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>這樣在點擊enter和space的時候就會彈出提示框。
鼠標監聽
- .left
- .right
- .middle
這些修飾符會限制處理函數僅響應特定的鼠標按鈕。
Vue表單綁定
你可以用 v-model 指令在表單 、 及 `` 元素上創建雙向數據綁定。
<template><div><input v-model="name" /></div> </template><script>export default {name: 'HelloWorld',data() {return {name: "小明"}}} </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>當data中name的值發生改變,表單中的值也會發生改變。
嘗試一下
不僅僅是輸入框,復選框,單選框、select也可以雙向綁定。 <template><div><h5>單選測試</h5><br /><input v-model="redio" value="false" id="false" type="radio" name="tadiotest" /><label for="false">博主是帥哥</label><input v-model="redio" value="true" id="true" type="radio" name="tadiotest" /><label for="true">博主是帥哥</label><p>你選擇了:{{redio}}</p><h5>復選框測試</h5><br /><input type="checkbox" id="xigua" value="西瓜" v-model="check" /><label for="yes">西瓜</label><input type="checkbox" id="juzi" value="橘子" v-model="check" /><label for="juzi">橘子</label><input type="checkbox" id="taozi" value="桃子" v-model="check" /><label for="taozi">桃子</label><p>你選擇了:{{check}}</p><h5>下拉框測試</h5><br /><select v-model="selected" name="fruit"><option value="">選擇一個</option><option value="軟件技術">軟件技術</option><option value="網絡技術">網絡技術</option></select><p>你選擇了:{{selected}}</p></div> </template><script>export default {name: 'HelloWorld',data() {return {redio:"false",check:[],selected:""}}} </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>修飾符
.lazy
在默認情況下,v-model 在每次 input 事件觸發后將輸入框的值與數據進行同步 (除了上述輸入法組合文字時)。你可以添加 lazy 修飾符,從而轉變為使用 change事件進行同步:
<!-- 在“change”時而非“input”時更新 --><input v-model.lazy="msg" >.number
如果想自動將用戶的輸入值轉為數值類型,可以給 v-model 添加 number 修飾符:
<input v-model.number="age" type="number">這通常很有用,因為即使在 type="number" 時,HTML 輸入元素的值也總會返回字符串。如果這個值無法被 parseFloat() 解析,則會返回原始的值。
.trim
如果要自動過濾用戶輸入的首尾空白字符,可以給 v-model 添加 trim 修飾符:
<input v-model.trim="msg">Vue組件
組件是可復用的 Vue 實例,且帶有一個名字:在這個例子中是 ``。我們可以在一個通過 new Vue 創建的 Vue 根實例中,把這個組件作為自定義元素來使用。
定義全局組件
在main.js文件中加入以下代碼,然后再想要使用的頁面直接調用標簽就好,com1為全局組件。
var com = {template: '<h1>這是一個全局自定義的組件</h1>'} Vue.component("com1",com)定義局部組件
<template><div><com></com></div> </template><script>var com = {template: '<h1>這是一個自定義的組件</h1>'}export default {name: 'HelloWorld',data() {return {}},components:{'com':com}} </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>本例中的com就是局部組件,只能在這一個頁面中使用。
如果自定義的組件是一個頁面,那么使用import導入,例如你創建一個tmp.vue的文件作為模板,你可以這樣使用它:
import Tmp from '@/commponents/tmp' //@符號代表src目錄 Vue.component("Tmp",Tmp)如果是要在全局引入,可以把上面代碼寫到main.js文件中去。
HTML 中的特性名是大小寫不敏感的,所以瀏覽器會把所有大寫字符解釋為小寫字符。這意味著當你使用 DOM 中的模板時,camelCase (駝峰命名法) 的 prop 名需要使用其等價的 kebab-case (短橫線分隔命名) 命名Prop
prop 是父組件用來傳遞數據的一個自定義屬性。
父組件的數據需要通過 props 把數據傳給子組件,子組件需要顯式地用 props 選項聲明 “prop”
<template><div><com message="message屬性"></com></div> </template><script>var com = {props:["message"],template: '<h1>{{message}}</h1>'}export default {name: 'HelloWorld',components:{'com':com}} </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>前面靜態綁定Prop,動態綁定可以通過v-bind指令來綁定:
<template><div><input v-model="msg" /><br /><com v-bind:message="msg"></com></div> </template><script>var com = {props: ["message"],template: '<h1>{{message}}</h1>'}export default {name: 'HelloWorld',data() {return {msg: "動態綁定內容"}},components: {'com': com}} </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>這里只要改變表單中的內容,自定義組件中的內容也會改變
Vue自定義事件、指令
前面講了父組件向子組件傳值,那么從子組件向父組件傳值就需要用到自定義事件了
自定義事件
只配合一個事件名使用 $emit:
<template><div><my-button v-on:welcome="coInfo"></my-button></div> </template><script>var butt = {template: '<button v-on:click="$emit(\'welcome\')">點擊我</button>'}export default {name: 'HelloWorld',methods:{coInfo(){console.log("123");}},components: {'my-button': butt}} </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>上面實例是一個簡單的自定義事件,使用了Vue的$emit API
創建一個普通的按鈕自定義組件,給他一個自定義事件welcome然后在使用該組件的時候通過點擊點擊coInfo方法。
配合額外的參數使用 $emit:
<template><div><my-button v-on:welcome="coInfo"></my-button></div> </template><script>var butt = {template: '<button v-on:click="addValue">點擊我</button>',data(){return{num : 0}},methods:{addValue(){this.num = this.num +1;this.$emit("welcome",this.num);}}}export default {name: 'HelloWorld',methods:{coInfo(num){console.log(num);}},components: {'my-button': butt}} </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>在這里發現和上面不同的是$emit中多了個參數?,F在解釋一下全部代碼。butt還是一個自定義組件,但是這個組件中包含了data參數(注意data格式)num,以及方法addValue。當點擊自定義組件按鈕時,num就會+1輸出到控制臺上。
自定義指令
除了默認的指令(v-model和v-bind),Vue也允許用戶自定義指令。
舉個聚焦輸入框的例子:
<template><div><input v-focus /></div> </template><script>export default {name: 'HelloWorld',methods:{},directives:{ //自定義指令組件focus:{ //指令名稱inserted:function(el){ //inserted為鉤子函數el.focus()el.placeholder = "獲取到焦點"}}}} </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style> ## 鉤子鉤子函數
一個指令定義對象可以提供如下幾個鉤子函數 (均為可選):
-
bind:只調用一次,指令第一次綁定到元素時調用。在這里可以進行一次性的初始化設置。
-
inserted:被綁定元素插入父節點時調用 (僅保證父節點存在,但不一定已被插入文檔中)。
-
update:所在組件的 VNode 更新時調用,但是可能發生在其子 VNode 更新之前。指令的值可能發生了改變,也可能沒有。但是你可以通過比較更新前后的值來忽略不必要的模板更新 (詳細的鉤子函數參數見下)。
-
componentUpdated:指令所在組件的 VNode 及其子 VNode 全部更新后調用。
-
unbind:只調用一次,指令與元素解綁時調用。
鉤子函數參數
指令鉤子函數會被傳入以下參數:
-
el:指令所綁定的元素,可以用來直接操作 DOM 。
binding:一個對象,包含以下屬性:
name:指令名,不包括 v- 前綴。
value:指令的綁定值,例如:v-my-directive="1 + 1" 中,綁定值為 2。
oldValue:指令綁定的前一個值,僅在 update 和 componentUpdated 鉤子中可用。無論值是否改變都可用。
expression:字符串形式的指令表達式。例如 v-my-directive="1 + 1" 中,表達式為 "1 + 1"。
arg:傳給指令的參數,可選。例如 v-my-directive:foo 中,參數為 "foo"。
modifiers:一個包含修飾符的對象。例如:v-my-directive.foo.bar 中,修飾符對象為 { foo: true, bar: true }。
-
vnode:Vue 編譯生成的虛擬節點。移步 VNode API 來了解更多詳情。
-
oldVnode:上一個虛擬節點,僅在 update 和 componentUpdated 鉤子中可用。
鉤子函數即為directives組件的函數,函數參數及為function()括號中的參數。
Vue路由
官方路由
對于路由官方文檔講的非常詳細。這里簡單示范一下路由的基本用發,如果需要用查看更多的內容請去文檔,vue-router 文檔
Vue項目中使用
Vue項目因為是用webpack模板,所以src目錄下會自帶一個router目錄,其中index.js及為路由的配置文件
默認index.js內容為:
import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld'Vue.use(Router)export default new Router({routes: [{path: '/',name: 'HelloWorld',component: HelloWorld}] })在main.js中有一行import router from './router',即為導入路由配置文件。
這里以一個登錄項目為例、
首先在src/cpmponents目錄下模仿HelloWorld新建兩個vue文件。
Login.vue
<template><div><form name="form1"><label for="username">用戶名</label><input id="username" v-model="username" name="username" /><br /><label for="password">密碼</label><input id="password" v-model="password" name="password" /></form><button @click="login()">登錄</button><p style="color: red;" id="msg">{{msg}}</p></div> </template><script>export default{name: "login",data(){return{username:'', //用戶名password:'', //密碼msg:"" //提示信息}},methods:{login(){// 登錄的用戶名為 'xiaoming',密碼為 '123'if(this.username == "xiaoming" && this.password == "123"){// 路由的編程式導航,還有其他的看下面this.$router.push({path:"/index", //跳轉路徑query:{ //使用query攜帶參數,會顯示在url上面username:this.username}})}else{this.msg = "用戶名或密碼錯誤!"}}}} </script><style> </style>Index.vue
<template><div><h1 v-if="username!=''">歡迎您!{{username}}</h1> <h1 v-else>您未登錄!</h1></div> </template><script>export default{namme:"index",data(){return{username :""}},created() { //當頁面創建時加載this.username = this.$route.query.username; //接收路由參數}} </script><style> </style>配置路由index.js文件:
import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' import Login from '@/components/Login' import Index from '@/components/Index'Vue.use(Router)export default new Router({routes: [{path: '/',name: 'HelloWorld',component: HelloWorld,meta:{title:"HelloWorld"}},{path: '/login',name: 'login',component: Login,meta:{title:"登錄"}},{path: '/index',name: 'index',component: Index,meta:{title:"首頁"}}] })默認模式,在main.js中加入:
router.beforeEach((to, from, next) => {if(to.meta.title){document.title = to.meta.titlenext()} })history模式在main.js中加入:
if(router.history.current.meta.title){document.title = router.history.current.meta.title; }這樣配置在默認路由下可以顯示title。
初步分析,頁面之間的調用關系如圖:
詳解
路由的導航分為聲明式導航和編程式導航
| <router-link :to="..."> | router.push(...) |
聲明式路由<router-link>標簽會被渲染成一個a標簽,傳遞參數形式為:
<router-link :to="{path:'/login', query:{name:username}}">編程式路由
注意,path和params不能同時使用,否則params會失效。使用path會在URL上面顯示傳遞的數據,要想不顯示就是用name
數據獲取
在路由到的界面使用watch組件來監聽路由是否有變化。
watch: {// 如果路由有變化,會再次執行fetchData方法'$route': 'fetchData' }, methods:{fetchData(){this.$route.params.userId; //若是使用的query則吧params換成`query`} }心細的人會發現,前面跳轉頁面為$router,接收數據為$route,這里要注意是不一樣的。
相關屬性
replace
跟 router.push 很像,唯一的不同就是,它不會向 history 添加新記錄,而是跟它的方法名一樣 —— 替換掉當前的 history 記錄。
| <router-link :to="..." replace> | router.push(...) |
append
設置 append 屬性后,則在當前 (相對) 路徑前添加基路徑。例如,我們從 /a 導航到一個相對路徑 b,如果沒有配置 append,則路徑為 /b,如果配了,則為 /a/b
<router-link :to="{ path: '/b'}" append></router-link>例:
當前路徑:localhost:8080/a
使用append路由到/b后路徑:localhost:8080/a/b
不使用:localhost:8080/b
tag
有時候想要 渲染成某種標簽,例如。 于是我們使用 tag prop 類指定何種標簽,同樣它還是會監聽點擊,觸發導航。
<router-link to="/foo" tag="li">foo</router-link> <!-- 渲染結果 --> <li>foo</li>VueAjax
官網只介紹了如何引入axios,這里是設置全局引入
npm下載axios:
npm install axios --save全局引入axios
在main.js中加入如下代碼:
import axios from 'axios' Vue.prototype.$ajax= axios例子
添加之后就能在vue文件methods中使用$ajax,例:
執行 GET 請求
axios.get('/user?ID=12345').then(function (response) {console.log(response); //回調函數}).catch(function (error) {console.log(error); //請求失敗});// 可選地,上面的請求可以這樣做 axios.get('/user', {params: {ID: 12345}}).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});執行POST請求
axios.post('/user', {firstName: 'Fred',lastName: 'Flintstone'}).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});axios API
可以通過向 axios 傳遞相關配置來創建請求
// 發送 POST 請求 axios({method: 'post',url: '/user/12345',data: {firstName: 'Fred',lastName: 'Flintstone'} }); //axios(url[, config]) // 發送 GET 請求(默認的方法) axios('/user/12345');axios跨域問題
在config/index.js文件中找到proxyTable{},在括號中添加:
'/api': {target: 'http://localhost:8080/',//設置你調用的接口域名和端口號 別忘了加httpchangeOrigin: true,//如果需要跨域pathRewrite: {'^/api': '/'//這里理解成用面的地址,//后面組件中我們掉接口時直接用api代替 比如我要調//用'http://425.0.100.100:8888/user/add',直接寫‘/api/user/add’即可}}但是這樣處理有個問題啊,只能在開發環境使用。真正線上時還是需要封裝一下
封裝axios
在一些大型項目中會封裝axios,并且添加攔截器。在src下創建目錄utils,在utils下創建js文件fetch.js。內容如下:
import axios from 'axios'Date.prototype.Format = function (fmt) {let o = {"M+": this.getMonth() + 1,"d+": this.getDate(),"h+": this.getHours(),"m+": this.getMinutes(),"s+": this.getSeconds(),"q+": Math.floor((this.getMonth() + 3) / 3),"S": this.getMilliseconds()}if (/(y+)/.test(fmt))fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length))for (var k in o)if (new RegExp("(" + k + ")").test(fmt))fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)))return fmt } // respone攔截器 axios.interceptors.response.use(response => {return response.data }, error => {return error.data }) axios.defaults.withCredentials = falsefunction checkStatus(response) {// loading// 如果http狀態碼正常,則直接返回數據if (response && (response.status === 200 || response.status === 304 || response.status === 400)) {return response// 如果不需要除了data之外的數據,可以直接 return response.data}// 異常狀態下,把錯誤信息返回去return {status: -404,msg: '網絡異常'} }function checkCode(res) {// 如果code異常(這里已經包括網絡錯誤,服務器錯誤,后端拋出的錯誤),可以彈出一個錯誤提示,告訴用戶if (res.status === -404) {console.log(res.msg)}if (res.data && (!res.data.success)) {// alert(res.data.error_msg)}// console.log('loadding')return res }function timestampToTime(timestamp) {let date = new Date(timestamp),Y = date.getFullYear() + '-',M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-',D = date.getDate() + ' ',h = date.getHours() + ':',m = date.getMinutes() + ':',s = date.getSeconds()return Y + M + D + h + m + s }export default {post(url, data) {return axios({method: 'post',url,//data: qs.stringify(data),data,timeout: 15000,headers: {'X-Requested-With': 'XMLHttpRequest',// 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8''content-type': 'application/json;charset=UTF-8'}}).then((response) => {return response}).then((res) => {return res})},upload(url, data) {let form = new FormData()Object.keys(data).forEach(value => {form.append(value, data[value])})return axios({method: 'post',// baseURL: process.env.BASE_API,url,data,transformRequest: [function (data) {let ret = ''for (let it in data) {ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'}return ret}],timeout: 15000,headers: {// 'X-Requested-With': 'XMLHttpRequest','Content-Type': 'application/x-www-form-urlencoded'}}).then((response) => {return response}).then((res) => {return res})},get(url, params) {return axios({method: 'get',// baseURL: process.env.BASE_API,url,params, // get 請求時帶的參數timeout: 15000}).then((response) => {return response}).then((res) => {return res})},put(url, data) {return axios({method: 'put',baseURL: process.env.BASE_API,url,data,timeout: 15000}).then((response) => {return response}).then((res) => {return res})},time(tamp) {return timestampToTime(tamp)} }然后再main.js中加入以下代碼:
import fetch from './utils/fetch'const extend = Vue.prototype extend.$post = fetch.post extend.$get = fetch.get extend.$form = fetch.form然后再vue文件使用的時候就很方便了:
this.$post('http://localhost:8080/Mybatis_war_exploded/upload.do',imageFile).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});結束
教程到這里就結束了,新手小白。寫這個一邊寫一邊自己做的,如果有錯誤的地方請留言多多指教。
總結
以上是生活随笔為你收集整理的Vue教程路由以及axios的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Nginx的proxy_pass及ups
- 下一篇: 查找DOM,受控与非受控组件