Vue從零到實戰

一、Vue核心知識瞭解

1.1、初識VUE,走進VUE的世界

歷史介紹

angular 09年,年份較早,一開始大家是拒絕 star:59.3k
react 2013年, 用戶體驗好,直接拉到一堆粉絲 star:119k
vue 2014年, 用戶體驗好 star:124k

Vue等框架與jQuery的區別

jQuery是基於操作dom的庫
Vue框架是以數據驅動和組件化開發爲核心

1.2、引包、留坑、實例化 、插值表達式{{}}

引包
確認已經下載了node,然後執行命令 npm install vue (如需下載自己要的版本在vue後面加上@版本號);
頁面引入剛下載的包:

<script type="text/javascript" src="vue.js"></script>

留坑

即留一個vue模板插入的地方或者是vue代碼對其生效的地方

實例化 即啓動Vue

啓動:
 new Vue({el:目的地,template:模板內容});實例化傳入的是一個對象options

options
目的地 el 對應上面留坑的坑位,可通過id名,類名,標籤名來查找 。方式和jq一樣
內容 template
數據 data 值爲函數形式也可是對象,但是都是用函數,因爲用的函數最後也是return一個對象

插值表達式:{{ }}

插值表達式內填入data裏面的變量即可在頁面取到變量值{{ data裏的變量 }}

實例:

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<!-- 留坑,爲了後邊在這裏插值 -->
	<div id="app"></div>

	<!-- 引包 -->
	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		// 實例化啓動vue
		new Vue({
			el:'#app',//目的的,可以識別類名、id名和標籤名,如果做到極致優化可以直接用document.getElementById獲取
			template:`     //注意:template模板內容裏的根節點只能有一個(最外層只能有一個div,不能再有span、div等節點了)
			<div>
				<div>我這裏是模板內容{{ msg }}</div>
				<div>111</div>
			</div>
			`,
			data:function(){
				return {
					msg:'Hello Vue!'
				}
			}
		})
	</script>
</body>
</html>

結果:
在這裏插入圖片描述

1.3、熟悉及使用常用指令

什麼是指令

在vue中提供一些對於頁面+數據的更爲方便的操作,這些操作就叫做指令。
指令就是以數據去驅動DOM行爲的,簡化DOM操作;
如在HTML頁面中這樣使用<div v-xxx=''></div>,在vue中v-xxx就是vue的指令;

常用的指令及怎麼使用這些指令

v-text 不可解析html標籤   必須是雙標籤
v-html 可解析html標籤

v-if 判斷後,做元素的插入(append)和移除(remove)操作
v-else-if
v-else

v-show  判斷是否隱藏,display:none 和display:block的切換

v-for

數組 item,index
對象 value,key ,index

代碼案例:

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<div id="app"></div>
	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		
		new Vue({
			el:'#app',
			template:`
			<div>
					<!--測試v-text-->
					<div v-text='mytext'></div>
					</hr>
					<!--測試v-html-->
					<div v-html='myhtml'></div>
					<!--測試v-if  v-else-if  v-else-->
					<button v-if='num==1'>測試v-if</button>
					<button v-else-if='num==2'>測試v-else-if</button>
					<button v-else>測試v-else</button>

					<!--測試v-show-->
					<div v-show='checkshow'>我是V-SHOW</div>
					
					<!--循環數組-->
					<ul>
					<!--item:數組裏的每一項,index:數組索引-->
					<li v-for='(item,index) in arrayfor'>
					{{ item }}-{{index}}
					</li>
					</ul>
					
					<ul>
					<!--循環對象-->
					<li v-for='(oj,key) in ojfor'>
					{{key}}:{{oj}}
					</li>
					</ul>
			</div>
			`,
			data:function(){
				return {
					mytext:'<h1>我這裏是v-text</h1>',
					myhtml:'<h1>我這裏是v-html</h1>',
					//1:測試v-if  2:測試v-else-if  其他值:測試v-else
					num:6,
					//true:顯示,false:隱藏
					checkshow:true,
					//定義數組
					arrayfor:['籃球','足球','乒乓球'],
					//定義一對象
					ojfor:{play:'籃球',people:'ming',age:'19'}
				}
			}
		})
	</script>
</body>
</html>

效果:
在這裏插入圖片描述

1.4、闡述vue單雙向數據流及事件綁定

vue單向數據流綁定屬性值 v-bind: (屬性) 簡寫 :(屬性)

單向數據綁定 內存(js)改變影響頁面改變(js的改變會影響頁面,但是頁面的改變不會影響js)
例子:<input v-bind:value="name" v-bind:class="name">
v-bind就是對屬性的簡單賦值,當內存中值改變,還是會觸發重新渲染

vue雙向數據流 v-model 只作用於有value屬性的元素

例子:<input v-model="name" v-bind:class="name">
雙向數據綁定 頁面對於input的value改變,能影響內存中name變量
內存js改變name的值,會影響頁面重新渲染最新值

單雙向數據流代碼

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<div id="app"></div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		console.log(this)
		new Vue({
			el:"#app",
			template:`
				<div>
				單向數據綁定
				<input type='text' v-bind:value="name" :class="name"><br>
				雙向數據綁定
				<input type='text' v-model="name"></br>
				{{ name }}
				</div>
			`,
			data:function(){
				return {
					name:'hello'
				}
			}
			
		})
	</script>
</body>
</html>

效果:
在這裏插入圖片描述
事件綁定:v-on:事件名=“表達式||函數名”, 簡寫: @事件名=“表達式||函數名”

事件名可以是原生也可以是自定義的
<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<div id="app"></div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		console.log(this)
		new Vue({
			el:"#app",
			template:`
				<div>
				單向數據綁定
				<input type='text' v-bind:value="name" :class="name"><br>
				雙向數據綁定
				<input type='text' v-model="name"></br>
				{{ name }}
				<button v-on:click="change">點擊我改變name變量</button>
				</div>

			`,
			data:function(){
				return {
					name:'hello'
				}
			},
			methods:{
				change:function(){
					//console.log(this)
					this.name='我改變了,是在方法屬性裏面定義的方法'
				},
			}
		})
	</script>
</body>
</html>

效果:
在這裏插入圖片描述
總結

v-model 雙向數據綁定:
vue頁面改變影響內存(js)
內存(js)改變影響vue頁面;

v-bind 單向數據綁定只是內存(js)改變影響vue頁面

1.5、過濾器

簡介:如何給數據添加一個管道進行進一步處理再輸出

過濾器就是可以對我們的數據進行添油加醋然後再顯示

過濾器有全局過濾器和組件內的過濾器

全局過濾器Vue.filter('過濾器名',過濾方式fn );
組件內的過濾器 filters:{ '過濾器名',過濾方式fn }
{{ msg | 過濾器名}}
最終都是在過濾方式fn裏面return產出最終你需要的數據

vue中的this是vue封裝好給我們使用的,跟平常方法裏面的this是不同的

代碼展示:

<!DOCTYPE html>
<html>
<head>
	<title>過濾器</title>
</head>
<body>
		<div id="app">
			我輸入的:<input type="text" name="" v-model='instring'></br>
			我輸出的:{{ instring }}</br>
			<!--將instring作爲參數傳到reversal過濾器裏,這裏最後顯示的結果就是過濾器返回的結果-->
			翻轉輸出::{{ instring | reversal}}
		</div>

		<script type="text/javascript" src="vue.js"></script>
		<script type="text/javascript">
			new Vue({
				el:'#app',
				data(){
					return {
						instring:''
					}
				},
				//組件內過濾器
				 filters:{
				    //reversal:過濾器名字
				 	reversal(val){
				    // 字符串轉數組後進行翻轉,將翻轉後的數組轉爲字符串
					return  val.split('').reverse().join('')
				 	}
				 }
			})
		</script>
</body>
</html>

結果:
在這裏插入圖片描述
上邊是組件內過濾器,下邊介紹全局過濾器

<!DOCTYPE html>
<html>
<head>
	<title>過濾器</title>
</head>
<body>
		<div id="app">
			我輸入的:<input type="text" name="" v-model='instring'></br>
			我輸出的:{{ instring }}</br>
			{{ instring | reversal('翻轉輸出:')}}
		</div>

		<script type="text/javascript" src="vue.js"></script>
		<script type="text/javascript">
		//過濾器名字加引號
			Vue.filter('reversal',function(val,arg2){
				return  arg2+val.split('').reverse().join('')
			})
			new Vue({
				el:'#app',
				data(){
					return {
						instring:''
					}
				}
			})
		</script>
</body>
</html>

1.6、數據監聽watch與計算屬性computed

數據的單個監聽以及多個監聽還有深度監聽的不同

watch監聽單個,computed監聽多個

思考業務場景:

類似淘寶,當我輸入某個人名字時,我想觸發某個效果
利用vue做一個簡單的計算器
當watch監聽的是複雜數據類型的時候需要做深度監聽(寫法如下)

watch:{
            msg:{
              handler(val){
               if(val.text=='love'){
                alert(val.text)
               }
              },
              deep:true//開啓深度監聽
            }
          }
computed 監視對象,寫在了函數內部, 凡是函數內部有this.相關屬性,改變都會觸發當前函數

代碼展示:
監聽一般數據類型:

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<div id="app">
		<div>watch監聽數據</div>
		<input type="text" name="" v-model='msg'>
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		
		new Vue({
			el:'#app',
			data(){
				return {
					msg:‘’
				}
			},

			watch:{
				msg:{
					msg(newval,oldval){
						if(newval.text=='love'){
							alert(newval.text)
						}
					}
				}
			}
		})
	</script>
</body>
</html>

複雜數據類型監聽

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<div id="app">
		<div>watch監聽數據</div>
		<input type="text" name="" v-model='msg.text'>
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		
		new Vue({
			el:'#app',
			data(){
				return {
					msg:{text:''}
				}
			},

			watch:{
				msg:{
					handler(newval,oldval){
						if(newval.text=='love'){
							alert(newval.text)
						}
					},
					//開啓深度監聽(監聽複雜數據時開啓深度監聽,一層一層監聽裏邊的數據)
					deep:true
				}
			}
		})
	</script>
</body>
</html>

效果:
在這裏插入圖片描述
計算屬性,做一個計算器

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<div id="app">
		<div>computed計算屬性</div>
		(<input type="text" name="" v-model='n1'>+
		<input type="text" name="" v-model='n2'>)*
		<input type="text" name="" v-model='n3'>={{result}}
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		
		new Vue({
			el:'#app',
			data(){
				return {
					n1:'',
					n2:'',
					//默認值設置爲1
					n3:'1'
				}
			},
			computed:{
				result(){
					return (Number(this.n1)+Number(this.n2))*Number(this.n3)
				}
			}
		})
	</script>
</body>
</html>

結果:
在這裏插入圖片描述

二、組件化開發知識介紹

2.1、組件化開發

簡介:講述頁面拆分爲組件進行開發和維護

創建組件的兩種方式:
方式一、var Header = { template:'模板' , data是一個函數,methods:功能,components:子組件們 }//局部聲明​
方式二、Vue.component('組件名',組件對象);//全局註冊 等於註冊加聲明瞭
 
組件類型:
通用組件(例如表單、彈窗、佈局類等)
業務組件(抽獎、機器分類)
頁面組件(單頁面開發程序的每個頁面的都是一個組件、只完成功能、不復用)
組件開發三步曲:聲明、註冊、使用

代碼展示:

<!DOCTYPE html>
<html>
<head>
	<title>組件化開發</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
	    //局部聲明組件
		var MyHeader={
			template:`
				<div>我是頭部</div>
			`,

		}
		//局部聲明組件
		var MyBody=Vue.extend({
			template:`
				<div>我是身體</div>
			`
		})
		//這個是語法糖
		// var MyBody={
		// 	template:`
		// 		<div>我是身體</div>
		// 	`
		// }
		//全局創建組件
		Vue.component('MyFooter',{
			template:`
				<div>我是尾部</div>
			`
		})
		new Vue({
			el:'#app',
			//註冊組件
			components:{
				MyHeader,
				MyBody
			},
			template:`
			    //使用組件
				<div>
					<my-header></my-header>
					<my-body></my-body>
					<my-footer></my-footer>
				</div>
			`,
			data(){
				return{}
			},
		})
	</script>
</body>
</html>

效果:
在這裏插入圖片描述

2.2、slot插槽和ref、$parent

簡介:講述如何設計可擴展組件及獲取子組件和父組件實例

slot插槽(組件嵌套組件的話就使用slor)

slot就是子組件裏給DOM留下的坑位
<子組件>DOM</子組件>
slot是動態的DOM
ref獲取子組件實例

識別:在子組件或元素上使用屬性ref="xxxx"
獲取:this.$refs.xxxx 獲取元素
$el 是拿其DOM
$parent獲取父組件實例(可在子組件直接使用this.$parent即可)

代碼展示:

<!DOCTYPE html>
<html>
<head>
	<title>組件化開發</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		var Parent={
			template:`
				<div>
				我是父組件
				<slot name='hello'></slot>
				</div>
			`,
		}
		
		new Vue({
			el:'#app',
			components:{
				Parent
			},
			template:`
				<div>
					<parent>
					    //不指定name值,這裏是無效的
						<div>我是插槽內容</div>
						//指定了name值,是有效果的
						<div slot='hello'>我是插槽內容2</div>
					</parent>
				</div>
			`,
			data(){
				return{}
			},
		})
	</script>
</body>
</html>

效果:
在這裏插入圖片描述
代碼展示2:

<!DOCTYPE html>
<html>
<head>
	<title>組件化開發</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		var Child={
			template:`
				<div>我是子組件</div>
			`,
			data(){
				return {
					msg:'hello'
				}
			},
			created(){
				console.log(this.$parent)
			}

		}
		var Parent={
			template:`
				<div>
				我是父組件
				<slot name='hello'></slot>
				<child ref='childs'></child>
				</div>
			`,
			components:{
				Child
			},
			data(){
				return {
					parents:'我是父組件'
				}
			},
			mounted(){
				// console.log(this.$refs.childs)
			}
		}
		
		new Vue({
			el:'#app',
			components:{
				Parent
			},
			template:`
				<div>
					<parent>
						<div>我是插槽內容</div>
						<div slot='hello'>我是插槽內容2</div>
					</parent>
				</div>
			`,
			data(){
				return{}
			},
		})
	</script>
</body>
</html>

效果:
在這裏插入圖片描述

2.3、父子組件的通信

簡介:搭起專屬於父子組件之間的溝通橋樑

父傳子:(父親傳遞數據給子)
父用子的時候通過屬性傳遞
子要聲明props:['屬性名'] 來接收
子收到後就是自己的了,隨便用
     1、在template中 直接可以用
     2、在js中使用   this.屬性名  的方式用

子傳父:(子傳遞數據給父親)
子組件裏通過$emit('自定義事件名',變量1,變量2)觸發
父組件@自定義事件名=‘事件名’監聽
子組件方法裏  this.$emit('sendfather',val1,val2)觸發自定義事件
父組件裏  <child @sendfather='mymethods'></child>

父傳子實例展示:

<!DOCTYPE html>
<html>
<head>
	<title>父子組件的通信</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		//定義子組件,子組件定義好了props,接收到數據後直接用
		var Child={
			template:`
				<div>
				我是子組件{{sendchild}}
				</div>
			`,
			//這裏接收父親傳遞過來的數據,接收到以後,像上邊那樣隨便用即可
			props:['sendchild'],
		}
		//定義一個父組件,父組件通過屬性sendchild傳遞了數據給子組件
		var Parent={
			template:`
				<div>
				我是父組件
				<child sendchild='父親給你的' ></child>
				</div>
			`,
			components:{
				Child
			}
		}
		
		new Vue({
			el:'#app',
			components:{
				Parent
			},
			template:`
				<div>
				<parent></parent>
				</div>
			`,
			data(){
				return {

				}
			},
		})
	</script>
</body>
</html>

效果:
在這裏插入圖片描述
子傳父實例展示:

<!DOCTYPE html>
<html>
<head>
	<title>父子組件的通信</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
		//子組件定義好了props直接用
		var Child={
			template:`
				<div>
				我是子組件{{sendchild}}
				<button @click='sendparent'>我要反饋東西給父親</button>
				</div>
			`,
			props:['sendchild'],
			methods:{
				sendparent(){
					this.$emit('baba','這是兒子組件給你的')
				}
			}

		}
		//父組件通過屬性sendchild傳遞了數據給子組件
		var Parent={
			template:`
				<div>
				我是父組件{{ msg }}
				//@baba,監聽事件,監聽子傳遞來的數據
				<child sendchild='父親給你的' @baba='reserve'></child>

				</div>
			`,
			components:{
				Child
			},
			data(){
				return {
					msg:''
				}
			},
			methods:{
				reserve(val){
						this.msg=val
				}
			}
		}
		
		new Vue({
			el:'#app',
			components:{
				Parent
			},
			template:`
				<div>
				<parent></parent>
				</div>
			`,
			data(){
				return {

				}
			},
		})
	</script>
</body>
</html>

效果:
在這裏插入圖片描述
在這裏插入圖片描述

2.4、非父子組件之間的通信

簡介:建立Bus總線機制實施非父子組件通訊(相當於通過中間的一個東西實現父子通信)

創建一個空實例(bus中央事件總線也可以叫中間組件)
利用$emit $on的觸發和監聽事件實現非父子組件的通信
Vue.prototype.$bus=new Vue()//在vue上面掛載一個$bus作爲中央處理組件
this.$bus.$emit('自定義事件名','傳遞的數據')//觸發自定義事件傳遞數據
this.$bus.$on('自定義事件名',fn)//監聽自定義事件獲取數據
解決的方案還有vuex、provide/inject是解決同根往下派發、本地存儲也可以進行非父子組件之間的通信

案例展示

<!DOCTYPE html>
<html>
<head>
	<title>非父子組件的通信</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript">
        //創建一個空實例,$bus可以自定義的,不是寫死的
		Vue.prototype.$bus=new Vue()
		
		var MyHeader={
			template:`
				<div>
				我是頭部
				{{ headermsg }}
				</div>
			`,
			data(){
				return {
					headermsg:'我是頭部的信息'
				}
			},
			created(){
			    //寫法一
				// var self=this
				// self.$bus.$on('sending',function(val){
				// 	self.headermsg=val
				// })
				//寫法二
				this.$bus.$on('sending',val=>{
					this.headermsg=val
				})
			}
		}
		var MyBody={
			template:`
				<div>我是身體</div>
			`,
		}
		var MyFooter={
			template:`
				<div>我是底部<button @click='sendhead'>我要跟頭部通信</button></div>
			`,
			methods:{
				sendhead(){
					this.$bus.$emit('sending','我是底部的數據')
				}
			}
		}
		new Vue({
			el:'#app',
			components:{
				MyHeader,
				MyBody,
				MyFooter
			},
			template:`
				<div>
					<my-header></my-header><hr>
					<my-body></my-body><hr>
					<my-footer></my-footer>
				</div>
			`,
			data(){
				return {}
			},
		})
	</script>
</body>
</html>

效果:
在這裏插入圖片描述
在這裏插入圖片描述

2.5、vue的生命週期

vue生命週期官方介紹

簡介:詳述vue所有的生命週期鉤子函數的作用

需要頻繁的創建和銷燬組件
比如頁面中部分內容顯示與隱藏,但是用的是v-if
組件緩存
內置組件中
被其包裹的組件,在v-if=false的時候,不會銷燬,而是停用
v-if="true" 不會創建,而是激活
避免頻繁創建組件對象的性能損耗
組件的激活和停用
activated 和 deactivated
成對比較
created 和 beforeCreate
A 可以操作數據 B 數據沒有初始化
mounted 和 beforeMount
A 可以操作DOM B 還未生成DOM
updated 和 beforeUpdate
A 可以獲取最終數據 B 可以二次修改
destroyed 和 beforeDestroy
性能調優:頻繁銷燬創建的組件使用內置組件包裹

html:

<!DOCTYPE html>
<html>
<head>
	<title>vue的生命週期</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript" src="main.js">


	</script>
</body>
</html>

js:

 // created 和 beforeCreate 

		 // A 可以操作數據 B 數據沒有初始化

		 // mounted 和 beforeMount

		 // A 可以操作DOM B 還未生成DOM

		 // updated 和 beforeUpdate

		 //  A 可以獲取最終數據 B 可以二次修改

		 // destroyed 和 beforeDestroy
		var Test={
			template:`
				<div>我是Test組件{{ msg }}
				<button @click="msg+='1'">msg+1</button>
				</div>
			`,
			data(){
				return{
					msg:'HELLO VUE'
				}
			},
			//組件創建前
			beforeCreate(){
				console.log('組件創建前')
				console.log(this.msg)
			},
			//組件創建後
			created(){
				console.log('組件創建後')
				console.log(this.msg)
			},
			//Dom掛載前
			// beforeMount(){
			// 	console.log('Dom掛載前')
			// 	console.log(document.body.innerHTML)
			// },
			// //Dom掛載後
			// mounted(){
			// 	console.log('Dom掛載後')
			// 	console.log(document.body.innerHTML)
			// }
			//基於數據更新前
			beforeUpdate(){
					console.log('數據更新前')
					console.log(document.body.innerHTML)
			},

			//基於數據更新後
			updated(){
					console.log('數據更新後')
					console.log(document.body.innerHTML)
			},
			//銷燬前
			beforeDestroy(){
				console.log('銷燬前')
			},
			//銷燬後
			destroyed(){
				console.log('銷燬後')
			},
			//組件停用
			deactivated(){
				console.log('組件停用')
			},
			//組件激活
			activated (){
				console.log('組件激活')
			}
		}
		new Vue({
			el:'#app',
			components:{
				Test	
			},
			template:`
				<div>
					<keep-alive><test v-if='testshow'></test></keep-alive></br>
					<button @click='clickbut'>銷燬組件</button>
				</div>
			`,
			data(){
				return {
					testshow:true
				}
			},
			methods:{
				clickbut(){
					this.testshow=!this.testshow
				}
			}
		})

效果:

每測試一步,可以自己在瀏覽器的控制檯查看

三、Vue核心插件之路由模塊

3.1、路由的跳轉原理(哈希模式)

簡介:瞭解vue核心插件的工作原理

單頁應用的路由模式有兩種
哈希模式(常用的模式):利用hashchange 事件監聽 url的hash 的改變
history模式:使用此模式需要後臺配合把接口都打到我們打包後的index.html上

哈希模式原理:
window.addEventListener('hashchange', function(e) {
  console.log(e)
})

哈希模式核心是錨點值的改變,我們監聽到錨點值改變了就去局部改變頁面數據,不是做跳轉。跟傳統開發模式url改變後,立刻發起請求,
響應整個頁面,渲染整個頁面比路由的跳轉用戶體驗更好;

代碼展示:

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	<a href="#/login">登錄</a>
	|
	<a href="#/register">註冊</a>
	<div id="app"></div>

	<script type="text/javascript">
		var appdiv=document.getElementById('app')

		window.addEventListener('hashchange', function(e) {
			  console.log(location.hash)
			  switch(location.hash){
			  	case '#/login':
			  	appdiv.innerHTML='我是登錄頁面';
			  	break;
			  	case '#/register':
			  	appdiv.innerHTML='我是註冊頁面';
			  	break;
			  }
			})
	</script>
</body>
</html>

效果:
在這裏插入圖片描述

3.2、 安裝和使用路由

簡介:引入路由插件,簡單瞭解單頁應用的實現

路由是以插件的形式引入到我們的vue項目中來的

vue-router是vue的核心插件:
1:下載 npm i vue-router -S
2:安裝插件Vue.use(VueRouter);
3:創建路由對象 var router = new VueRouter();
4:配置路由規則 router.addRoutes([路由對象]);
路由對象{path:'錨點值',component:要(填坑)顯示的組件}
5:將配置好的路由對象交給Vue
在options中傳遞-> key叫做 router
6:留坑(使用組件) <router-view></router-view>

代碼:

<!DOCTYPE html>
<html>
<head>
	<title>路由的安裝和使用</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<!-- 引入路由插件 -->
	<script type="text/javascript" src="vue-router.js"></script>
	<script type="text/javascript">
		var Login={
			template:`
				<div>我是登錄頁面</div>
			`,
		}
		//安裝路由插件
		Vue.use(VueRouter);
		//創建路由對象
		var router= new VueRouter({
			//配置路由對象
			routes:[
				{path:'/login',name:'login',component:Login}
			]
		})
		new Vue({
			el:'#app',
			//將配置好的路由對象交給Vue
			router,
			template:`
				<div>
					<p>請在鏈接上加上login測試路由功能</p>
					<!--使用組件-->
					<router-view></router-view>
				</div>
			`,
			data(){
				return {}
			},
		})
	</script>
</body>
</html>

3.3、路由的跳轉

簡介:簡述路由的幾種跳轉方式及他們之間的異同

路由的跳轉方式有:
通過標籤:<router-link to='/login'></router-link>
通過js控制跳轉this.$router.push({path:'/login'})

區別:
this.$router.push() 跳轉到指定的url,會向history插入新記錄
this.$router.replace() 同樣是跳轉到指定的url,但是這個方法不會向history裏面添加新的記錄,點擊返回,
會跳轉到上上一個頁面。上一個記錄是不存在的。
this.$router.go(-1) 常用來做返回,讀history裏面的記錄後退一個

vue-router中的對象:
$route 路由信息對象,只讀對象
$router 路由操作對象,只寫對象

代碼展示

<!DOCTYPE html>
<html>
<head>
	<title>路由的跳轉</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<!-- 引入路由插件 -->
	<script type="text/javascript" src="vue-router.js"></script>
	<script type="text/javascript">

		var Login={
			template:`
				<div>我是登錄頁面</div>
			`,
		}
		var Register={
			template:`
				<div>我是註冊頁面</div>
			`,
		}
	
		//安裝路由插件
		Vue.use(VueRouter);
		//創建路由對象
		var router= new VueRouter({
			//配置路由對象
			routes:[
				{path:'/login',name:'login',component:Login},
				{path:'/register',name:'register',component:Register}
			]
		})
		new Vue({
			el:'#app',
			router,
			template:`
				<div>
					<router-link to='/login'>去登錄</router-link>
					|
					<router-link to='/register'>去註冊</router-link>
				
					<router-view></router-view>
				</div>
			`,
			data(){
				return {}
			}
		})
	</script>
</body>
</html>

效果:
在這裏插入圖片描述
通過js跳轉

<!DOCTYPE html>
<html>
<head>
	<title>路由的跳轉</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<!-- 引入路由插件 -->
	<script type="text/javascript" src="vue-router.js"></script>
	<script type="text/javascript">

		var Login={
			template:`
				<div>我是登錄頁面</div>
			`,
		}
		var Register={
			template:`
				<div>我是註冊頁面</div>
			`,
		}
		var Buy={
			template:`
				<div>我要買東西</div>
			`,
		}
		//安裝路由插件
		Vue.use(VueRouter);
		//創建路由對象
		var router= new VueRouter({
			//配置路由對象
			routes:[
				{path:'/login',name:'login',component:Login},
				{path:'/register',name:'register',component:Register},
				{path:'/buy',name:'buy',component:Buy},
			]
		})
		new Vue({
			el:'#app',
			router,
			template:`
				<div>
					<router-link to='/login'>去登錄</router-link>
					|
					<router-link to='/register'>去註冊</router-link>
					<div>
						<button @click='goregister'>我要去買東西</button>
						<button @click='back'>返回上一頁</button>
					</div>
					<router-view></router-view>
				</div>
			`,
			data(){
				return {}
			},
			methods:{
				goregister(){
					//push跟replace是達到同樣效果,但是replace是不會向history插入記錄
					// this.$router.push({path:'/register'})
					this.$router.replace({path:'/buy'})
					
				},
				back(){
					this.$router.go(-1)
				}
			}
		})
	</script>
</body>
</html>

3.4、路由的傳參和取參

簡介:詳解路由之間的溝通交流

查詢參
配置(傳參) :to="{name:'login',query:{id:loginid}}"
獲取(取參) this.$route.query.id
路由參數

配置(傳參) :to="{name:'register',params:{id:registerid} }"
配置路由的規則 { name:'detail',path:'/detail/:id'}
獲取 this.$route.params.id

總結:
:to傳參的屬性裏 params是和name配對的 query和name或path都可以
使用路由參數必須要配置路由規則裏面配置好參數名,否則刷新頁面參數會丟失

代碼展示:

<!DOCTYPE html>
<html>
<head>
	<title>路由的跳轉</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<!-- 引入路由插件 -->
	<script type="text/javascript" src="vue-router.js"></script>
	<script type="text/javascript">
		var Login={
			template:`
				<div>我是登錄頁面 
					<span>這是我獲取到的參數: {{ msg }}</span>
				</div>
			`,
			data(){
				return { 
					msg:''
				}
			},
			created(){
				this.msg=this.$route.query.id
			}
		}
		var Restiger={
			template:`
				<div>我是註冊頁面
					<span>這是我獲取到的路由參數:{{ foo }}</span>
				</div>
			`,
			props:['foo']
			// data(){
			// 	return {
			// 		restigerfoo:''
			// 	}
			// },
			// created(){
			// 	this.restigerfoo=this.$route.params.foo
			// }
		}
		//安裝路由插件
		Vue.use(VueRouter);
		//創建路由對象
		var router= new VueRouter({
			//配置路由對象
			routes:[
				{path:'/login',name:'login',component:Login},
				{path:'/restiger/:foo',name:'restiger',props:true, component:Restiger},
			]
		})
		new Vue({
			el:'#app',
			router,
			template:`
				<div>
					<router-link :to="{name:'login',query:{id:'123'}}">去登錄</router-link>
					|
					<router-link :to="{name:'restiger',params:{foo:'bar'}}">去註冊</router-link>
					<button @click='jslink'>js跳轉去登錄</button>
					<router-view :key="$route.fullPath"></router-view>
				</div>
			`,
			data(){
				return {}
			},
			methods:{
				//js跳轉傳參是一樣的
				jslink(){
					this.$router.push({name:'login',query:{id:'456'}})
				}
			}
		})
	</script>
</body>
</html>

3.5、嵌套路由

簡介:瞭解嵌套路由的使用場景和如何實現

補充上一節知識點:js跳轉路由傳參和標籤傳參,路由相同而參數不同時頁面不做刷新的問題
解決方案:<router-view :key="$route.fullPath"></router-view>

代碼思想
1:router-view的細分
router-view第一層中,包含一個router-view
2:每一個坑挖好了,要對應單獨的組件
路由配置
routes: [
           {
               path:'/nav',
               name:'nav',
               component:Nav,
               //路由嵌套增加此屬性
               children:[
               //在這裏配置嵌套的子路由
               ]
           }
       ]
       
案例
進入首頁下面會有導航,個人中心、首頁、資訊、我的之類的

代碼展示:

<!DOCTYPE html>
<html>
<head>
	<title>路由的跳轉</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<!-- 引入路由插件 -->
	<script type="text/javascript" src="vue-router.js"></script>
	<script type="text/javascript">
		var Nav={
			template:`
				<div>
					<router-view></router-view>
					<router-link :to="{name:'nav.index'}">首頁</router-link>
					|
					<router-link :to="{name:'nav.pensonal'}">個人中心</router-link>
					|
					<router-link :to="{name:'nav.message'}">資訊</router-link>
					|
					<router-link :to="{name:'nav.mine'}">我的</router-link>
				</div>
			`,
		}
		var Index={
			template:`
				<div>首頁</div>
			`,
		}
		var Pensonal={
			template:`
				<div>個人中心</div>
			`,
		}
		var Message={
			template:`
				<div>資訊</div>
			`,
		}
		var Mine={
			template:`
				<div>我的</div>
			`,
		}
		//安裝路由插件
		Vue.use(VueRouter);
		//創建路由對象
		var router= new VueRouter({
			//配置路由對象
			routes:[
				{
					path:'',
					redirect:'/nav'
				},
				{
					path:'/nav',
					name:'nav',
					component:Nav,
					//嵌套路由增加這個屬性
					children:[
						//配置我們的嵌套路由
						{path:'',redirect:'/nav/index'},
						{path:'index',name:'nav.index',component:Index},
						{path:'pensonal',name:'nav.pensonal',component:Pensonal},
						{path:'message',name:'nav.message',component:Message},
						{path:'mine',name:'nav.mine',component:Mine},
					]
				}
			]
		})
		new Vue({
			el:'#app',
			router,
			template:`
				<div>
					<router-view></router-view>
				</div>
			`,
			data(){
				return {}
			},
			methods:{
			}
		})
	</script>
</body>
</html>

3.6、路由守衛

簡介:瞭解路由守衛的作用和如何使用

const router = new VueRouter({ ... }
//前置的鉤子函數 最後要執行next()纔會跳轉
router.beforeEach((to, from, next) => {
  // ...
})
//後置的鉤子函數 已經跳轉了不需要next
router.afterEach((to, from) => {
  // ...
})
主要是簡單介紹一下,路由守衛主要用於檢驗是否登錄了,沒登錄就跳轉到登錄頁面不讓他在其他頁面停留,但是現在這種處理主要的都用請求的全局攔截來做了。大致瞭解一下路由守衛即可

代碼展示:

<!DOCTYPE html>
<html>
<head>
	<title>路由守衛</title>
</head>
<body>
	<div id="app">
		
	</div>

	<script type="text/javascript" src="vue.js"></script>
	<!-- 引入路由插件 -->
	<script type="text/javascript" src="vue-router.js"></script>
	<script type="text/javascript">
		var Nav={
			template:`
				<div>
					<router-view></router-view>
					<router-link :to="{name:'nav.index'}">首頁</router-link>
					|
					<router-link :to="{name:'nav.pensonal'}">個人中心</router-link>
					|
					<router-link :to="{name:'nav.message'}">資訊</router-link>
					|
					<router-link :to="{name:'nav.mine'}">我的</router-link>
				</div>
			`,
		}
		var Index={
			template:`
				<div>首頁</div>
			`,
		}
		var Pensonal={
			template:`
				<div>個人中心</div>
			`,
		}
		var Message={
			template:`
				<div>資訊</div>
			`,
		}
		var Mine={
			template:`
				<div>我的</div>
			`,
		}
		//安裝路由插件
		Vue.use(VueRouter);
		//創建路由對象
		var router= new VueRouter({
			//配置路由對象
			routes:[
				{
					path:'',
					redirect:'/nav'
				},
				{
					path:'/nav',
					name:'nav',
					component:Nav,
					//嵌套路由增加這個屬性
					children:[
						//配置我們的嵌套路由
						{path:'',redirect:'/nav/index'},
						{path:'index',name:'nav.index',component:Index},
						{path:'pensonal',name:'nav.pensonal',component:Pensonal},
						{path:'message',name:'nav.message',component:Message},
						{path:'mine',name:'nav.mine',component:Mine},
					]
				}
			]
		})
		new Vue({
			el:'#app',
			router,
			template:`
				<div>
					<router-view></router-view>
				</div>
			`,
			data(){
				return {
					loginstate:true
				}
			},
			methods:{
			},
			mounted(){
				//利用路由守衛做當跳轉首頁時可直接跳轉,跳轉其他頁面要等待兩秒纔可以跳轉
				router.beforeEach((to,from,next)=>{
					console.log(to)
					if(to.path=='/nav/index'){
						next()
					}else{
						setTimeout(function(){
								next()
						},2000)
					}
				})
			}
			
		})
	</script>
</body>
</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章