2.4 OpenEuler中C語言中的函式呼叫測試
vue是什麼
vue.js是現今最為主流的MVVM框架
作者:尤雨溪 前google員工
MVVM
mvvm是一個程式設計的思想 在這個思想下 更加只專注於業務的開發(功能)讓我們的開發變得更加簡單
M ------model 模型 = 資料
V ------ view 檢視 = 介面(就是你寫出來讓使用者看見的內容)
VM --- viewmodel 檢視模型 用來傳遞模型和關聯檢視的
vue優勢
vue的開發目的
vue 的核心
資料驅動與元件化
vue 初體驗
獲取vue的依賴庫 npm install --save vue
編寫如下內容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <!-- 1.下載包2.引包 --> <script src="./node_modules/vue/dist/vue.min.js"></script> </head> <body> <!-- M ------model 模型 = 資料 V ------ view 檢視 = 介面(就是你寫出來讓使用者看見的內容) VM --- viewmodel 檢視模型 用來傳遞模型和關聯檢視的 --> <!-- 3.新建v層 --> <div id="demodiv"> {{text}}</div> <script> // <!-- 4.新建vm層 就是vue例項 --> new Vue({ el:"#demodiv", // 5.編寫m層 data:{ text:"你好麼麼噠!!!!!^_@" } }) </script> </body> </html>
{{}}是什麼?
{{表示式---通過計算返回結果的公式}}
{{}} 大括號賦值法/雙大括號語法/模板語法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>雙大括號賦值法</h1>
<h1>{{text}}</h1>
<h1>{{num+2}}</h1>
<h1>{{bool?"你好":"你壞"}}</h1>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
text:"字串",
num:18,
bool:false,
arr:[1111,22222,33333,44444],
obj:{
name:"xixi",
age:18
}
}
})
</script>
</body>
</html>
vue渲染資料
vue,js的核心就是資料驅動 vue的資料驅動就是檢視的內容是根據模型data資料的改變而改變的
資料驅動的分類
1.宣告式渲染 我們只需要告訴程式 想幹什麼 那麼程式就會自動來完成
2.命令式渲染 我們需要一步步的指揮著程式 程式才會按照我們的指令去執行
指令
在vue中 使用v-開頭html特殊屬性
指令的作用:在vue中 擴充套件標籤的功能
指令的語法:寫在html開標籤中並且 v-指令="指令值"
v-model
作用: 用於在表單元素上完成資料的雙向繫結
語法: v-model="值"
雙向繫結
使用者在可以看見的介面中也就是v層檢視層 改變了資料 那麼data中的內容也就會改變 檢視變模型變
模型改變了 反之也會讓檢視發生改變 模型變檢視變
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>v-model</h1>
<!-- 雙向繫結
使用者在可以看見的介面中也就是v層檢視層 改變了資料 那麼data中的內容也就會改變 檢視變模型變
模型改變了 反之也會讓檢視發生改變 模型變檢視變 -->
<input type="text" v-model="inputval"/>
<h1>{{inputval}}</h1>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
inputval:""
}
})
</script>
</body>
</html>
雙向繫結的原理
雙向繫結是通過 資料劫持 與 釋出者訂閱者模式來實現的
資料劫持:資料(變數)劫持(攔截)就是當資料改變的時候 我要攔截到這次改變 通知模型或者檢視發生改變
通過一個Object.defineProperty()來監聽資料當資料改變的時候他就會被觸發 從而通知另外一方(有一個get的方法和set的方法 分別是讀取與修改)
也有一個bug 後面會說先佔個位置
bug詳見$set
釋出者訂閱者模式:就是一個一對多的關係 ,當釋出者改變了 其所有的訂閱者頁隨之發生改變
v-show
作用: 控制dom元素的顯示和隱藏
語法: v-show="返回值為布林值的表示式" true 顯示 false 隱藏
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>v-show</h1>
<!-- 如果給一個複選框繫結一個變數 那麼這個變數會隨著勾選和取消在true和false中切換 -->
<input type="checkbox" v-model="bool"/>{{bool?"顯示了":"隱藏了"}}
<h1 v-show="bool">我是測試顯示和隱藏的元素</h1>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
bool:true
}
})
</script>
</body>
</html>
v-on
作用: 就是給dom元素繫結事件的
語法: v-on:事件不加on="函式" 簡寫就是 @
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>v-on</h1>
<!-- 繫結事件用v-on -->
<button v-on:click="fun()">點我繫結事件</button>
<!-- v-on還有個簡寫的寫法 就是把v-on: 替換成 @ -->
<button @click="fun()">簡寫寫法</button>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
},
// methods來建立函式
methods:{
// 函式名(){
// }
fun(){
console.error("你好麼麼噠")
}
}
})
</script>
</body>
</html>
v-for
作用:遍歷展示資料
語法: v-for=" ( 引數1--便利出來的值 , 引數2-- 便利出來的下標) in 你要便利的資料 "
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>v-for</h1>
<ul>
<li v-for="(v,i) in arr">{{v}}</li>
</ul>
<hr>
<table border="1">
<tr v-for="(v,i) in obj">
<td>{{i}}</td>
<td>{{v.name}}</td>
<td>{{v.age}}</td>
</tr>
</table>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
arr:["EZ","Vn","MF","NOC"],
obj:[
{name:"xixi1",age:181},
{name:"xixi2",age:182},
{name:"xixi3",age:183},
{name:"xixi4",age:1845},
{name:"xixi5",age:186},
{name:"xixi6",age:187}
]
}
})
</script>
</body>
</html>
v-bind(使用中最容易忽略的指令)
作用:就是給html的屬性插入變數
語法:v-bind:html標籤的屬性="變數" 簡寫:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>v-bind</h1>
<!-- html的屬性插變數使用v-bind -->
<a v-bind:href="ahref">{{atext}}</a>
<!-- 簡寫 v-bind: 替換成 : -->
<a :href="ahref">{{atext}}</a>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
atext:"點我去百度",
ahref:"http://www.baidu.com"
}
})
</script>
</body>
</html>
v-if全家桶
v-if
從使用者的角度看上去和v-show沒有區別
作用: 判斷當前dom是否載入
語法: v-if="表示式結果為布林值" true 載入當前dom false 移除當前dom
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>v-if</h1>
<h1 v-if="bool">我是測試v-if</h1>
<h1 v-show="bool">我是測試v-show</h1>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
bool:true
},
methods:{
}
})
</script>
</body>
</html>
v-if與v-show的區別
v-if 在顯示和隱藏的時候是對當前dom進行移除和新增 v-if在頁面初始化的時候效能損耗低 在切換的時候效能損耗高
v-show 是對於css的樣式設定顯示和隱藏 v-show在頁面初始化的時候效能損耗高 在切換的時候效能損耗低
v-else
必須配合v-if來使用 當v-if條件不成立的時候執行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>v-else</h1>
<h1 v-if="false">請登入</h1>
<!-- v-if與v-else之間不能有第三者 -->
<h1 v-else>歡迎您尊敬的vip</h1>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
},
methods:{
}
})
</script>
</body>
</html>
v-else-if
多重if選擇 當其中一項成立的時候執行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>v-else-if</h1>
<select v-model="text">
<option value="吃飯">吃飯</option>
<option value="睡覺">睡覺</option>
<option value="上廁所">上廁所</option>
<option value="在吃飯">在吃飯</option>
<option value="在睡覺">在睡覺</option>
</select>
<h1 v-if="text=='吃飯'">吃飯</h1>
<h1 v-else-if="text=='睡覺'">睡覺</h1>
<h1 v-else-if="text=='上廁所'">上廁所</h1>
<h1 v-else-if="text=='在吃飯'">在吃飯</h1>
<h1 v-else-if="text=='在睡覺'">在睡覺</h1>
<h1 v-else>啥都沒幹</h1>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
text:""
},
methods:{
}
})
</script>
</body>
</html>
v-html
作用 : 把字串標籤 解析到頁面中
語法: v-html="值"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>v-html</h1>
<div>
{{newhtml}}
<div v-html="newhtml"></div>
</div>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
newhtml:"<em>我是測試的</em>"
},
methods:{
}
})
</script>
</body>
</html>
v-once
作用: 一次性插值 資料插入到頁面中之後就不會改變了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>v-once</h1>
<input type="text" v-model="text">
<h1 v-once>{{text}}</h1>
<h1>{{text}}</h1>
<h1>{{text}}</h1>
<h1>{{text}}</h1>
<h1>{{text}}</h1>
<h1>{{text}}</h1>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
text:"我是預設值"
},
methods:{
}
})
</script>
</body>
</html>
v-text
作用: 就是在頁面中插入純文字 {{}}可以理解為和他是一樣的功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>v-text</h1>
<h1>{{num}}</h1>
<h1 v-text="num"></h1>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
num:"我是預設值"
},
methods:{
}
})
</script>
</body>
</html>
螢幕閃爍
當用戶網路 或者裝置效能較低的時候 可能在vue渲染初期會在頁面顯示沒有編譯好的很多{{}} 當網路通順或者裝置渲染完成之後 在突然間顯示最終效果 就叫螢幕閃爍
解決:
1.v-text
2.v-cloak指令 當前指令是會在vue例項渲染完畢之後自動消失
<style>
[v-cloak]{
display: none;
}
</style>
<div id="demodiv" v-cloak>
<h1>v-text</h1>
<h1>{{num}}</h1>
<h1 v-text="num"></h1>
</div>
watch監聽
他是vue例項中的一個屬性 寫在與el data methods 等屬性同級的位置
用來繫結監聽data中建立的資料 當data的資料改變的時候 watch就會收到通知 做出相關的反應
watch在初始化的時候是不會執行的 只有當資料改變的時候才會執行
課下自行檢視
我就是向讓watch在初始化執行怎麼辦?
語法:
watch:{
newval 就是改變之後的值 oldval就是之前的舊資料
你要監聽的資料(newval,oldval){
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>watch的使用</h1>
<h1>{{text}}</h1>
<button @click="fun()">點我改變資料</button>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
text:"我是預設值"
},
methods:{
fun(){
this.text="你好麼麼噠!!"
}
},
watch:{
text(newval,oldval){//當text改變的時候就會執行
console.log(newval);
console.log(oldval);
}
}
})
</script>
</body>
</html>
計算屬性---computed
為什麼要使用計算屬性?
檢視層是用來展示資料的 但是我們卻在檢視層中處理資料 不太合適
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<!-- 檢視層是用來展示資料的 但是我們卻在檢視層中處理資料 -->
<div id="demodiv">
<h1>{{text}}</h1>
<h1>大寫展示:{{text.toUpperCase()}}</h1>
<h1>大寫加擷取展示:{{text.toUpperCase().substr(1,4)}}</h1>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
text:"abcdefghijk"
},
methods:{
},
watch:{
}
})
</script>
</body>
</html>
什麼是計算屬性
計算屬性 他是一個vue例項下的屬性 這個屬性是一個帶有計算(data資料的)功能的 他會時時刻刻的盯著data中的資料 當data的資料改變了 他也會知道 重新計算並且在返回出計算之後的結果
一條資料 在不同位置展示不同形態的時候 使用
語法:
computed:{
你計算之後返回的資料變數(){
return 你處理資料的邏輯
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>{{text}}</h1>
<h1>大寫{{upptext}}</h1>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
text:"abcdefghijk"
},
methods:{
},
watch:{
},
computed:{
upptext(){
return this.text.toUpperCase()
}
}
})
</script>
</body>
</html>
計算屬性與方法的區別
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>{{text}}</h1>
<h1>大寫{{upptext}}</h1>
<hr>
<h1>{{fun()}}</h1>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
text:"abcdefghijk"
},
methods:{
fun(){
console.log("我是方法")
return this.text.toUpperCase()
}
},
watch:{
},
computed:{
upptext(){
console.log("我是計算屬性")
return this.text.toUpperCase()
}
}
})
</script>
</body>
</html>
計算屬性 是依賴於快取的 也就是說 計算屬性處理的資料 在第一次處理好之後就會把結果儲存在記憶體中 只要處理的資料不變 那麼無論我們呼叫多少次 它的資料都是從快取中讀取出來
方法 方法只要被呼叫就會執行 方法比較消耗效能
計算屬性與watch的區別
watch 監聽一個data資料 當這個data資料改變的時候 watch就會觸發一個函式完成一些指定的功能(非同步操作 開銷較大的邏輯)
計算屬性 依賴一個data的資料 當這個資料改變了他會重新計算這個資料返回結果
vue的事件物件
$event 來描述事件物件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiv">
<h1>事件物件的使用</h1>
<button @click="fun($event)">點我得到事件物件</button>
</div>
<script>
new Vue({
el:"#demodiv",
data:{
},
methods:{
fun(xiaoming){
console.log(xiaoming.target);
}
},
watch:{
}
})
</script>
</body>
</html>
事件修飾符
就是幫助我們來修飾一些在觸發事件過程中的一些細節
修飾符: @事件.修飾符
按鍵修飾符
幫助我們在觸發一些事件的時候 指定鍵盤按鈕
.up .down .ctrl .enter .space等 按鍵修飾符
<input type="text" @keydown.enter="changeb($event)">
事件修飾符
.prevent 阻止事件預設行為
.stop 阻止冒泡
.captrue 設定當前為捕獲事件
.once 當前事件只會觸發一次
.self 只會觸發自身的事件 不包子元素
過濾器與全域性區域性
全域性與區域性
全域性就是在所有vue例項中都可以使用
區域性就是隻能在當前例項中使用
自定義過濾器---filter
在不改變原始資料的情況下 格式化展示內容
全域性過濾器----filter
寫在建立vue例項之前
Vue.filter( "過濾器的名字", (你要過濾的資料)=>{
return 你過濾的邏輯
} )
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiva"> {{text}}</div>
<div id="demodivb">{{text}} </div>
<script>
// 寫在例項之前
Vue.filter("xiaoming",(val)=>{
return "<<"+val+">>"
})
new Vue({
el:"#demodiva",
data:{
text:"紅樓夢"
}
})
new Vue({
el:"#demodivb",
data:{
text:"西遊記"
}
})
</script>
</body>
</html>
使用:
| 管道符來進行使用 資料|過濾器的名字
<div id="demodiva"> {{text|xiaoming}}</div>
區域性過濾器---filters
寫在想使用這個過濾器的例項中 與el data methods watch computed 同級
filters:{
過濾器的名字(val 你要過濾的資料會自動傳入){
return 你過濾的邏輯
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="demodiva">{{text|xiaoming}} </div>
<div id="demodivb"> {{text|xiaoming}} </div>
<script>
new Vue({
el:"#demodiva",
data:{
text:"我是第1個"
},
filters:{//區域性過濾器
xiaoming(val){
return "<<"+val+">>"
}
}
})
new Vue({
el:"#demodivb",
data:{
text:"我是第2個"
}
})
</script>
</body>
</html>
擴充套件--內建過濾器
在vue2x之後 內建過濾器已經移除了 所以在vue2.0之後就沒有內建過濾器了
鉤子函式
在特定階段內被自定執行的函式 就叫做鉤子函式
生命週期的鉤子函式
被自動執行的函式
就可以讓程式在特定階段自動執行某些操作
鉤子函式就是幾個vue預先定義好的自動執行的函式 所以我們如果要寫 寫在data el methods等同級位置
例項建立
例項建立之前 -- beforeCreate 在這個鉤子中資料觀測與事件還沒有開始
例項建立完畢 -- created 資料的觀測 例項的其他屬性 以及事件等 都已經準備好了
模板渲染
模板渲染之前 -- beforeMount 已經準備開始掛載頁面了 此時頁面還沒有開始渲染
模板渲染之後 -- mounted el屬性已經掛載完成 dom也已經渲染載入完畢了
資料更新
資料更新之前 -- beforeUpdate 準備開始更新 猜這個時候還沒有開始進行資料的狀態修改
資料更新之後 -- updated 資料與頁面DOM都已經修改完畢了
例項銷燬
例項銷燬之前 -- beforeDestory 銷燬之前 但是此時例項還可以使用
例項銷燬之後 -- destoryed 例項已經不存在了 和vue相關的所有內容都不能使用
第一次執行的之後執行那幾個鉤子
例項建立前後 模板渲染前後
生命週期的鉤子函式有什麼作用?
vue預先定義好的自動執行的函式 是在vue例項從建立到銷燬的過程中自動執行某些特定的業務的一個函式
DOM渲染在那個鉤子中完成?
mounted
你能不能分別介紹下這8個鉤子
vue-cli 腳手架
1.電腦上必須有node
2.全域性下載vue-cli(除非你重新裝電腦了或者重灌node了 否則只需要下載一次就好了) npm install -g @vue/cli
3.測試下載是否成功 vue --version
4.把cmd cd到執行下載專案的資料夾下
5.新建專案 vue create 專案名
會出現選擇 那麼在第一項 我們選擇第三個自定義 剩下的 眼睛一閉 回車到底
6 把cms cd到你下載的專案之下
7 啟動 npm run serve
.vue 檔案
.vue檔案 -----》 單檔案元件
組成:
1.template ---》 把你的html寫進去
2.script ---》 把你的js寫進去
3.style ---》 把你的css寫進去
拿到空專案怎麼辦?
1.刪除src下的components資料夾下的Helloword.vue
2.在新建一個屬於我們自己的.vue檔案並寫入如下內容
<template>
<div>
<h1>你好麼麼噠</h1>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
3.來到app.vue 中 (app.vue是全部元件的老大)修改原來裡面helloword相關的內容成我們自己的
<template>
<div id="app">
<!-- 4圖片刪除引用 -->
<!-- <img alt="Vue logo" src="./assets/logo.png"> -->
<!-- 3.使用 -->
<Home/>
</div>
</template>
<script>
// 1.引用
import Home from './components/home.vue'
export default {
name: 'App',
components: {
// 2.呼叫
Home
}
}
</script>
<style>
/* 5刪除原有樣式 */
/* #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>
之前學的vue屬性怎麼用?
data
語法:
data(){
return {
}
}
為什麼data是一個函式而不是物件 因為物件是引用資料型別 如果data是物件的方式建立的 那麼這個元件被多次呼叫的時候 data都指向的是統一個記憶體空間
函式的話 每一次呼叫都返回一個新的物件
以下的和之前本地模式沒有任何區別
methods
watch
computed
filters
8個生命週期的鉤子函式
作業
新建一個腳手架 並且在其中新建一個.vue檔案把 之前學到的todolist移植過來
元件
元件把一個頁面拆成多個細小的小功能區域 分別來建立
就可以讓這一個個的小模組方便重複的進行呼叫 減少了程式碼量 降低了後期維護的難度
元件分類
全域性元件--component
可以在全部專案中任意使用
在main.js
1.引用
2.呼叫
剩下在所有的元件中可以任意的使用
區域性元件--components
建立元件其實就是新建一個.vue檔案 並且寫入如下內容
<template>
<div>
我是一個元件麼麼噠
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
使用元件
在你想使用的地方
引用
// 1.引用
import Demo from "./components/demo.vue"
呼叫
components 用來描述區域性元件 寫在與data methods watch等同級的位置
語法:
components:{
給你引用的元件起個名字: 你引用的元件
}
components:{
Demo
}
使用
元件的本質 就是自定義標籤
標籤有單標籤和雙標籤 單標籤 <關鍵字/> 雙標籤 <關鍵字></關鍵字>
<你的元件名/>
scoped
當前樣式僅對當前元件生效
父子元件
其實就是在一個元件中引用另外一個元件
引用
呼叫
使用
元件傳值
我在父元件中有個資料 我能在子元件中直接使用嗎?不能
我在子元件中有個資料 我能在父元件中直接使用嗎?不能
結論:
元件與元件之間是完全獨立的一個體 無論元件是什麼關係都不能直接相互使用資料
正向傳值--props
父元件把資料給子元件使用
1.子元件需要使用props來建立接收傳遞過來資料的變數
props寫在與data methods等同級的位置
語法:
props:[ 變數1,變數2,.....,變數n]
<template>
<div>
{{xiaoming}}
</div>
</template>
<script>
export default {
props:["xiaoming"]
}
</script>
2.父元件就要給他傳遞資料
在子元件被呼叫的時候 把子元件的props當做一個屬性來進行傳值
<div class="bottombar">
<Zi xiaoming="資料1"/>
<Zi xiaoming="你好"/>
<Zi xiaoming="購物車1"/>
<Zi xiaoming="購物車2"/>
<Zi xiaoming="購物車3"/>
</div>
props 驗證
就是在現有的正向傳值之上 對父元件傳遞給子元件的資料進行資料格式或者型別上的驗證
1.子元件接收的時候需要設定接收資料的驗證
props:{
你接收資料的變數:資料型別
你接收資料的變數:[ 資料型別1,資料型別2 ]
你接收資料的變數:{
type:你要驗證的資料型別,
default:預設值
}
}
props:{
//text:String 只驗證一種型別
text:[String,Number]
}
預設值語法
props:{
//text:String 只驗證一種型別
// text:[String,Number]
text:{
type:String,
// 預設值
default:"你好我是預設值"
}
}
逆向傳值
子元件把資料給父元件
逆向傳值預設是不被允許的 如果想逆向傳值的話那麼我們必須要通過 自定義事件來完成
逆向傳值必須要通過一個事件來觸發自定義事件的建立
實現:
1.在子元件中必須要用一個事件來觸發
<template>
<div>
zizzizizizizizi
<button v-on:click="fun()">點我進行逆向傳值</button>
</div>
</template>
<script>
export default {
methods:{
fun(){
}
}
}
</script>
<style>
</style>
2.自定義事件 使用this.$emit()來實現自定義事件
語法: this.$emit("自定義事件名",“資料”)
<template>
<div>
zizzizizizizizi
<button v-on:click="fun()">點我進行逆向傳值</button>
</div>
</template>
<script>
export default {
methods:{
fun(){
// 建立自定義事件
this.$emit("xiaoming","我是子元件的資料^_*!")
}
}
}
</script>
<style>
</style>
3.父元件接收這個自定義事件
<template>
<div>
fufuffufufufufufufu
<!-- 父元件函式不加()
父元件函式不加()
父元件函式不加()
父元件函式不加()
父元件函式不加()
因為加了函式就自動呼叫了
-->
<Nz @xiaoming="demo"/>
</div>
</template>
<script>
import Nz from "./nizi.vue"
export default {
methods:{
// 這個形參就是子元件傳遞的資料會自動傳給形參
demo(val){
console.log(val);
}
},
components:{
Nz
}
}
</script>
<style>
div{
font-size: 0.2rem;
}
</style>
逆向傳值預設不被允許 所以我們通過事件觸發一個自定義事件的丟擲 在父元件中使用@ 繫結這個自定義事件 從而得到子元件的資料
兄弟同胞傳值--中央事件匯流排
相同父元件的兩個子元件之間相互傳值
預設情況下兄弟元件要進行傳值
什麼是中央事件匯流排
eventBus---中央事件匯流排 就是凌駕在兩個兄弟元件之上的一個空的vue例項(中央事件匯流排eventBus)通過這個空的vue例項 就在兩個兄弟元件之上建立起了資料通訊的橋樑
實現
1.新建資料夾eventbus與檔案用來存放這個中央事件匯流排的空例項
2.建立空例項
import Vue from "vue"
//建立空例項並且暴漏
export default new Vue
3.需要傳遞的元件中 引用中央事件匯流排 並且 使用事件來觸發 給中央事件匯流排之上繫結一個自定義事件
<template>
<div>
<!-- 2.事件來觸發一個函式 -->
zia <button @click="fun()">點我把資料給zib</button>
</div>
</template>
<script>
// 1.引用中央事件匯流排
import EventBus from "@/eventbus/index.js"
export default {
methods:{
fun(){
// 3.給中央事件匯流排之上繫結一個自定義事件
EventBus.$emit("zia","我是zia的資料呵呵!!!!")
}
}
}
</script>
<style>
</style>
4.在需要資料的元件之上 先引用中央事件匯流排 使用$on()來監聽例項上的自定義事件
<template>
<div>
zib
</div>
</template>
<script>
// 1.引用
import EventBus from "@/eventbus/index.js"
export default {
// 2.就可以使用$on來監聽例項上的自定義事件
// $on( 你要監聽得自定義事件名,(你傳遞過來的資料)=>{} )
mounted(){
EventBus.$on("zia",(val)=>{
console.log(val);
})
}
}
</script>
<style>
</style>
跨元件傳值---vuex
元件與元件之間有多個層級關係的時候傳值
vuex 狀態(資料)管理工具 給專案提供了一個集中儲存資料的地方 把專案的資料都放在這個倉庫中 無論那個元件向使用某條資料 那麼直接來倉庫去取出即可 免去了傳統元件與元件之間傳遞資料的複雜性
vue是單項資料流 那麼元件與元件之間在傳遞的時候 如果是兄弟或者跨元件又或者逆向傳值 我們就可以使用vuex來集中的管理我們的資料
vuex使用
state 存放資料的地方
定義state實在vuex的檔案中的state中進行定義
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {//就是這個倉庫中存放資料的地方
name:"xixi"
},
mutations: {
},
actions: {
},
modules: {
}
})
使用方式1
直接在你想使用的地方用 this.$store.state.xxx 來直接讀取
<template>
<div class="about">
<h1>This is an about page{{this.$store.state.name}}</h1>
</div>
</template>
使用方式2
在計算屬性中進行呼叫
<template>
<div class="about">
<h1>This is an about page{{this.$store.state.name}}</h1>
<h1>計算屬性方式取值--{{newname}}</h1>
</div>
</template>
<script>
export default {
// 方式2在計算屬性中進行讀取
computed:{
newname(){
return this.$store.state.name
}
}
}
</script>
總結:
1.vuex 是一個倉庫 裡面有很多個物件 其中state就是用來儲存資料的地方 相對與vue的data作用
2.state裡面的資料是響應式的 vue的元件從store中讀取資料 如果store中的state改變了 那麼對應引用的檢視也會隨之發生改變
modules 模組
傳統寫法上 我們把所有的vuex操作都在一個檔案中繼續編寫 太麻煩了 後期也不好維護
1.在store下新建資料夾 用來存放我們拆分的模組檔案
2.在檔案中新建物件並且把vuiex的屬性放置進去
let aboutm={
state: {//就是這個倉庫中存放資料的地方
name:"我是about的資料",
},
mutations: {
},
actions: {
},
}
export default aboutm
3.在vuex的檔案中引用模組 呼叫模組
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 1.引用模組
import Aboutm from "./modules/aboutm.js"
import Homem from "./modules/homem.js"
export default new Vuex.Store({
modules: {//2.模組的呼叫
Aboutm,Homem
}
})
4.在使用模組之後 頁面使用資料 就必須是 this.$store.state.模組名.xxxx
<h1>This is an about page{{this.$store.state.aboutm.name}}</h1>
mutations 狀態的修改
在vuex中如果想要修改資料 不能直接修改 而是要通過 mutations來進行修改 mutations 是一個屬性 其中有n個方法 每個方法就是一個修改的動作
let homem={
state: {//就是這個倉庫中存放資料的地方
name:"我是home的資料",
},
// 在vuex中如果想要修改資料 不能直接修改
// 而是要通過 mutations來進行修改
// mutations 是一個屬性
// 其中有n個方法 每個方法就是一個修改的動作
mutations: {
// state 形參就是上面的state資料來源
// payload 提交載荷 後續呼叫的時候傳遞進來的引數
upname(state){
state.name="呵呵!!!!"
}
},
actions: {
},
}
export default homem
在元件中觸發這個修改 commit("你要觸發的mutations的名字")
在元件中使用函式 來呼叫this.$store.commit() 修改
<button @click="fun()">點我修改</button>
methods:{
fun(){
// 使用commit()呼叫mutations 修改state
this.$store.commit("upname")
}
}
總結 在vuex中使用commit呼叫mutations 來修改state的資料
payload 載荷
就是用來接收呼叫mutations的時候傳遞進來的資料
homedata(state,payload){
state.name=payload.text
}
在元件使用commit的時候傳遞第二個引數
fun(){
// commit中傳遞了第二個引數 那麼這個引數會被mutations的payload接收
this.$store.commit("homedata",{text:"我是paylad接收的資料"})
}
擴充套件----vuex資料修改重新整理丟失的問題
使用事件監聽器 監聽頁面關閉事件 當頁面關閉的時候 把vuex的state 全部取出來並且轉成字串 儲存在本地儲存中
在頁面載入之後 判斷本地儲存中有沒有之前存的資料
如果有 那麼就把本地儲存的資料取出來轉成物件 並且替換vuex的當前state
在你想儲存資料重新整理丟失的地方加如下內容
created () {
//在頁面載入時讀取sessionStorage裡的狀態資訊
if (sessionStorage.getItem("store") ) {
this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(sessionStorage.getItem("store"))))
}
//在頁面重新整理時將vuex裡的資訊儲存到sessionStorage裡
window.addEventListener("beforeunload",()=>{
sessionStorage.setItem("store",JSON.stringify(this.$store.state))
})
}
actions 用來觸發非同步操作
actions也是vuex的一個屬性 作用就是用來在vuex中觸發非同步操作 它裡面也是有n個方法 每個方法就是一個觸發非同步操作的動作
1.建立actions 並且寫入觸發的動作
actions: {
// 建立觸發非同步的動作
// context就是代表$store
// payload 載荷接收外部的資料
demolink(){
// 呼叫非同步操作
console.log("我觸發了非同步操作");
}
},
2.在頁面觸發資料請求 dispatch("actions的名字")
funb(){
this.$store.dispatch("demolink")
}
資料請求的閉環操作
1.需要模擬資料就新建mockjs 寫好資料請求與攔截器 2.我們需要在元件頁面通過 dispath() 來觸發一個vuex的actions來 呼叫一個請求
<template>
<div>
<h1>資料請求的閉環操作</h1>
</div>
</template>
<script>
export default {
// 1.在頁面載入完畢後自動使用生命週期的鉤子呼叫 dispatch 來觸發vuex的呼叫非同步操作
mounted(){
this.$store.dispatch("demoaxios")
}
}
</script>
<style>
</style>
3.來到vuex中建立對應的modules 並且在vuex檔案中 引用 呼叫 方可使用模組
建立模組
let aboutm={
state: {
},
mutations: {
},
actions: {
}
}
export default aboutm
使用模組
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 2.引用建立的vuex模組
import aboutm from "./modules/aboutm.js"
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
// 3.呼叫模組
aboutm
}
})
4.在vuex的actions中建立對應的 非同步觸發方法
let aboutm={
state: {
},
mutations: {
},
actions: {
// 4建立 非同步觸發的任務動作
demoaxios(){
}
}
}
export default aboutm
5.在模組中引用 使用我們封裝好的非同步請求 進行資料請求
// 5.先引用資料請求封裝
import getlink from "@/api/getapi.js"
let aboutm={
state: {
},
mutations: {
},
actions: {
// 4建立 非同步觸發的任務動作
demoaxios(){
// 6 呼叫封裝的請求 進行資料請求
getlink("/data/mock/userlist").then((ok)=>{
console.log(ok.data)
})
}
}
}
export default aboutm
6.把請求來的資料 通過commit 傳遞到mutations上
// 5.先引用資料請求封裝
import getlink from "@/api/getapi.js"
let aboutm={
state: {
},
mutations: {
},
actions: {
// 4建立 非同步觸發的任務動作
// 7.建立context形參
demoaxios(context){
// 6 呼叫封裝的請求 進行資料請求
getlink("/data/mock/userlist").then((ok)=>{
console.log(ok.data)
// 8把請求來的資料交給mutations來修改state
context.commit("uparr",{data:ok.data})
})
}
}
}
export default aboutm
7.在mutations中進行state的修改 並且在state中也建立資料
// 5.先引用資料請求封裝
import getlink from "@/api/getapi.js"
let aboutm={
state: {
// 11.新建狀態資料
arr:[]
},
mutations: {
// 9.新建mutations
uparr(state,payload){
// 10修改state的資料 根據payload的值(payload的值就是請求來的資料)
state.arr=payload.data
}
},
actions: {
// 4建立 非同步觸發的任務動作
// 7.建立context形參
demoaxios(context){
// 6 呼叫封裝的請求 進行資料請求
getlink("/data/mock/userlist").then((ok)=>{
console.log(ok.data)
// 8把請求來的資料交給mutations來修改state
context.commit("uparr",{data:ok.data})
})
}
}
}
export default aboutm
8 在元件中讀取請求過來的state資料
<template>
<div>
<h1>資料請求的閉環操作</h1>
<!-- 13.展示 -->
{{newarr}}
</div>
</template>
<script>
export default {
// 1.在頁面載入完畢後自動使用生命週期的鉤子呼叫 dispatch 來觸發vuex的呼叫非同步操作
mounted(){
this.$store.dispatch("demoaxios")
},
// 12.讀取state的資料
computed:{
newarr(){
return this.$store.state.aboutm.arr
}
}
}
</script>
<style>
</style>
actions payload形參
在呼叫diapatch( "呼叫得我actions的名字",{ 你傳遞的資料 } )的時候 可以向actions中傳遞資料進去
總結
getters vuex的計算屬性
getters是在vuex中對一條資料在不同位置展示不同形態的時候 使用的資料處理的一個屬性 getters是依賴state的資料 當state的資料改變了之後getters也會重新計算返回新的計算結果
getters與元件的計算屬性有啥區別?
vuex的getters處理的資料可以在多個元件都是用 元件的計算屬性 只能在當前元件中使用
1.在vuex中與state mutations等同級位置 建立getters getters裡面也是多個方法 每個方法就是一個數據的處理 但是裡面必須必須return
getters:{//vuex的計算屬性
// state就是上面的額資料來源
newnum(state){
return state.num.toUpperCase()
}
}
2.在頁面使用的時候 直接 this.$store.getters.xxxxx(getters的名字)
this.$store.getters.newnum-
slot--槽口/插槽
引子
元件在被呼叫的時候 我們知道元件的本質是自定義標籤 標籤是可以在內部插內容的 元件可以
預設情況下不可以
槽口是什麼?
用來混合父元件與子元件自己的模板(就是可以在元件被呼叫的時候 向其內部插入新的dom節點)槽口也是元件提高複用的技術之一 props如果是隻能向元件內部插入資料的話 那麼槽口就是可以向元件內容部插入新的dom節點
基礎用法
預設情況在元件是一個自定義標籤 但是在元件被呼叫的時候不能直接插入dom節點 所以在這個時候需要給元件內部設定一個插槽 來接收外部插入的資料
語法:
<slot></slot>
<div>
zizizizizziizziz
<slot></slot>
</div>
上面這種寫法 後期插入的內容多個就不好維護了 所以在開發的時候使用的很少
具名槽口
帶有名字的槽口 給槽口在定義的時候起個名字
語法:
在定義的時候 <slot name="給槽口起個名字隨便寫"></slot>
在插入內容的時候:
<元件>
<p slot="你要插入的slot的namne"></p>
</元件>
子元件
<template>
<div>
zizizizizziizziz
<div class="red">
<slot name="xiaoming"></slot>
</div>
<hr>
<div class="yellow">
<slot name="xiaohong"></slot>
</div>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
.red>h1{
color:red;
}
.yellow>h1{
color:yellow;
}
</style>
父元件
<template>
<div>
fufufufuffufufu
<Sz>
<h1 slot="xiaohong">插入內容1</h1>
<h1>插入內容2</h1>
<h1>插入內容3</h1>
<h1>插入內容4</h1>
<h1 slot="xiaoming">插入內容5</h1>
<h1>插入內容6</h1>
<h1>插入內容7</h1>
<h1>插入內容8</h1>
<h1 slot="xiaoming">插入內容9</h1>
<h1>插入內容0</h1>
</Sz>
</div>
</template>
<script>
import Sz from "./slotzi.vue"
export default {
components:{
Sz
}
}
</script>
<style>
</style>
路由---router
傳統的專案怎麼切換跳轉頁面?
1.新建很多的html檔案
2.使用 標籤的方式進行跳轉(a標籤) 或者使用js的方式進行跳轉(window.location.href )
傳統的專案稱之為 多頁面專案
路由基本概念
根據url的不同來渲染不同的元件頁面
SPA -- 單頁面應用 在使用者切換頁面的時候 沒有那種傳統頁面的白屏問題 提高了使用者的體驗
路由基本建立
vue-cl自動建立
在建立腳手架的時候 選擇自定義 在選擇Router 即可
在建立完專案之後 會在src中多了兩個資料夾
router ---》 當前資料夾就是配置路由的資料夾
views ---》 當前資料夾就是來寫路由頁面元件的
帶有路由的空專案怎麼辦?
1.刪除components裡面的helloword.vue 與views裡面的home.vue about.vue檔案
2.views下新建你所需要的元件頁面
3.需要配置路由規則 去router下的index.js中配置
(3-1)引用你所想要的頁面 到index.js下 import from
(3-2) 在index.js的陣列物件中 進行規則的配置
// 引用vue
import Vue from 'vue'
// 引用vue的路由功能模組
import VueRouter from 'vue-router'
// 引用你要配置的路由頁面
// @ 只要在路徑中出現 無論是在那個層級 只要寫@就指向src
import Home from "@/views/home.vue"
import Jingxi from "@/views/jingxi.vue"
import Phone from "@/views/phone.vue"
import Shop from "@/views/shop.vue"
import User from "@/views/user.vue"
// 在vue中 使用 vue路由
Vue.use(VueRouter)
// 配置路由規則的地方
const routes = [
// 配置路由規則
{
path: '/home', //url的路徑
name: 'home',//給這個規則起個名字
component: Home //根據上後面的path路徑 所渲染的元件頁面
},
{
path: '/jingxi', //url的路徑
name: 'jingxi',//給這個規則起個名字
component: Jingxi //根據上後面的path路徑 所渲染的元件頁面
},
{
path: '/phone', //url的路徑
name: 'phone',//給這個規則起個名字
component: Phone //根據上後面的path路徑 所渲染的元件頁面
},
{
path: '/user', //url的路徑
name: 'user',//給這個規則起個名字
component: User //根據上後面的path路徑 所渲染的元件頁面
},
{
path: '/shop', //url的路徑
name: 'shop',//給這個規則起個名字
component: Shop //根據上後面的path路徑 所渲染的元件頁面
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
手動建立
下載 vue-router npm instrall --save vue-router
1.新建router與views資料夾 2.建立元件頁面
3.來到router下建立index.js來編寫如下程式碼
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
4.需要路由物件注入到vue例項中main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'//引用路由
Vue.config.productionTip = false
new Vue({
router,//把路由例項注入到vue例項中
render: h => h(App)
}).$mount('#app')
5.設定路由出口
千萬不要忘了設定路由出口 router-view
路由導航
標籤方式----宣告式導航
使用 router-link這個標籤來完成頁面的跳轉 其中有個to屬性就是 你要去哪裡的路徑
<template>
<div class="bar">
<!-- 宣告式導航 -->
<router-link to="/home">首頁 </router-link>
<router-link to="/jingxi">驚喜 </router-link>
<router-link to="/phone">手機 </router-link>
<router-link to="/shop">購物 </router-link>
<router-link to="/user">我的 </router-link>
</div>
</template>
宣告式導航選中樣式類
每當我們選中那個宣告式導航之後 vue會自動給這個導航新增一個router-link-active的類名 那麼我們就可以根據這個動態的類名新增樣式
js的方式--- 程式設計式導航
1.跳轉 this.$router.push("/去哪裡的路徑")
2.替換 this.$router.replace("/替換的路徑")
fun(){
this.$router.push("/home")
}
3.前進與後退 this.$router.go() 正數 前進 負數 後退
404頁面
就是當路徑沒有匹配頁面的時候 需要給使用者一個錯誤頁面的提示
// 404頁面是一個錯誤提示頁面 我們必須把路由規則配置放在最後
{
path: '*',
name: 'Err',
component: Err
},
路由規則也是由優先順序的 配置越靠前 優先順序越高
重定向----redirect
重(重新)定(定位)向(方向路徑)
在使用者第一次進入的時候 我們需要把使用者的路徑重新定位到 首頁
在路由規則中進行重定向的設定
const routes = [
{
path: '/home',
name: 'Home',
component: Home
},
{
path: '/shop',
name: 'Shop',
component: Shop
},
{
path: '/user',
name: 'User',
component: User
},
// 重定向 /預設路徑
{path:"/",redirect:"/home"},
// 404頁面是一個錯誤提示頁面 我們必須把路由規則配置放在最後
{
path: '*',
name: 'Err',
component: Err
}
]
路由出口
router-view 來設定路由出口 就是根據路由的規則 顯示規則所匹配的路由元件頁面 顯示的位置
多級路由/巢狀路由
在應用開發的過程中通常會出現在一個頁面中巢狀另外一個區域性頁面進行區域性跳轉的時候
1.新建二級路由頁面
2.在router下的index.js中先引用二級路由
3.配置二級路由的規則
(3-1)要配置規則先要確定規則寫在那 二級路由的規則寫在一級路由的規則內 使用children來標識
path可以是 /二級路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/home.vue'
import Shop from '../views/shop.vue'
import User from '../views/user.vue'
import Err from '../views/err.vue'
// 二級路由
import Era from "@/views/er/era.vue"
import Erc from "@/views/er/erc.vue"
import Erd from "@/views/er/erd.vue"
Vue.use(VueRouter)
const routes = [
{
path: '/home',
name: 'Home',
component: Home
},
{
path: '/shop',
name: 'Shop',
component: Shop
},
{
path: '/user',
name: 'User',
component: User,
// 設定二級路由
children:[
{
path: '/era',
name: 'era',
component:Era
},
{
path: '/erc',
name: 'erc',
component:Erc
},
{
path: '/erd',
name: 'erd',
component:Erd
},
]
},
// 重定向 /預設路徑
{path:"/",redirect:"/home"},
// 404頁面是一個錯誤提示頁面 我們必須把路由規則配置放在最後
{
path: '*',
name: 'Err',
component: Err
}
// {
// path: '/about',
// name: 'About',
// // route level code-splitting
// // this generates a separate chunk (about.[hash].js) for this route
// // which is lazy-loaded when the route is visited.
// component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
// }
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
path也可以是 不帶/
path也可以是 不帶/
path也可以是 不帶/
path也可以是 不帶/
path也可以是 不帶/
{
path: '/user',
name: 'User',
component: User,
// 設定二級路由
// path不帶/
children:[
{
path: 'era', // path不帶/
name: 'era',
component:Era
},
{
path: 'erc', // path不帶/
name: 'erc',
component:Erc
},
{
path: 'erd', // path不帶/
name: 'erd',
component:Erd
},
]
},
4.設定二級路由的路由出口 在對應的一級路由頁面中進行設定 使用router-view
4.設定二級路由的路由出口 在對應的一級路由頁面中進行設定 使用router-view
4.設定二級路由的路由出口 在對應的一級路由頁面中進行設定 使用router-view
4.設定二級路由的路由出口 在對應的一級路由頁面中進行設定 使用router-view
4.設定二級路由的路由出口 在對應的一級路由頁面中進行設定 使用router-view
4.設定二級路由的路由出口 在對應的一級路由頁面中進行設定 使用router-view
<div>
<router-view></router-view>
user
</div>
5.設定二級路由的導航
方式1 在設定二級路由規則的時候 path帶/來設定的時候 二級路由的路徑是 /二級路由
<div>
<router-link to="/era">era</router-link>
<router-link to="/erc">erc</router-link>
<router-link to="/erd">erd</router-link>
</div>
方式2 在設定二級路由規則的時候 path不不不不不不不不不不不不不不帶/////////來設定的時候
二級路由的路徑是 /一級路由/二級路由
<router-link to="/user/era">era</router-link>
<router-link to="/user/erc">erc</router-link>
<router-link to="/user/erd">erd</router-link>
路由傳參/動態路由匹配
在vue中需要把資料從一個頁面傳遞到另外一個頁面的時候
方式
params方式
1.在需要接收資料的路由規則中設定接收引數
{
path: '/shop/:xiaoming',//設定接收引數
name: 'Shop',
component: Shop
},
2.傳送
宣告式
<router-link :to="{name:'你要去的路由的name',params:{設定的接收引數:'傳遞的資料'}}"></router-link>
<template>
<div>
home
<!-- <router-link :to="{name:'你要去的路由的name',params:{設定的接收引數:'傳遞的資料'}}">點我把資料使用宣告式方式傳遞到shop中</router-link> -->
<router-link :to="{name:'Shop',params:{xiaoming:'呵呵我是傳遞的額資料'}}">點我把資料使用宣告式方式傳遞到shop中</router-link>
</div>
</template>
程式設計式
methods:{
fun(){
this.$router.push({name:'Shop',params:{xiaoming:'1111呵呵我是傳遞的額資料'}})
}
}
3.接收
直接使用this.$route.params.xxxx
<div>
shop----{{this.$route.params.xiaoming}}
</div>
query方式
1.傳送
語法:
<!-- query傳參可以使用name 或者 path -->
<router-link :to="{name:'Shop',query:{xiaoming:'我是資料'}}">點我宣告式傳參query</router-link>
<router-link :to="{path:'/shop',query:{xiaoming:'我是資料'}}">點我宣告式傳參query2222</router-link>
2.接收
this.$route.query.xxxx
query和params的區別
語法上區別:
query方式傳參分為兩步 傳送資料的時候可以使用name還可以使用path來進行 接收的時候使用this.$route.query.xxxxxx
params 傳參需要三步 並且在傳送資料的時候只能是name 接收的時候使用this.$route.params.xxxx
url展示上 params在url上面只展示資料 相對來說傳參安全一點 queryurl 有key還有val 相對來說不安全
$router與$route區別
$router物件: 是vue路由的物件 他是路由例項 他是一個路由全域性物件 包含了與路由相關的關鍵屬性
$route物件 : 是跳轉到指定路由的區域性物件 一個路由頁面就有一個$route物件
路由模式
在vue中路由模式使用 mode來進行指定
1.hash模式 預設模式 你不寫就是hash模式
2.history模式
區別 | hash | history |
---|---|---|
url展示上 | url帶# | url不帶# |
瀏覽器相容性 | 相容性好 | html5新特性所以對ie相容性不好 |
瀏覽器重新整理 | 重新整理之後正常顯示 | 上線之後重新整理頁面丟失 |
路由守衛/路由鉤子/導航守衛
就是在路由跳轉的時候觸發的鉤子函式
全域性守衛
全域性前置
在路由跳轉的時候 進入下一個路由之前觸發
beforeeach
to 去哪裡
from 從哪裡來
next 下一步 必須有
router.beforeEach((to,from,next)=>{
console.log(to)
console.log(from)
next()
})
全域性後置
在路由跳轉的時候 進入下一個路由後觸發
aftereach()
路由獨享守衛
僅僅只會對一個路由生效
beforeRouterEnter()
to 去哪裡
from 從哪來
next 下一步
{
path: '/user',
name: 'user',
component: () => import('../views/user.vue'),
// d當前路由生效
beforeEnter(to,from,next){
console.log(to)
console.log(from)
next()
}
元件內守衛
beforeRouteEnter() 進入當前元件的時候呼叫
beforeRouteLeave() 離開當前元件的時候呼叫
<template>
<div>
shop
</div>
</template>
<script>
export default {
// 元件內守衛
beforeRouteEnter(to,from,next){
console.log("進來了");
console.log(to);
console.log(from);
next()
},
beforeRouteLeave(to,from,next){
console.log(to);
console.log(from);
if(confirm("您確定離開嗎")){
next()
}else{
next(false)//下一步我什麼都不幹
}
}
}
</script>
<style>
</style>
擴充套件--懶載入
路由懶載入 路由頁面按需載入
因為在傳統的vue專案中如果使用了路由可能會出現 首頁白屏問題 也會造成很大的效能問題
-
import匯入
component: () => import('你要顯示路由的頁面路徑')
-
非同步元件
component: (resolve) => require(['你要顯示的路由頁面路徑即可'], resolve),
擴充套件--路由的更多屬性
meta 路由記錄/路由元資訊
我們給路由的規則中新增一個meta的物件 那麼就可以在其中儲存一些資訊 在頁面進行使用
{
path: '/phone',
name: 'phone',
component: () => import('../views/phone.vue'),
// meta元資訊
meta:{
text:"我是路由中的meta資訊"
}
在當前頁面中使用這個meta資訊
this.$route.meta.xxx
<template>
<div>
phone---{{this.$route.meta.text}}
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
在元件內獲取路由全部規則
this.$router.options.routes
前後端資料互動
資料請求在vue中有多種方式
1.原生或者jquery的ajax
2.vue-resource vue官方出品 vue2x之後已經停止更新了
3.axios 是一個第三方的資料請求 他是基於XHr物件的 但是在XHR物件之上使用promise進行了封裝 讓他更符合當下的主流語法規範
4.fetch請求 是es最新的規範
axios
因為是第三方的所有需要先下載 npm install --save axios
基本使用
axios.get() axios.post()
axios()
<template>
<div>
<h1>基本axios的使用</h1>
<button @click="fun()">點我傳送請求</button>
</div>
</template>
<script>
import axios from "axios"
export default {
methods:{
fun(){
// 開始請求資料
axios({
url:"http://api.artgoer.cn:8084/artgoer/api/v1/user/324380/v3/topic/topicHomeByLabel?pageIndex=1&token=b544cd63-6d42-46fe-a96c-3cf96bae3113&topicId=62187",
// 注意單詞
method:"GET"
}).then((ok)=>{
console.log(ok)
}).catch((err)=>{
console.log(err);
})
}
}
}
</script>
<style>
</style>
資料請求封裝與攔截器
資料請求封裝
公司中就不一定是按照咱們所學的方式進行封裝了 因為有的公司可能在封裝的時候就是單純的把請求提取出來
有一些可能使用promise來進行封裝 有一些公司可能是用async 來進行封裝
我們需要認識一個資料夾 api 這個資料夾通常百分之90都是用來存放資料請求的
使用promise來進行封裝(提高了複用性 讓自己寫的程式碼叼一點)
api資料夾中進行封裝
import axios from "axios"
// 在其中進行請求的封裝
let getlink=(url)=>{
// resolve成功資料會交給then來接收 reject失敗的資料會交給catch來接收
return new Promise((resolve,reject)=>{
// 就來寫你的非同步操作
axios({
url,
method:"GET"
}).then((ok)=>{
resolve(ok)
}).catch((err)=>{
reject(err)
})
})
}
// 千萬不要忘了
export default getlink
在元件中引用使用
<template>
<div>
<h1>使用封裝來進行請求</h1>
</div>
</template>
<script>
import getlink from "@/api/getapi.js"
export default {
created(){
getlink("http://api.artgoer.cn:8084/artgoer/api/v1/user/324380/v3/topic/topicHomeByLabel?pageIndex=1&token=b544cd63-6d42-46fe-a96c-3cf96bae3113&topicId=62187").then((ok)=>{
console.log(ok)
}).catch((err)=>{
console.log(err)
})
}
}
</script>
<style>
</style>
axios攔截器
如果需要編寫攔截器 我們需要建立一個util資料夾工具資料夾(與專案業務無關的一些程式碼 但是有了這些程式碼可以提高效率)
什麼是攔截器?
攔截請求的一個技術
有些情況下 我們需要在每次請求的時候都要攜帶一個引數(比如:使用者的登入狀態資訊) 那麼我們就可以放到攔截器中 因為每次請求攔截器都會先攔截到 讓後才去傳送請求 那麼我們就可以在攔截器中吧這些引數資訊進行統一的新增 不需要每次請求都寫一遍
1.請求攔截 我們在傳送請求的時候 他會攔截
2.相應攔截 伺服器把資料給我們的時候先被攔截器所攔截
// 就是用來存放攔截器的
// 引用axios
import axios from "axios"
// 1建立axios例項並且交給一個變數方便使用\
const service = axios.create()
// 2.建立請求與相應攔截
// 新增請求攔截器
service.interceptors.request.use(function (config) {
// 在傳送請求之前做些什麼
return config;
}, function (error) {
// 對請求錯誤做些什麼
return Promise.reject(error);
});
// 新增響應攔截器
service.interceptors.response.use(function (response) {
// 對響應資料做點什麼
return response;
}, function (error) {
// 對響應錯誤做點什麼
return Promise.reject(error);
});
// 千萬不要忘了暴露
export default service
請求封裝呼叫攔截器
// 資料封裝於攔截器
import service from "@/util/service.js"
let getblink=(url)=>{
return new Promise((resolve,reject)=>{
// 使用request請求
service.request({
url,
method:"GET"
}).then((ok)=>{
resolve(ok)
}).catch((err)=>{
reject(err)
})
})
}
export default getblink
mockjs 模擬資料
在前後端分離開發的過程中 有的時候後臺資料在我們編寫前臺的時候還沒有寫好 我們可以在後臺沒有準備好的時候 先試用模擬資料建立資料 然後用請求請求我們的模擬資料進行展示、
資料json json是鍵值對 但是後臺在建立資料的時候 這個key起什麼名字 後臺可能會問你咱倆一起對下介面資料吧(理想派 我們可以把我們的模擬資料的key來進行和他溝通) 他自己默默的把後臺資料寫好了 然後給你了(沉默派 你不知道資料裡面的東西代表什麼 你的嘴要甜一點 發信息說 哥 我剛來公司 咱們公司的流程可能不太熟 您看 某某key是個什麼意思 你可以問題要介面文件 你也可以過去問他)
使用
1.mockjs是一個第三方的模擬資料的庫
npm install --save mockjs (注意單詞沒有點)
2.新建一個mock資料夾 這個資料夾今後在工作中通常就是寫模擬資料的 在其中建立一個存放模擬資料的資料夾 與編寫程式碼的index.js
3.新建模擬資料 是以.json結尾的檔案
4.在index.js來編寫 mockjs的程式碼
let Mock=require("mockjs")
// Mock.mock("隨便寫一個請求的介面地址","請求方式",require("你的模擬資料路徑"))
Mock.mock("/data/list","GET",require("./data/demo.json"))
5.在main.js中引用mock
import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 引用mock
require("./mock")
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
注意 一定要重啟專案
axios傳送get請求
params屬性來進行get資料的傳送
axios傳送post請求
data屬性來進行post資料傳送
傳送post需要使用URLsearchParams()來進行引數傳遞的轉換
並且配合append來進行接收
// 傳送post資料不能直接發需要轉換
let usp=new URLSearchParams()
// usp.append(你要傳送的key,你要傳送的val)
usp.append("dengluname",this.inputaval)
usp.append("denglupwd",this.inputbval)
mixins 混入
多個元件中都要使用一些相同的方法
混入就是vue元件中一個提高元件複用性的一個技術 他可以讓多個元件中重複使用的方法 等內容進行提取出來然後在想使用的地方直接使用
分類
1.全域性混入
慎用 因為會汙染整個專案
1.資料夾mixins與檔案的建立 並且全域性混入的檔案寫法和區域性混入相同
2.引用呼叫的時候需要在main.js中引用呼叫 剩下在任何元件中就可以直接使用混入的內容了
// 1.混入引用
import xiaoming from "./mixins/xiaoming.js"
// 2。呼叫
Vue.mixin(xiaoming)
2.區域性混入
1.新建資料夾mixins檔案 來存放我們提取出來的內容 建立js檔案來進行存放
2.在js中建立一個物件寫入你想複用的內容
let xiaoming={
// 提取出想複用的方法
methods:{
fun(){
console.log("你好");
}
}
}
export default xiaoming
3.在想使用的元件中引用呼叫使用
<template>
<div>
<h1>混入的使用</h1>
<!-- 3.直接使用混入的方法 -->
<button @click="fun()">點我呼叫函式</button>
<button @click="funb()">點我呼叫函式</button>
</div>
</template>
<script>
// 1.引用
import xiaoming from "@/mixins/xiaoming.js"
export default {
// 2.呼叫 使用mixins來進行呼叫 mixins是一個數組
mixins:[xiaoming]
}
</script>
<style scoped>
div{
font-size:0.2rem;
}
</style>
混入中除了函式 生命週期 計算屬性等也可以 data也可以
自定義指令----directives
在現有指令不夠的情況下我們可以建立自定義指令
指令就是html的屬性 屬性就是給html新增特殊的功能
寫在與data methods等同級的位置
語法:
direactives:{
自定義指令的名字:{
自定義指令的鉤子函式(形參就是你繫結這個自定義指令的當前dom元素){
你的邏輯
}
},
自定義指令的名字:{
},
}
<template>
<div>
自定義自定義指令
<input type="text">
<input type="text" v-xiaoming>
<input type="text">
<input type="text">
<input type="text">
<input type="text">
<input type="text">
<input type="text" v-xiaohong>
</div>
</template>
<script>
export default {
directives:{
xiaoming:{
// 自定義指令的鉤子函式
// bind 指令繫結到元素之上只執行一次
// inserted 是我們百分之90以上使用的 繫結的這個指令的元素 在頁面展示的時候呼叫
// update 當元件節點更新的時候呼叫
// componentUpdated 指令所在的元件節點以及所有的子節點更新完畢之後呼叫
// unbind 當前dom被移除的時候呼叫
inserted(el){
el.focus()
}
},
xiaohong:{
inserted(el){
el.style.backgroundColor="red";
}
}
}
}
</script>
<style scoped>
div{
font-size: 0.2rem;;
}
</style>
ref
在vue中預設是沒有dom操縱的 有些時候我們就是需要使用dom的操縱 那麼就可以使用vue提供的ref來進行
基本使用
<template>
<div>
<h1>ref的基本使用</h1>
<!-- 1.給你要操作的dom起個名字 ref="你起的名字" -->
<input type="text" ref="demoinput">
<button @click="fun()">點我得到輸入框的值</button>
</div>
</template>
<script>
export default {
methods:{
fun(){
// 2.找到ref對應的內容進行操縱
console.log(this.$refs.demoinput.value)
}
}
}
</script>
<style scoped>
div{
font-size:0.2rem;
}
</style>
擴充套件--$set以及原理
你在開發中有沒有遇見過資料改變了但是檢視沒有改變的問題 你是怎麼解決的?
<template>
<div>
<h1>$set</h1>
<h1>{{obj.name}}</h1>
<button @click="obj.name='haha'">點我修改</button>
<h1>--------------------------------</h1>
<h1>age:{{obj.age}}</h1>
<button @click="fun()">點我新增一個age</button>
</div>
</template>
<script>
export default {
data(){
return {
obj:{
name:"xixi"
}
}
},
methods:{
fun(){
this.obj.age=18
console.log(this.obj.age);
}
}
}
</script>
<style scoped>
div{
font-size: 0.2rem;
}
</style>
出現的場景是 如果我們在vue中向data定義的陣列獲取物件中新增新的屬性的時候 就會出現資料變了但是檢視沒有發生改變
原因 :因為雙向繫結中 依賴資料劫持(object.defineProperty()) 資料劫持有一個非常大的bug 他只會劫持初始化的時候data有的資料 但是當程式執行之後 在給data的屬性插入新的內容的時候 由於資料劫持劫持不到 就沒有雙向綁定了 沒有雙向綁定了 當然資料變了檢視不會發生改變
$set的使用
所以我們為了解決這種資料變檢視不發生改變的問題 我們使用$set來解決
語法: this.$set( 你要操縱的資料,新增的key,新增的val )
fun(){
// this.obj.age=18
// $set來進行新增新屬性
this.$set(this.obj,"age",666)
console.log(this.obj.age);
}
動態元件
多個元件使用同一個掛載點(component)並且動態元件
掛載點這個掛載點放在頁面的那個地方 那麼動態切換的內容就在哪裡展示:
<component :is="當前掛載點需要顯示那個元件"></component>
1.新建多個元件
2.在需要動態顯示這多個元件的位置使用 來設定掛載點 並且引用呼叫 你要使用的元件到當前頁面中
<component :is="當前掛載點需要顯示那個元件"></component>
3.建立變數 在變數中設定多個元件初始化顯示的內容
data(){
return{
com:"你要初始化顯示的元件名"
}
},
4.把這個變數插入到掛載點的is上
<component :is="你建立的變數"></component>
5.想動態切換 只需要 改變 你儲存顯示元件的那個變數即可
keep-alive
引子
我們新建的路由頁面 使用者在路由頁面中填寫內容之後 在進行路由的切換 會發現資料不見了
同樣的我們在使用動態元件進行切換的時候 會和路由一樣 資料丟失
出現的原因
因為路由或者動態元件 在切換的時候 vue會在每次切換的過程中 對切換的元件進行例項的重新建立
keep-alive
keep-alive 使用他可以把元件中的狀態保留在記憶體中 防止元件重複dom渲染 減少了在切換的時候效能上面損耗 提高使用者體驗
語法 :
<keep-alive>
你要儲存狀態的元件放進去
<kepp-alive>
屬性
在vue2.1之後 kepp-alive加入了新的特性 引進了兩個屬性
incloude 你要快取誰
<keep-alive include="Da,Dc">
<component :is="com"></component>
</keep-alive>
excloude 你不快取誰
<keep-alive exclude="Da">
<component :is="com"></component>
</keep-alive>
incloude 與 excloude 同時都寫了聽誰的?
excloude的優先順序高
鉤子函式keep-alive
這兩個鉤子函式需要寫在被keep-alive管理的元件之內 以data methods等同級
activated 進入被keep-alive管理的元件時候呼叫
deactivated 離開被keep-alive管理的元件時候呼叫
nextTick
vue的響應式 不是在 資料變化了之後 DOM立即改變 而是按照一定的策略進行dom的更新。
<template>
<div>
<!-- 資料變了 頁面的dom不是立即改變 -->
<h1 ref="demoh">{{text}}</h1>
<button @click="fun()">點我修改</button>
</div>
</template>
<script>
export default {
data(){
return {
text:"你好麼麼噠!!!"
}
},
methods:{
fun(){
this.text="我變了!!!"
// 我在資料修改之後 直接讀取dom看看變了沒有變就知道了
console.log(this.$refs.demoh.innerText)
}
}
}
</script>
<style>
</style>
資料修改非同步說明
簡單來說 vue在資料修改之後 檢視是不會立即更新 而是等同一事件迴圈中的所有資料都變化了 之後 在同一進行頁面檢視的更新
原理:
1 vue先進行資料的修改 是一個同步任務 同一事件迴圈上的所有同步任務 進行一個個的執行 但是這個時候 還沒有涉及到dom的任何操作
2.vue開啟一個非同步列隊 把在上面事件迴圈中的資料變化進行非同步的緩衝
3 同步任務執行完畢 開始執行非同步的列隊任務 , 更新dom
什麼是nextTick
會在dom載入完畢之後 立即執行的一個方法
<template>
<div>
<h1>nextTick</h1>
<h1 ref="demoh">{{text}}</h1>
</div>
</template>
<script>
export default {
created(){
// console.log(this.$refs.demoh.innerText);
this.$nextTick(()=>{
console.log(this.$refs.demoh.innerText);
})
},
data(){
return {
text:"你好!!!!!"
}
}
}
</script>
<style>
</style>
擴充套件---瀏覽器自動開啟與修改埠
在根路徑下建立vue.config.js 寫入open 自動開啟
module.exports={
devServer:{
open:true,//自動開啟瀏覽器
}
}
修改埠
module.exports={
devServer:{
open:true,//自動開啟瀏覽器
port:8888 //修改埠
}
}