Vue基本語法
一、Hello Vue
1.1 引入 Vue.js 檔案
Vue.js 提供了兩個版本的檔案:
-
開發環境:包含了使用幫助的命令列警告
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
-
生成環境:優化了尺寸和速度
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
這裡我們採用開發環境版本的 Vue.js
檔案
1.2 定義檢視物件並新增插值表示式
<!--2.定義檢視物件,並新增一個插值表示式 --> <div id="app"> {{message}} </div>
1.3 建立Vue物件繫結到之前申明的檢視物件上,並設定 message 值
<script>
<!--3.建立Vue物件繫結到之前申明的檢視物件上,並設定 message 值-->
var app = new Vue({
el: "#app",
data: {
message: "Hello Vue!"
}
});
</script>
完整程式碼如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Hello Vue</title> <!--1.匯入 JS 檔案--> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <!--2.定義檢視物件,並新增一個插值表示式 --> <div id="app"> {{message}} </div> <script> <!--3.建立Vue物件繫結到之前申明的檢視物件上,並設定 message 值--> var app = new Vue({ el: "#app", data: { message: "Hello Vue!" } }); </script> </body> </html>
二、Vue 常用屬性
2.1 el
只在用 new
建立例項時生效,用於指定掛載元素,表示Vue 的作用域。如之前的例項 #app 就是將 Id
值為 app
的元素掛載到 vue 物件上去。
2.2 data
Vue 例項的資料物件,可以包含多種型別的資料:
<div id="app"> {{string}} <br> {{integer}} <br> {{array[2]}} <br> {{user.name}} -- {{user.age}} </div> <script> var app = new Vue({ el: "#app", data: { string: "文字型別的資料", integer:18, array:[ new Date("2020-12-01"), new Date("2020-12-02"), new Date("2020-12-03"), new Date("2020-12-04") ], user:{ name:"張三", age:23 } } }); </script>
2.3 computed
計算屬性,它的結果會被快取,除非依賴的響應式屬性變化才會重新計算。注意,如果某個依賴 (比如非響應式屬性) 在該例項範疇之外,則計算屬性是不會被更新的。
<div id="app">
{{userinfo}}
</div>
<script>
var app = new Vue({
el:"#app",
data:{
name:"張三",
age:18,
},
computed:{
userinfo:function(){
return "姓名:"+ this.name +";年齡:"+ this.age;
}
}
});
</script>
2.4 methods
方法物件,申明 Vue 物件的行為:
<div id="app">
<!-- v-on:click 繫結按鈕單擊事件 -->
<button v-on:click="showName()">顯示使用者姓名</button>
<button v-on:click="showAge()">顯示使用者年齡</button>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
name:"張三",
age:18
},
methods:{
showName :function(){
alert("name:"+this.name)
},
showAge :function(){
alert("age:"+this.age);
}
}
});
</script>
2.5 watch
偵聽器,當需要在資料變化時執行非同步或開銷較大的操作時可以採取這種方式:
<div id="app">
<button v-on:click="toUpperCase">轉大寫</button>
<button v-on:click="toLowerCase ">轉小寫</button>
<br>
{{message}}
</div>
<script>
var app = new Vue({
el:"#app",
data:{
message:"hello vue"
},
methods:{
toUpperCase:function(){
this.message = this.message.toUpperCase();
},
toLowerCase:function(){
this.message = this.message.toLowerCase();
}
},
watch: {
message:function(newValue, oldValue) {
console.log("原值:"+oldValue);
console.log("新值:"+newValue);
}
},
});
</script>
點選轉大寫按鈕,然後點選轉小寫按鈕,檢視控制檯輸出:
原值:hello vue
新值:HELLO VUE
原值:HELLO VUE
新值:hello vue
2.6 template
模版物件,用來動態新增 DOM:
<div id="app1">
</div>
<!--==============-->
<div id="app2">
</div>
<template id="template">
<h1>引入template標籤的形式</h1>
</template>
<!--==============-->
<div id="app3">
</div>
<script type="x-template" id="x-template">
<h1> 引入script的形式</h1>
</script>
<script>
new Vue({
el:"#app1",
template:"<h1>通過直接書寫HTML的形式新增</h1>"
});
new Vue({
el:"#app2",
template:"#template"
});
new Vue({
el:"#app3",
template:"#x-template"
});
</script>
三、Vue 生命週期
3.1 介紹
函式名稱 | 說明 |
---|---|
beforeCreate | 元件例項剛被建立,元件屬性繫結前,如data屬性等 |
created | 元件例項建立完成,屬性繫結完成,但DOM未生成,$el 屬性不存在 |
beformMount | 模板編譯/掛載之前 |
mounted | 模板編譯/掛載之後 |
beforeUpdaate | 元件更新之前 |
updated | 元件更新之後 |
activated | for keep-alive,元件被啟用時呼叫 |
deactivated | for keep-alive,元件被移除時呼叫 |
beforeDestory | 元件銷燬前呼叫 |
destoyed | 元件銷燬後呼叫 |
3.2 使用場景
- beforeCreate 可以在此時加一些 loading 效果,在created時進行移除
- created 需要非同步請求資料的方法可以在此時執行,完成資料的初始化
- mounted 當需要操作 DOM 的時候執行,可以配合
$.nextTick
使用進行單一事件對資料的更新後更新 DOM - updated 當資料更新需要做統一業務處理的時候使用
四、事件
4.1 監聽事件
在 Vue
中可以用 v-on
指令監聽 DOM
事件,並在觸發時執行一些 JavaScript
程式碼:
<div id="app">
<!--為按鈕增加單擊事件,如果不需要傳參可以不寫方法括號-->
<button v-on:click="increment">自增</button>
<button v-on:click="decrement">自減</button>
<button v-on:click="add(2)">增加指定步長</button>
<!--可以將事件縮寫為@click-->
<button @click="subtract(2)">減少指定步長</button>
<br>
{{value}}
</div>
<script>
var app = new Vue({
el:"#app",
data:{
value:0
},
methods:{
increment:function(){
this.value++;
},
decrement:function(){
this.value--;
},
add:function(step){
this.value+=step;
},
subtract:function(step){
this.value -= step;
}
}
});
</script>
4.2 事件修飾符
修飾符是由點開頭的指令字尾來表示的:
.stop
.prevent
.capture
.self
.once
.passive
<!-- 阻止單擊事件繼續傳播 -->
<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>
<!-- 滾動事件的預設行為 (即滾動行為) 將會立即觸發 -->
<!-- 而不會等待 `onScroll` 完成 -->
<!-- 這其中包含 `event.preventDefault()` 的情況 -->
<div v-on:scroll.passive="onScroll">...</div>
4.3 按鍵修飾符
在監聽鍵盤事件時,我們經常需要檢查常見的鍵值。Vue
允許為 v-on
在監聽鍵盤事件時新增按鍵修飾符:
<!-- 只有在 `keyCode` 是 13 時呼叫 `vm.submit()` -->
<input v-on:keyup.13="submit">
記住所有的 keyCode 比較困難,所以 Vue 為最常用的按鍵提供了別名:
<input v-on:keyup.enter="submit">
<!-- 縮寫語法 -->
<input @keyup.enter="submit">
全部的按鍵別名:
- .enter
- .tab
- .delete (捕獲“刪除”和“退格”鍵)
- .esc
- .space
- .up
- .down
- .left
- .right
可以通過全域性 config.keyCodes 物件自定義按鍵修飾符別名:
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112
4.4 .exact 修飾符
.exact 修飾符允許你控制由精確的系統修飾符組合觸發的事件。
<!-- 即使 Alt 或 Shift 被一同按下時也會觸發 -->
<button @click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的時候才觸發 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 沒有任何系統修飾符被按下的時候才觸發 -->
<button @click.exact="onClick">A</button>
4.5 滑鼠按鈕修飾符
- .left
- .right
- .middle
這些修飾符會限制處理函式僅響應特定的滑鼠按鈕。
五、指令語法
5.1 v-if
根據表示式條件結果是否為真,來控制檢視是否渲染:
<div id="app">
<h1 v-if="value>0">數值大於零</h1>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
value:1
}
});
</script>
5.2 v-else-if
和 **v-if ** 搭配使用,用於另一個條件分支成立的情況:
<div id="app">
<h1 v-if="value>0">數值大於零</h1>
<h1 v-else-if="value<0">數值小於零</h1>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
value:-5
}
});
</script>
5.3 v-else
和 **v-if ** 搭配使用,表示其他未明確申明的條件分支:
<div id="app">
<h1 v-if="value>0">數值大於零</h1>
<h1 v-else-if="value<0">數值小於零</h1>
<h1 v-else>數值等於零</h1>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
value:0
}
});
</script>
5.4 v-show
v-show 和 v-if 一樣根據表示式結果來控制檢視的渲染。兩者的區別在於 v-if 是 DOM 元素的動態新增/刪除,而 v-show 是修改 display CSS 屬性,從效能比較上來看 v-show 更具優勢:
<div id="app">
<h1 v-show="value>0">數值大於零</h1>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
value:5
}
});
</script>
5.5 v-for
v-for 基於資料迴圈渲染檢視:
<div id="app">
<ul>
<!--:key 表示主鍵-->
<!--index 表示索引下標-->
<li v-for="(city,index) in citys" :key="city.id">
{{index}} -- 城市編碼:{{city.id}} -- 城市名稱:{{city.name}}
</li>
</ul>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
citys:[
{
id:10001,
name:"北京"
},
{
id:10002,
name:"上海"
},
{
id:10003,
name:"廣東"
},
{
id:10004,
name:"深圳"
},
{
id:10005,
name:"杭州"
}
]
}
});
</script>
5.6 v-bind
用於繫結資料和元素屬性,可以縮寫為 :屬性名
<div id="app">
<a v-bind:href="url">百度一下</a>
<br>
<a :href="url">百度一下</a>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
url:"http://www.baidu.com"
}
});
</script>
5.7 v-model
用於建立雙向資料繫結,負責監聽使用者的輸入事件以更新資料。
只有這些輸入元件可以使用:
* input
* select
* textarea
* components
修飾符:
* 如果想將資料同步時機從 Input 事件調整為change 事件之後,可以給 v-model 新增 lazy 修飾符;
* 如果想自動將使用者的輸入值轉為數值型別,可以給 v-model 新增 number 修飾符;
* 如果要自動過濾使用者輸入的首尾空白字元,可以給 v-model 新增 trim 修飾符;
<div id="app">
<button @click="resetValue">重置值</button>
<button @click="showValue">顯示當前值</button>
<br>
<!--增加number修飾符,表示輸入的是數值型-->
<input v-model.number="value"/>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
value:0
},
methods:{
resetValue:function(){
this.value=0;
},
showValue:function(){
alert(this.value);
}
}
});
</script>
5.8 v-text
文字內容繫結,等同於 {{ 資料欄位名稱}}
形式
<div id="app">
<h3 v-text="message"></h3>
<br>
{{message}}
</div>
<script>
var app = new Vue({
el:"#app",
data:{
message:"Hello Vue!"
}
});
</script>
5.9 v-html
原樣輸出 HTML 樣式文字:
<div id="app">
<div v-html="htmlValue"></div>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
htmlValue:"<h1> HelloVue!"
}
});
</script>
六、元件
6.1 介紹
元件就是可複用的 Vue
例項,它們與 new Vue
接收相同的選項,例如 data
、computed
、watch
、methods
以及生命週期鉤子等。僅有的例外是像 el
這樣根例項特有的選項。
注:元件中的 data 必須是函式。
這是因為如果像 Vue
例項那樣,傳入一個物件,由於 JS
中物件型別的變數實際上儲存的是物件的引用,所以當存在多個這樣的元件時,會共享資料,導致一個元件中資料的改變會引起其他元件資料的改變。
而使用一個返回物件的函式,每次使用元件都會建立一個新的物件,這樣就不會出現共享資料的問題來了。
6.2 建立元件
<div id="app">
<!--可以對註冊的元件進行任意的複用,每個元件都有各自的資料維護-->
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
<script>
<!--全域性註冊元件,詳情檢視元件註冊-->
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">你點選了 {{ count }} 次</button>'
});
var app = new Vue({
el:"#app"
});
</script>
6.3 父元件向子元件傳遞資料
通過 Prop(元件上自定義的 attribute) 向子元件傳遞資料
<div id="app">
<!--繫結title屬性,用來調整title屬性值-->
<input v-model="title"/>
<br>
<!--父元件傳遞屬性資料-->
<button-counter v-bind:title="title"></button-counter>
<!--父元件傳遞固定資料-->
<button-counter my-msg="父元件傳遞固定資料"></button-counter>
</div>
<script>
Vue.component('button-counter', {
// 屬性
props:["my-msg","title"],
template: '<div><h1>{{myMsg}}</h1><h1>{{title}}</h1></div>'
});
var app = new Vue({
el:"#app",
data:{
title:"父元件傳遞屬性資料"
}
});
</script>
6.4 子元件向父元件傳值
子元件主要通過 事件傳遞 的形式將資料給父元件:
<div id="app">
<!--將事件和父元件方法做繫結-->
<usernam-view @show-user-name="getInput"></usernam-view>
<br>
{{value}}
</div>
<script>
//申明子元件
Vue.component('usernam-view', {
data (){
return {
username:""
}
},
template: '<input v-model="username" @change="handleChange"></input>',
methods:{
handleChange : function(){
// 通過事件將值傳遞到父元件
this.$emit('show-user-name',this.username)
}
}
});
var app = new Vue({
el:"#app",
data:{
value:""
},
methods:{
getInput:function(input){
this.value = input;
},
}
});
</script>
6.5 父元件向子元件傳遞模板內容
當子元件的模板內容需要父元件傳遞時,可以通過在子元件中申明 slot 標籤,父元件將模板內容傳遞進去,這種方式叫做插槽:
<div id="app">
<component-view>
<h1>沒有名稱的 slot </h1>
<template slot="header">
<h1> slot 名稱為 header 的</h1>
</template>
<template slot="content">
<h1>slot 名稱為 content 的</h1>
</template>
</component-view>
</div>
<script>
Vue.component('component-view', {
data (){
return {
username:""
}
},
template: `
<div>
<strong>資訊</strong>
<slot></slot>
<slot name="header"></slot>
<slot name="content"></slot>
</div>
`
});
var app = new Vue({
el:"#app"
});
</script>
七、 元件註冊
元件註冊分為全域性註冊和區域性註冊。
7.1 全域性註冊
全域性註冊通過 Vue.component 來實現:
Vue.component('my-component-name', {
// ... 選項 ...
})
全域性註冊後的元件,可以在任何地方使用,與之相反的則是區域性註冊。
7.2 區域性註冊
區域性註冊的元件在其子元件中不可用:
<div id="app">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
<script>
<!--定義元件-->
var buttonCounter = {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">你點選了 {{ count }} 次</button>',
}
var app = new Vue({
el:"#app",
components:{
"button-counter": buttonCounter
}
});
</script>
八、ajax 請求
Vue.js 2.0 版本推薦使用 axios 來完成 ajax 請求。
8.1 介紹
Axios 是一個基於 Promise 的 HTTP 庫,可以用在瀏覽器和 node.js 中。
Github開源地址: https://github.com/axios/axios
請求配置項:
{
// `url` 是用於請求的伺服器 URL
url: "/user",
// `method` 是建立請求時使用的方法
method: "get", // 預設是 get
// `baseURL` 將自動加在 `url` 前面,除非 `url` 是一個絕對 URL。
// 它可以通過設定一個 `baseURL` 便於為 axios 例項的方法傳遞相對 URL
baseURL: "https://some-domain.com/api/",
// `transformRequest` 允許在向伺服器傳送前,修改請求資料
// 只能用在 "PUT", "POST" 和 "PATCH" 這幾個請求方法
// 後面陣列中的函式必須返回一個字串,或 ArrayBuffer,或 Stream
transformRequest: [function (data) {
// 對 data 進行任意轉換處理
return data;
}],
// `transformResponse` 在傳遞給 then/catch 前,允許修改響應資料
transformResponse: [function (data) {
// 對 data 進行任意轉換處理
return data;
}],
// `headers` 是即將被髮送的自定義請求頭
headers: {"X-Requested-With": "XMLHttpRequest"},
// `params` 是即將與請求一起傳送的 URL 引數
// 必須是一個無格式物件(plain object)或 URLSearchParams 物件
params: {
ID: 12345
},
// `paramsSerializer` 是一個負責 `params` 序列化的函式
// (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
paramsSerializer: function(params) {
return Qs.stringify(params, {arrayFormat: "brackets"})
},
// `data` 是作為請求主體被髮送的資料
// 只適用於這些請求方法 "PUT", "POST", 和 "PATCH"
// 在沒有設定 `transformRequest` 時,必須是以下型別之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 瀏覽器專屬:FormData, File, Blob
// - Node 專屬: Stream
data: {
firstName: "Fred"
},
// `timeout` 指定請求超時的毫秒數(0 表示無超時時間)
// 如果請求花費了超過 `timeout` 的時間,請求將被中斷
timeout: 1000,
// `withCredentials` 表示跨域請求時是否需要使用憑證
withCredentials: false, // 預設的
// `adapter` 允許自定義處理請求,以使測試更輕鬆
// 返回一個 promise 並應用一個有效的響應 (查閱 [response docs](#response-api)).
adapter: function (config) {
/* ... */
},
// `auth` 表示應該使用 HTTP 基礎驗證,並提供憑據
// 這將設定一個 `Authorization` 頭,覆寫掉現有的任意使用 `headers` 設定的自定義 `Authorization`頭
auth: {
username: "janedoe",
password: "s00pers3cret"
},
// `responseType` 表示伺服器響應的資料型別,可以是 "arraybuffer", "blob", "document", "json", "text", "stream"
responseType: "json", // 預設的
// `xsrfCookieName` 是用作 xsrf token 的值的cookie的名稱
xsrfCookieName: "XSRF-TOKEN", // default
// `xsrfHeaderName` 是承載 xsrf token 的值的 HTTP 頭的名稱
xsrfHeaderName: "X-XSRF-TOKEN", // 預設的
// `onUploadProgress` 允許為上傳處理進度事件
onUploadProgress: function (progressEvent) {
// 對原生進度事件的處理
},
// `onDownloadProgress` 允許為下載處理進度事件
onDownloadProgress: function (progressEvent) {
// 對原生進度事件的處理
},
// `maxContentLength` 定義允許的響應內容的最大尺寸
maxContentLength: 2000,
// `validateStatus` 定義對於給定的HTTP 響應狀態碼是 resolve 或 reject promise 。如果 `validateStatus` 返回 `true` (或者設定為 `null` 或 `undefined`),promise 將被 resolve; 否則,promise 將被 rejecte
validateStatus: function (status) {
return status >= 200 && status < 300; // 預設的
},
// `maxRedirects` 定義在 node.js 中 follow 的最大重定向數目
// 如果設定為0,將不會 follow 任何重定向
maxRedirects: 5, // 預設的
// `httpAgent` 和 `httpsAgent` 分別在 node.js 中用於定義在執行 http 和 https 時使用的自定義代理。允許像這樣配置選項:
// `keepAlive` 預設沒有啟用
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),
// "proxy" 定義代理伺服器的主機名稱和埠
// `auth` 表示 HTTP 基礎驗證應當用於連線代理,並提供憑據
// 這將會設定一個 `Proxy-Authorization` 頭,覆寫掉已有的通過使用 `header` 設定的自定義 `Proxy-Authorization` 頭。
proxy: {
host: "127.0.0.1",
port: 9000,
auth: : {
username: "mikeymike",
password: "rapunz3l"
}
},
// `cancelToken` 指定用於取消請求的 cancel token
// (檢視後面的 Cancellation 這節瞭解更多)
cancelToken: new CancelToken(function (cancel) {
})
}
響應結構:
{
// `data` 由伺服器提供的響應
data: {},
// `status` HTTP 狀態碼
status: 200,
// `statusText` 來自伺服器響應的 HTTP 狀態資訊
statusText: "OK",
// `headers` 伺服器響應的頭
headers: {},
// `config` 是為請求提供的配置資訊
config: {}
}
8.2 安裝
使用 cdn:
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.0/axios.js"></script>
或
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.0/axios.min.js"></script>
使用 npm:
# 針對 vue-cli 建立的專案,需要 CMD 進入專案目錄下執行
npm install axios
8.3 GET 請求
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>axios</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.0/axios.js"></script>
<body>
<div id="app">
<button @click="loadUserInfo">獲取使用者資訊</button>
</div>
<script>
var app = new Vue({
el:"#app",
methods:{
loadUserInfo:function(){
axios
.get('http://localhost:8080/api/userInfo/123')
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.log(error);
})
},
}
});
</script>
</body>
</html>
8.4 POST 請求
<div id="app">
<button @click="createUser">建立使用者</button>
</div>
<script>
var app = new Vue({
el:"#app",
methods:{
createUser:function(){
axios
.post('http://localhost:8080/api/create',{
userId:"1234",
userName:"張三",
age:19
})
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.log(error);
})
},
}
});
</script>