文章目錄
歡迎訪問筆者個人技術博客:http://rukihuang.xyz/
一、Vue概述
1.1 介紹
- Vue.js是一個構建數據驅動的 web 界面的漸進式框架。Vue.js 的目標是通過儘可能簡單的 API 實現響應的數據綁定和組合的視圖組件。它不僅易於上手,還便於與第三方庫或既有項目整合。
1.2 MVVM模式
- MVVM是Model-View-ViewModel的簡寫。它本質上就是MVC 的改進版。MVVM 就是將其中的View 的狀態和行爲抽象化,讓我們將視圖 UI 和業務邏輯分開
- MVVM模式和MVC模式一樣,主要目的是分離視圖(View)和模型(Model)
- Vue.js 是一個提供了 MVVM 風格的雙向數據綁定的 Javascript 庫,專注於View 層。它的核心是 MVVM 中的 VM,也就是 ViewModel。 ViewModel負責連接 View 和 Model,保證視圖和數據的一致性,這種輕量級的架構讓前端開發更加高效、便捷。
1.3 Vue的快速入門
- 在script腳本區域,創建vue對象
- 聲明
el: "#[區域id]"
,表示這塊區域由vue接管。 - 聲明
data: {}
,數據域 - 在body塊,使用插值表達式,將
data
域中聲明的變量插到{{變量名}}
中
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>快速入門</title>
<!--引入vue.js-->
<script src="js/vuejs-2.5.16.js"></script>
</head>
<body>
<div id="app">
{{message}} <!-- //vue的插值表達式,把data中定義的數據顯示到此處 -->
</div>
</body>
<script>
//view model
//創建Vue對象
new Vue({
el: "#app",//由vue接管id爲app區域
data: {
message: "hello, vue", //注意:此處不要加分號
}
});
</script>
</html>
1.3.1 插值表達式
- 數據綁定的最常見形式用雙大括號語法的文本插值,無論何時,vue對象中
data
數據發生改變,插值出的內容都會更新。 - 支持的表達式,如下:
<!-- 支持 三目運算符, 但不支持賦值語句-->
{{ok? "A":"B"}}
<!--數學運算-->
{{number + 1}}
- 賦值語句與流程控制語句都不會生效!
<!-- 插值表達式不支持變量的聲明 -->
{{var a = 1 }}
<!-- 插值表達式不支持條件判斷流程控制 -->
{{ if(ok) return message}}
二、Vue常用指令
2.1 v-on
- 用
v-on
指令鑑定DOM事件,並會觸發javascript代碼
2.1.1 v-on:click
<!DOCTYPE html>
<html xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>v-on:click</title>
<script src="js/vuejs-2.5.16.js"></script>
</head>
<body>
<div id="app">
{{message}}
<button v-on:click="fun1('vue v-on')" >vue的onclick事件</button>
</div>
</body>
<script>
//view model
new Vue({
el: "#app",
data: {
message: "hello vue"
},
methods: {
fun1: function(message) {//fun1爲button中的方法名,message爲傳的參
this.message = message;
//點擊button後會觸發方法,將data中的message改爲傳入的參數
}
}
});
</script>
</html>
2.1.2 v-on:keydown
- 我對
event
對象的理解:鍵盤按下,鼠標按下等,都稱爲一個“事件”,只有事件發生了,纔會觸發功能函數。 event
對象代表事件的狀態,比如事件在其中發生的元素、鍵盤按鍵的狀態、鼠標的位置、鼠標按鈕的狀態。事件通常與函數結合使用,函數不會在事件發生前被執行!- 注意點:
- 使用不帶圓括號的形式,event 對象將被自動當做實參傳入
- 使用帶圓括號的形式,我們需要使用 $event 變量顯式傳入 event 對象,如果不傳入可能最終找到的是全局的
window .event
<!DOCTYPE html>
<html xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>v-on:keydown</title>
<script src="js/vuejs-2.5.16.js"></script>
</head>
<body>
<div id="app">
<!--鍵盤按下事件-->
<!--使用不帶圓括號的形式,event 對象將被自動當做實參傳入;-->
<!--使用帶圓括號的形式,我們需要使用 $event 變量顯式傳入 event 對象。-->
vue: <input type="text" v-on:keydown="fun($event)">
<!--<input type="text" v-on:keydown="fun">-->
<hr>
傳統Js: <input type="text" onkeydown="showKeyCode()">
</div>
</body>
<script>
//view model
new Vue({
el: "#app",
methods: {
// $event 它是vue中的事件對象,和傳統js的event對象是一樣的
fun: function (event) {
var keyCode = event.keyCode;
if (keyCode < 48 || keyCode > 57) {
//不讓鍵盤起作用
event.preventDefault();
}
}
}
});
//傳統js的鍵盤按下事件
function showKeyCode() {
//event對象和 document對象 window對象 是一樣的, 可以不定義直接使用
//alert("success");
var keyCode = event.keyCode;
if(keyCode < 48 || keyCode > 57) {
event.preventDefault();
}
// alert(keyCode);
}
</script>
</html>
2.1.3 v-on:mouseover
event.stopPropagation()
阻止冒泡。
<!DOCTYPE html>
<html xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>v-on:mouseover</title>
<style>
#div, #div2 {
background-color: red;
}
</style>
<script src="js/vuejs-2.5.16.js"></script>
</head>
<body>
<div id="app">
<!--@mouseover等價於 v-on:mouseover
@事件名稱 就是 v-on:事件名稱 的簡寫方式
-->
<div v-on:mouseover="fun1" id="div">
<textarea v-on:mouseover="fun2($event)">這是一個文件域</textarea>
</div>
<div onmouseover="fun3" id="div2">
<textarea onmouseover="fun4()">這是一個文件域</textarea>
</div>
</div>
</body>
<script>
//view model
new Vue({
el: "#app",
methods: {
fun1: function () {
alert("鼠標懸停在div上");
},
fun2: function (event) {
alert("鼠標懸停在文件域上");
event.stopPropagation();//阻止冒泡
}
}
});
//傳統js
function fun3() {
alert("鼠標移動到了傳統div2上了");
}
function fun4() {
alert("鼠標移動到了傳統文件域上了");
event.stopPropagation();
}
</script>
</html>
2.1.4 事件修飾符
- vue爲
v-on
提供了事件修飾符來處理DOM事件細節,如event.preventDefault()
(通知瀏覽器不要執行與事件關聯的默認動作)、event.stopPropagation()
(不再派發事件)。.stop
.prevent
.capture
.self
.once
<!DOCTYPE html>
<html xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>v-on:事件修飾符</title>
<script src="js/vuejs-2.5.16.js"></script>
</head>
<body>
<div id="app">
<!--阻止事件執行行爲 -->
<form action="https://www.baidu.com/" method="post" v-on:submit.prevent>
<input type="submit" value="提交">
</form>
<form action="https://www.baidu.com/" method="post" onsubmit="return checkForm()">
<input type="submit" value="提交">
</form>
</div>
</body>
<script>
//view model
new Vue({
el: "#app"
});
//傳統Js方式
function checkForm() {
alert(1);
//表單驗證必須有一個明確的boolean類型返回值
//在應用驗證方法時必須加上 return 方法名稱
//return false表示表單驗證不通過,action的url不會訪問
return false;
}
</script>
</html>
2.1.5 按鍵修飾符
- vue允許
v-on
在監聽事件時添加按鍵修飾符.enter
.tab
.delete
.esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
.meta
<!DOCTYPE html>
<html xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>v-on:按鍵修飾符</title>
<script src="js/vuejs-2.5.16.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-on:keydown.enter="fun1()">
</div>
</body>
<script>
//view model
new Vue({
el: "#app",
data: {
fun1: function () {
alert("按下的是回車")
}
}
});
</script>
</html>
- 補充
v-on
的完整寫法和簡易寫法
<!-- 完整語法 -->
<a v-on:click="doSomething">...</a>
<!-- 縮寫 -->
<a @click="doSomething">...</a>
2.2 v-text / v-html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>v-text與v-html</title>
<script src="js/vuejs-2.5.16.js"></script>
</head>
<body>
<div id="app">
<div v-html="message"></div>
<div v-text="message"></div>
<div id="div1"></div>
<div id="div2"></div>
</div>
</body>
<script>
//view model
//vue接管這塊區域
new Vue({
el: "#app",
data: {
message: "<h1>hello</h1>"
}
});
//傳統js的 innerHTML(能解析標籤) 和 innerText(純文本,不能解析標籤)
window.onload = function () {
document.getElementById("div1").innerHTML="<h1>hello</h1>";
document.getElementById("div2").innerText="<h1>hello</h1>";
}
</script>
</html>
2.3 v-bind
- 插值語法不能使用在html標籤屬性上,應使用
v-bind
指令
<!DOCTYPE html>
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>v-text與v-html在v-bind上的使用</title>
<script src="js/vuejs-2.5.16.js"></script>
</head>
<body>
<div id="app">
<font size="5" v-bind:color="ys1" >hello</font>
<font size="5" :color="ys2" >hello</font>
</div>
</body>
<script>
//view model
//插值表達式不能用於html標籤的屬性取值
//若想給html標籤的屬性設置變量的值,需要使用v-bind
//v-bind簡化寫法, 直接使用:
new Vue({
el: "#app",
data: {
ys1: "red",
ys2: "green"
}
});
</script>
</html>
- 補充
v-bind
的完整寫法和簡易寫法
<!-- 完整語法 -->
<a v-bind:href="url">...</a>
<!-- 縮寫 -->
<a :href="url">...</a>
2.4 v-model
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>v-model</title>
<script src="js/vuejs-2.5.16.js"></script>
</head>
<body>
<div id="app">
<form action="" method="post">
用戶名:<input type="text" name="username" v-model="user.username">
密碼:<input type="text" name="password" v-model="user.password">
</form>
</div>
</body>
<script>
//view model
new Vue({
el: "#app",
data: {
user: {
username: "test",
password: "1234"
}
}
});
</script>
</html>
2.5 v-for
2.5.1 操作數組
<li v-for="item in arr">{{item}}</li>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>v-for遍歷數組</title>
<script src="js/vuejs-2.5.16.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in arr">{{item}}</li>
</ul>
</div>
</body>
<script>
//view model
new Vue({
el: "#app",
data: {
arr: [1,2,3,4,5]
}
});
</script>
</html>
2.5.2 操作對象
<li v-for="(key, value) in product"> {{key}} === {{value}}</li>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>v-for遍歷對象</title>
<script src="js/vuejs-2.5.16.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="(key, value) in product"> {{key}} === {{value}}</li>
</ul>
</div>
</body>
<script>
new Vue({
el: "#app",
data: {
product: {
id: "1",
name: "電腦",
price: 2000
}
}
});
</script>
</html>
2.5.3 操作對象數組
<tr v-for="(item, index) in products">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>v-for遍歷對象</title>
<script src="js/vuejs-2.5.16.js"></script>
</head>
<body>
<div id="app">
<table border="1">
<tr>
<td>序號號</td>
<td>編號</td>
<td>名稱</td>
<td>價格</td>
</tr>
<tr v-for="(item, index) in products">
<td>{{index}}</td>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
</tr>
</table>
</div>
</body>
<script>
//view model
new Vue({
el: "#app",
data: {
products: [
{id: 1, name: "電腦", price: 5000},
{id: 2, name: "手機", price: 3000},
{id: 3, name: "電視", price: 4000},
]
}
});
</script>
</html>
2.6 v-if / v-show
v-if
:根據表達式的值決定是否渲染元素(決定有還是沒有)v-show
:根據表達式的值切換display
屬性(已有,決定show還是none)
<!DOCTYPE html>
<html xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>v-if與v-show</title>
<script src="js/vuejs-2.5.16.js"></script>
</head>
<body>
<div id="app">
<span v-if="flag">hello</span>
<span v-show="flag">halo</span><br>
<button v-on:click="toggle">切換</button>
</div>
</body>
<script>
//view model
new Vue({
el: "#app",
data: {
flag: false
},
methods: {
toggle: function () {
this.flag = ! this.flag;
}
}
});
</script>
</html>
三、Vue生命週期
- 每個Vue對象在被創建之前都要經過一系列的初始化過程。
-
具體生命狀態
beforeCreate
- 數據還沒有監聽,沒有綁定到vue對象實例,同時也沒有掛載對象
created
- 數據已經綁定到了對象實例,但是還沒有掛載對象
beforeMount
- 模板已經編譯好了,根據數據和模板已經生成了對應的元素對象,將數據對象關聯到了對象的
el
屬性,el
屬性是一個HTMLElement
對象,也就是這個階段,vue實例通過原生的createElement
等方法來創建這個html片段,準備注入到我們vue實例指明的el屬性所對應的掛載點
- 模板已經編譯好了,根據數據和模板已經生成了對應的元素對象,將數據對象關聯到了對象的
mounted
- 將el的內容掛載到了
el
,相當於我們在jquery執行了(el).html(el)
,生成頁面上真正的dom,上面我們就會發現dom的元素和我們el
的元素是一致的。在此之後,我們能夠用方法來獲取到el
元素下的dom對象,並進行各種操作
- 將el的內容掛載到了
beforeUpdate
- 數據更新到dom之前,我們可以看到
$el
對象已經修改,但是我們頁面上dom的數據還沒有發生改變
- 數據更新到dom之前,我們可以看到
updated
- dom結構會通過虛擬dom的原則,找到需要更新頁面dom結構的最小路徑,將改變更新到dom上面,完成更新
beforeDestroy
destroyed
- 實例的銷燬,vue實例還是存在的,只是解綁了事件的監聽還有watcher對象數據與view的綁定,即數據驅動
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>vuejs生命週期</title> <script src="js/vuejs-2.5.16.js"></script> </head> <body> <div id="app"> {{message}} </div> </body> <script> var vm = new Vue({ el: "#app", data: { message: 'hello world' }, beforeCreate: function() { console.log(this); showData('創建vue實例前', this); }, created: function() { showData('創建vue實例後', this); }, beforeMount: function() { showData('掛載到dom前', this); }, mounted: function() { showData('掛載到dom後', this); }, beforeUpdate: function() { showData('數據變化更新前', this); }, updated: function() { showData('數據變化更新後', this); }, beforeDestroy: function() { vm.test = "3333"; showData('vue實例銷燬前', this); }, destroyed: function() { showData('vue實例銷燬後', this); } }); function realDom() { console.log('真實dom結構:' + document.getElementById('app').innerHTML); } function showData(process, obj) { console.log(process); console.log('data 數據:' + obj.message) console.log('掛載的對象:') console.log(obj.$el) realDom(); console.log('------------------') console.log('------------------') } //vm.message = "good..."; vm.$destroy(); </script> </html>
四、Vue的ajax請求
4.1 axios
- 引入axios,可以通過
script
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
4.1.1 get請求
const axios = require('axios');
// Make a request for a user with a given ID
// 通過給定的id來發送請求
axios.get('/user?ID=12345')
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.finally(function () {
// always executed
});
// Optionally the request above could also be done as
// 也可以通過json格式 {params: {key: value}}
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.finally(function () {
// always executed
});
// Want to use async/await? Add the `async` keyword to your outer function/method.
async function getUser() {
try {
const response = await axios.get('/user?ID=12345');
console.log(response);
} catch (error) {
console.error(error);
}
}
4.1.2 post請求
//以json格式傳入參數
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});