介紹 Vue.js 中文文檔地址:https://cn.vuejs.org/guide/introduction.html#what-is-vue Vue.js 是什麼 Vue (讀音 /vjuː/,類似於 view) 是一套用於構建用戶界面的漸進式框架。與其它大型框架不同的是,Vue 被設計為可以 ...
介紹
- Vue.js 中文文檔地址:https://cn.vuejs.org/guide/introduction.html#what-is-vue
Vue.js 是什麼
- Vue (讀音 /vjuː/,類似於 view) 是一套用於構建用戶界面的漸進式框架。與其它大型框架不同的是,Vue 被設計為可以自底向上逐層應用。Vue 的核心庫只關註視圖層,不僅易於上手,還便於與第三方庫或既有項目整合。另一方面,當與現代化的工具鏈以及各種支持類庫結合使用時,Vue 也完全能夠為複雜的單頁應用提供驅動。
Vue.js 優點
前端三要素
- HTML + CSS + JavaScript
CSS 預處理器
JavaScript 框架
UI 框架
JavaScript 構建工具
常用的 Vue UI 組件庫
vue-element-admin
- 簡述:vue-element-admin 是一個後臺前端解決方案,它基於 vue 和 element-ui實現。它使用了最新的前端技術棧,內置了 i18 國際化解決方案,動態路由,許可權驗證,提煉了典型的業務模型,提供了豐富的功能組件,它可以幫助你快速搭建企業級中後臺產品原型。相信不管你的需求是什麼,本項目都能幫助到你。
- 地址:https://panjiachen.github.io/vue-element-admin-site/zh/
MVVM 模式
為什麼使用 MVVM 模式
第一個 Vue 程式
IDEA 安裝插件
使用 IDEA 工具開發,可安裝 Vue.js 插件!
在 IDEA 中安裝插件後,可快速構建 vue 文件:
PS:若安裝插件後也沒有出現快速構建 vue 文件的選項,可先手動創建 .vue 結尾的空文件,再次新建時,則可成功顯示!
CDN 簡述
-
智能 dns 讓用戶可以訪問同線路最近的伺服器
-
cdn 的緩存機制可以加快訪問速度,也可以緩解源站伺服器壓力(因為根本不會去訪問源站)
-
cdn 讓大規模的用戶請求架構變得簡單
-
cdn 性價比高,同帶寬需求下 cdn 服務比增加帶寬划算
作用:儘可能避開互聯網上有可能影響數據傳輸速度和穩定性的瓶頸和環節,使內容傳輸得更快、更穩定。
安裝
可使用多種方式進行安裝,如直接下載對應類庫、使用 CDN 引入、使用 NPM 安裝等...
此處使用 CDN:
- 壓縮版:
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
- 完整版:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
示例代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>first vue</title>
</head>
<body>
<!--view層:模板-->
<div id="app">
<h2>{{message}}</h2>
</div>
<!--使用CDN方式導入Vue.js-->
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
//Model: 數據
data: {
message: "hello,vue!"
}
});
</script>
</body>
</html>
相關指令
v-bind
-
作用:與指定屬性進行綁定
-
v-bind:
可簡寫為:
-
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <!--view層:模板--> <div id="app"> <h2>{{message}}</h2> <span v-bind:title="message"> 滑鼠懸浮幾秒查看動態綁定的提示信息! </span> <!-- v-bind可簡寫 --> <input type='text' :value="str" /> </div> <!--使用CDN方式導入Vue.js--> <script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script> <script> var vm = new Vue({ el: "#app", //Model: 數據 data: { message: "hello,vue!", str: "test str" } }); </script> </body> </html>
v-if、v-else-if、v-else
-
作用:判斷
-
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test3</title> </head> <body> <div id="app"> <h1 v-if="ok">yes</h1> <h1 v-else>no</h1> <span v-if="type==='A'">A</span> <span v-else-if="type==='B'">B</span> <span v-else>D</span> </div> <!-- 導入vue.js --> <script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script> <script> var vm = new Vue({ el: "#app", data: { ok: true, type: 'A' } }); </script> </body> </html>
v-show
- 作用:判斷
- 說明:從功能上講,
v-show
和v-if
作用是相同的,主要是他們的渲染過程有區別。
除了
v-if
,還有一個可以按條件顯示一個元素的指令是v-show
。其用法基本一樣:<h1 v-show="ok">Hello!</h1>
不同之處在於
v-show
會在 DOM 渲染中保留該元素;v-show
僅切換了該元素上名為display
的 CSS 屬性。
v-show
不支持在<template>
元素上使用,也不能和v-else
搭配使用。
v-if
vs.v-show
v-if
是“真實的”按條件渲染,因為它確保了在切換時,條件區塊內的事件監聽器和子組件都會被銷毀與重建。
v-if
也是惰性的:如果在初次渲染時條件值為 false,則不會做任何事。條件區塊只有當條件首次變為 true 時才被渲染。相比之下,
v-show
簡單許多,元素無論初始條件如何,始終會被渲染,只有 CSSdisplay
屬性會被切換。總的來說,
v-if
有更高的切換開銷,而v-show
有更高的初始渲染開銷。因此,如果需要頻繁切換,則使用v-show
較好;如果在運行時綁定條件很少改變,則v-if
會更合適。
v-for
-
作用:迴圈
-
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test4</title> </head> <body> <div id="app"> <ul>編程語言 <li v-for="item in items"> {{item.message}} </li> </ul> <ol>編程語言(顯示下標) <li v-for="(item, index) in items"> {{item.message}} --> {{index}} </li> </ol> </div> <!-- 導入vue.js --> <script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script> <script> var vm = new Vue({ el: "#app", data: { items: [ {message: "java"}, {message: "python"}, {message: "go"} ] } }); </script> </body> </html>
v-on
-
作用:事件監聽
-
v-on:click
可簡寫為@click
-
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test5</title> </head> <body> <div id="app"> <p>{{message}}</p> <button v-on:click="reverseMessage">反轉消息</button> </div> <!-- 導入vue.js --> <script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script> <script> var vm = new Vue({ el: "#app", data: { message: "Hello Vue.js!"}, methods: { reverseMessage: function () { this.message = this.message.split('').reverse().join(''); } } }); </script> </body> </html>
v-model
-
作用:實現數據的雙向綁定
-
說明:使用該指令可在
<input>、<textarea>、<select>
等元素上創建雙向數據綁定,會根據控制項類型自動選取正確方法來更新元素。它負責監聽用戶的輸入事件以更新數據,並對一些極端場景進行一些特殊處理。 -
註意:
v-model
會忽略所有表單元素的 value、checked、selected 特性的初始值而總是將 Vue 實例的數據作為數據來源,所以開發者應該通過 JavaScript 在組件的 data 選項中聲明初始值! -
v-model 又稱表單標簽,主要作用就是實現表單標簽的的雙向綁定;
它只能使用在表單輸入標簽,因為需要通過表單輸入標簽輸入的內容,來改變其他地方的數據;
v-model:value
可以簡寫為v-model
,需要明確它預設就是綁定的 value 屬性。 -
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test6</title> </head> <body> <div id="app"> 單行文本: <input type="text" v-model="message"> {{message}} <br><br> 文本域: <textarea v-model="texts"></textarea> {{texts}} <br><br> 單選按鈕:<br> 性別: <input type="radio" name="sex" value="男" v-model="gender">男 <input type="radio" name="sex" value="女" v-model="gender">女 <br> <span>選中了【{{gender}}】</span> <br><br> 下拉框: <select v-model="selected"> <option value="" disabled>--請選擇--</option> <option>A</option> <option>B</option> <option>C</option> </select> <span>value:{{selected}}</span> </div> <!-- 導入vue.js --> <script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script> <script> var vm = new Vue({ el: "#app", data: { selected: '', message: "123", texts: '', gender: '' } }); </script> </body> </html>
vue 實例
每個使用 vue 進行數據渲染的網頁文檔都需要創建一個 Vue 實例——ViewModel
Vue 實例的生命周期
vue 實例的生命周期:vue 實例從創建到銷毀的過程
- 創建 vue 實例:初始化 data,載入 el
- 數據掛載:將 vue 實例 data 中數據渲染到網頁 HTML 標簽
- 重新渲染:當 vue 的 data 數據發生變化,會重新渲染到 HTML 標簽
- 銷毀實例
鉤子函數
為便於開發者在 vue 實例生命周期不同階段進行特定的操作,vue 在生命周期四個階段的前後分別提供了一個函數,這個函數無須開發者調用,當 vue 實例到達生命周期的指定階段,會自動進行相關函數的調用,這些函數稱為鉤子函數。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
</head>
<body>
<div id="container">
<label v-once>{{str}}</label><br />
<label>{{str}}</label><br />
<input type="text" v-model="str" />
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#container",
data: {
str: "初始數據"
},
beforeCreate: function() {
//1.data初始化之前執,不能操作data
console.log("beforeCreate------->1");
},
created: function() {
//2.data初始化之後執行,模板載入之前,可以修改/獲取data中的值
console.log(this.str);
console.log("created------->2");
//this.str = "data初始化之後執行";
},
beforeMount: function() {
//3.模板載入之後,數據初始渲染(掛載)之前,可以修改/獲取data中的值
//this.str = "數據初始渲染(掛載)之前執行";
console.log("beforeMount------->3");
},
mounted: function() {
//4.數據初始渲染(掛載)之後,可以對data中的變數進行修改,但是不會影響v-once的渲染
//this.str = "數據初始渲染(掛載)之後執行";
console.log("mounted------->4");
},
beforeUpdate: function() {
//5.數據渲染之後,當data中的數據變化觸發重新渲染,渲染之前執行此函數
// data數據被修改之後,重新渲染到html之前
console.log("-----" + this.str);
this.str = "數據被修改,重新被渲染到html之前";
console.log("beforeUpdate------->5");
},
updated: function() {
//6.data數據被修改之後,重新渲染到html之後
//this.str = "數據被修改,重新渲染都html後";
console.log("updated------->6");
},
beforeDestroy: function() {
//7.實例銷毀之前
console.log("beforeDestroy------->7");
},
destroyed: function() {
//8.實例銷毀之後
console.log("destroyed------->8");
}
});
</script>
</body>
</html>
計算屬性
計算屬性的重點突出在屬性兩個字上(屬性是名詞),首先它是個屬性,其次,這個屬性有計算的能力(計算是動詞),這裡的計算就是個函數;簡單點說,他就是一個能夠將計算結果緩存起來的屬性(將行為轉化成了靜態的屬性),僅此而已;也可以將其想象成緩存!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test9</title>
<!--引入Vue.js-->
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
</head>
<body>
<div id="vue">
<!--註意:一個是方法,一個是屬性!-->
<p>調用當前時間的方法:{{currentTime1()}}</p> <!--方法調用需要帶括弧-->
<p>當前時間的計算屬性:{{currentTime2}}</p> <!--屬性調用不能帶括弧-->
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#vue',
data: {message: 'Hello Vue.js!'},
// 註意:methods 和 computed 里的東西不能重名!
methods: { //在此可定義方法,調用方法需要帶()
//currentTime1:這是一個方法!
currentTime1: function () {
return Date.now();
}
},
computed: { //在此可定義計算屬性,調用屬性不需要帶()
//currentTime2:這是一個屬性,不是方法!
currentTime2: function () {
this.message; //作用:通過改變該值,觀察currentTime2屬性值的變化
return Date.now();
}
}
});
</script>
</body>
</html>
測試結果:(F12 --》控制台)
vm.currentTime1()
1656988519767
vm.currentTime1()
1656988521888
vm.currentTime1()
1656988524916
結論:調用方法,每次都需要重新計算
vm.currentTime2()
Uncaught TypeError: vm.currentTime2 is not a function
<anonymous> debugger eval code:1
debugger eval code:1:4
結論:計算屬性是屬性,調用時不能帶括弧
vm.currentTime2
1656988393581
vm.currentTime2
1656988393581
vm.currentTime2
1656988393581
結論:計算屬性將不經常變化的計算結果緩存了起來,只有發生變化的時候才會重新計算
vm.message = 'new data';
"new data"
vm.currentTime2
1656988775105
vm.currentTime2
1656988775105
結論:計算屬性中的值被改變時,計算結果重新計算,並重新進行緩存
說明:如果計算屬性中的值發生變化時,則緩存就會刷新,可在控制台使用vm.message = 'new data';
,改變下數據的值,再次測試並觀察效果!
結論:調用方法時,每次都需要重新計算,既然有計算過程,則必定會產生系統開銷,如果這個結果是不經常變化的,則可以考慮將這個結果緩存起來,採用計算屬性就可以很方便的做到這一點!計算屬性的主要特性就是為了將不經常變化的計算結果進行緩存,以節約系統開銷。
偵聽器
偵聽器,就是 data 中屬性的監聽器,當 data 中的屬性值發⽣變化就會觸發偵聽器函數的執⾏。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
</head>
<body>
<div id="container">
<input type="text" v-model="str1" /><br />
<input type="text" v-model="str2" /><br />
{{str3}}
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#container",
data: {
str1: "江蘇",
str2: "蘇州",
str3: "江蘇蘇州"
},
watch: {
str1: function() {
this.str3 = this.str1 + this.str2;
},
str2: function() {
this.str3 = this.str1 + this.str2;
}
}
});
</script>
</body>
</html>
類與樣式綁定
我們可以使⽤ mustache 語法將 vue 中 data 的數據綁定到 HTML 標簽及標簽的屬性,如何將 data 中的值綁定到標簽的 class 及 style 屬性呢?下麵就是需要介紹的類與樣式綁定—— class 與 style 綁定。
class 綁定
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
<style type="text/css">
.mystyle1 {
width: 200px;
height: 100px;
background: orange;
}
.mystyle3 {
width: 200px;
height: 100px;
background: black;
}
.my-style2 {
border-radius: 10px;
}
</style>
</head>
<body>
<div id="container">
<!--如果b1為true就載入 mystyle1;如果b2為true,則載入my-style2-->
<!-- 註意:如果樣式名中有特殊字元如橫杠,需要添加單引號 -->
<div :class="{mystyle1:b1,'my-style2':b2}"></div>
<!--為class屬性載入多個樣式名 -->
<div :class="[chooseStyle1,chooseStyle2]"></div>
<!--如果b3為true,則class='mystyle3'; 否則class='mystyle1'
如果在三目運算中使用樣式名則需加單引號,不加單引號則表示從data變數中獲取樣式名-->
<div :class="[b3 ? 'mystyle3' : 'mystyle1']"></div>
<div :class="[b3 ? chooseStyle3 : chooseStyle1]"></div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#container",
data: {
b1: true,
b2: true,
b3: false,
chooseStyle1: "mystyle1",
chooseStyle2: "my-style2",
chooseStyle3: "mystyle3"
}
});
</script>
</body>
</html>
style 綁定
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
</head>
<body>
<div id="container">
<!--當使用v-bind綁定內聯樣式時:
1. 使用{}定義style樣式,才能獲取data中的值,{}要遵循JSON格式
2. {}中不再使用style樣式屬性名“font-size”,要使用對應的js屬性名
border-style-width ---》 borderStyleWidth(橫杠連接變駝峰形式)
-->
<div v-bind:style="{color: colorname,fontSize: fontsize+'px'}">vue之style綁定</div>
<!--我們可以直接為style屬性綁定一個data中定義好的內聯樣式的字元串-->
<div v-bind:style="mystyle1">vue之style綁定</div>
<!--我們可以直接為style屬性綁定一個data中定義好的內聯樣式的對象-->
<div v-bind:style="mystyle2">vue之style綁定</div>
<!--可以在同一個style上通過數組引用多個內聯樣式的對象-->
<div v-bind:style="[mystyle2,mystyle3]">vue之style綁定</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#container",
data: {
colorname: "green",
fontsize: 30,
mystyle1: "color:orange;font-size:45px",
mystyle2: {
color: "blue",
fontSize: "40px"
},
mystyle3: {
textShadow: "orange 3px 3px 5px"
}
}
});
</script>
</body>
</html>
事件處理
事件綁定傳值的三種方式
在使⽤ vue 進⾏數據渲染時,如果使⽤原⽣ js 事件綁定(例如 onclick ),則需要獲取 vue 實例中的數據,並傳參,而且需要通過拼接來完成。
vue 提供了 v-on 指令⽤於綁定各種事件(
v-on:click
),簡化了從 vue 取值的過程,但是觸發的⽅法需要定義在 vue 實例的 methods 中,如下:<button type="button" v-on:click="doDelete(s.stuNum,s.stuName)">刪除</button> <script type="text/javascript"> var vm = new Vue({ el:"#container", data:{}, methods:{ doDelete:function(snum,sname){ console.log("----delete:"+snum+" "+sname) } } }); </script>
PS:
v-on:click
可以縮寫為@click
1. 使用 JS 函數傳值(不建議)
<button type="button" v-on:click="doDelete(s.stuNum,s.stuName)">刪除</button>
<script>
var vm = new Vue({
el:"#container",
data:{};
methods:{
doDelete:function(snum,sname){
console.log("----delete:"+snum+" "+sname)
}
}
});
</script>
2. 使⽤ dataset 對象傳值(推薦)
說明:
推薦直接調用方法;
需要傳遞的參數使用
:data-xxx="數據"
格式進行傳遞;參數獲取通過方法定義時添加的 event 參數中獲取;
<button type="button" @click="doUpdate" :data-snum="s.stuNum" :data-sname="s.stuName" :data-simg="s.stuImg">修改</button>
<script>
var vm = new Vue({
el:"#container",
data:{};
methods:{
doUpdate:function(event){
//如果v-on綁定的js函數沒有參數,調⽤的時候可以省略(),同時可以給
//js函數⼀個event參數(事件對象)
// 1. event 表示觸發當前函數的事件
// 2. event.srcElement 表示發⽣事件的元素---修改按鈕
// 3. event.srcElement.dataset 表示按鈕上綁定的數據集(data-開頭的屬性)
console.log("-----update")
var stu = event.srcElement.dataset;
}
}
});
</script>
3. 混合使⽤傳值
混合傳值,方法參數中事件參數 event 需要註意,必須使用
$event
。
<button type="button" v-on:click="doDelete(s.stuNum,s.stuName,$event)":data-simg="s.stuImg">刪除</button>
<script>
var vm = new Vue({
el:"#container",
data:{};
methods:{
doDelete:function(snum,sname,event){
console.log("----delete:"+snum+" "+sname)
console.log(event.srcElement.dataset);
}
}
});
</script>
事件修飾符
當使⽤ v-on 進⾏事件綁定的時候,可以添加特定尾碼,設置事件觸發的特性。
下麵介紹常用的幾個事件修飾符,更多參考官網:點擊查看
.prevent
:消除元素的預設事件.stop
:阻⽌事件冒泡(阻⽌⼦標簽向上冒泡).self
:設置只能⾃⼰觸發事件(⼦標簽不能觸發).once
:限定事件只觸發⼀次
使用語法示例:
<button type="submit" @click.prevent="事件函數">測試</button>
.prevent
作用:消除元素的預設事件
示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
</head>
<body>
<div id="container">
<form action="https://www.baidu.com">
<button type="submit" class="btn btn-success btn-xs" @click.prevent="test">測試</button>
</form>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#container",
data: {},
methods: {
test: function() {
console.log("---test");
}
}
});
</script>
</body>
</html>
.stop
和 .self
作用:
.stop
:阻⽌事件冒泡(阻⽌⼦標簽向上冒泡).self
:設置只能⾃⼰觸發事件(⼦標簽不能觸發)
示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
</head>
<body>
<div id="container">
<div style="width: 200px; height: 200px; background: red;" @click.self="method1">
<div style="width: 150px; height: 150px; background: green;" @click="method2">
<button type="button" @click.stop="method3">測試</button>
</div>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#container",
data: {},
methods: {
method1: function() {
alert("1");
},
method2: function() {
alert("2");
},
method3: function() {
alert("3");
},
}
});
</script>
</body>
</html>
.once
作用:限定事件只觸發⼀次
示例:略
按鍵修飾符
按鍵修飾符就是針對鍵盤事件的修飾符,限定哪個按鍵會觸發事件。
示例說明:對於下列文本框,輸入文字後,按下回車鍵並彈起時,會觸發事件,調用 method4 方法。
<input type="text" @keyup.enter="method4"/>
針對鍵盤操作的動作,除了 @keyup
還有:@keydown
和 @keypress
Vue 為一些常用的按鍵提供了別名:
.enter
.tab
.delete
(捕獲“Delete”和“Backspace”兩個按鍵).esc
.space
.up
.down
.left
.right
除了以上 vue 提供按鈕的別名之外,我們還可以為按鍵⾃定義別名。
示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
</head>
<body>
<div id="container">
<!--2.使用定義的按鍵別名aaa作為修飾符-->
<input type="text" @keyup.aaa="method4" />
</div>
<script type="text/javascript">
//1.為按鍵J定於別名為 aaa
Vue.config.keyCodes.aaa = 74;
var vm = new Vue({
el: "#container",
data: {},
methods: {
method4: function() {
alert("4");
}
}
});
</script>
</body>
</html>
系統修飾符
組合鍵
可使用以下系統按鍵修飾符來觸發滑鼠或鍵盤事件監聽器,只有當按鍵被按下時才會觸發:
.ctrl
.alt
.shift
.meta
:windows 鍵
示例:Ctrl + J 觸發事件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
</head>
<body>
<div id="container">
<input type="text" @keyup.ctrl.j="method4" />
</div>
<script type="text/javascript">
Vue.config.keyCodes.j = 74;
var vm = new Vue({
el: "#container",
data: {},
methods: {
method4: function() {
alert("4");
}
}
});
</script>
</body>
</html>
表單輸入綁定
表單輸⼊綁定,即雙向綁定,就是能夠將 vue 實例的 data 數據渲染到表單輸⼊視圖(input\textarea\select 等),也能夠將輸⼊視圖的數據同步更新到 vue 實例的 data 中。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
</head>
<body>
<div id="container">
<!--文本輸入框、密碼輸入框-->
<input type="text" v-model="text" /><br />
<input type="password" v-model="pwd" /><br />
<!--單選按鈕-->
<input type="radio" v-model="opt1" value="A" />A 3
<input type="radio" v-model="opt1" value="B" />B 4
<input type="radio" v-model="opt1" value="C" />C 5
<input type="radio" v-model="opt1" value="D" />D 6 <br />
<!--覆選框,綁定的是一個數組-->
<input type="checkbox" v-model="opt2" value="籃球" />籃球 <br />
<input type="checkbox" v-model="opt2" value="足球" />足球 <br />
<input type="checkbox" v-model="opt2" value="羽毛球" />羽毛球 <br />
<input type="checkbox" v-model="opt2" value="乒乓球" />乒乓球 <br />
<!--下拉菜單select:綁定一個字元串-->
<select v-model="city">
<option value="BJ">北京</option>
<option value="SH">上海</option>
<option value="GZ">廣州</option>
<option value="SZ">深圳</option>
</select>
<br />
<!--下拉菜單select:如果有multiple表示可多選,需要綁定一個數組-->
<select v-model="cities" multiple>
<option value="BJ">北京</option>
<option value="SH">上海</option>
<option value="GZ">廣州</option>
<option value="SZ">深圳</option>
</select>
<br />
<button type="button" @click="test">測試</button>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#container",
data: {
text: "aaa",
pwd: "111111",
opt1: "C",
opt2: ["籃球", "羽毛球"],
city: "SZ",
cities: ["BJ", "SZ"]
},
methods: {
test: function() {
alert(vm.cities);
}
}
});
</script>
</body>
</html>
組件化應用構建
組件系統是 Vue 的另一個重要概念,因為它是一種抽象,允許我們使用小型、獨立和通常可復用的組件構建大型應用。仔細想想,幾乎任意類型的應用界面都可以抽象為一個組件樹:
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test6</title>
</head>
<body>
<div id="app">
<ol>
<!--構建一個組件模板:創建一個 todo-item 組件的實例,使用自定義的Vue組件,遍曆數據,將數據傳遞給綁定的指定屬性-->
<todo-item v-for="item in todoList" v-bind:todo="item"></todo-item>
</ol>
</div>
<!-- 導入vue.js -->
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
<script>
//註冊組件:定義名為 todo-item 的新組件
Vue.component("todo-item", {
props: ['todo'],
template: '<li>{{todo.text}}</li>'
});
var vm = new Vue({
el: "#app",
data: {
todoList: [
{id: 0, text: "學英語"},
{id: 1, text: "學技術"},
{id: 2, text: "學做飯"}
]
}
});
</script>
</body>
</html>
組件
組件介紹及示例
組件,就是將通⽤的 HTML 模塊進⾏封裝——可復⽤
組件註冊
將通⽤的 HTML 模塊封裝註冊到 vue 中
Vue.component("header-bar",{
});
組件引用
- 定義組件需要依賴 vue.js,在引⽤⾃定義組件的 js ⽂件之前要先引⽤ vue.js
- 組件的引⽤必須在 vue 實例 el 指定的容器中
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="container">
<header-bar></header-bar>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript" src="js/my-components.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: "#container",
});
</script>
</body>
</html>
組件註冊
自定義組件的結構
data
定義組件的模板渲染的數據template
組件的 HTML 模塊(HTML標簽\css樣式)methods
定義組件中的標簽事件綁定的 JS 函數
Vue.component("header-bar", {
data: function() {
//組件中的data是通過函數返回的對象
return {
title: "Java電商平臺"
};
},
template: `<div style="width: 100%; height: 80px; background: lightyellow;">
<table width="100%">
<tr>
<td width="200" align="right" valign="middle">
<img src="img/logo.png" height="80">
</td>
<td>
<label style="color: deepskyblue;font-size:32px; font-family: 華文行楷; margin-left: 30px;">
{{title}}
</label>
</td>
<td>
<button @click="test">組件中的按鈕</button>
</td>
</tr>
</table>
</div>`,
methods: {
test: function() {
alert("組件中定義的函數");
}
}
});
組件的封裝
- 將模版中的 css 樣式提出取來,單獨定義到 css ⽂件存儲在 css ⽬錄
- 將模版中的圖⽚存在 img ⽬錄
- 將定義組件的 js ⽂件和 vue 的⽂件存放到 js ⽬錄
組件的復用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" href="css/my-components.css" />
</head>
<body>
<div id="container">
<header-bar></header-bar>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript" src="js/my-components.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: "#container"
});
</script>
</body>
</html>
組件通信
vue 實例本身就是⼀個組件(模板就是 el 指定容器,data 就是組件數據,methods 就是組件的事件函數)
在 vue 實例指定的 el 容器中引⽤的組件稱為⼦組件 ,當前 vue 實例就是⽗組件
父傳子
vue 實例引⽤組件的時候,傳遞數據到引⽤的組件中
子傳父
通過⼦組件的按鈕“調⽤”⽗組件的函數,通過函數傳值
組件插槽
當我們⾃定義 vue 組件時,允許組件中的部分內容在調⽤組件時進⾏定義——插槽
插槽的使用
在⾃定義組件時通過 slot
標簽在組件的模版中定義插槽
Vue.component("header-bar", {
data: function() {
//組件中的data是通過函數返回的對象
return {
str2: "子組件中的數據"
};
},
template: '<div class="divStyle">
<table class="tableStyle">
<tr>
<td width="200" align="right" valign="middle">
<img src="img/logo.png" class="logoImg">
</td>
<td>
<label class="titleStyle">
{{title}}
</label>
</td>
<td>
<slot></slot>
</td>
<td>
<button @click="childMethod">子組件中的按鈕</button>
</td>
</tr>
</table>
</div>',
props: ["title"],
methods: {
childMethod: function() {
this.$emit("my-event", this.str2);
}
}
});
在⽗組件中調⽤此組件時,指定插槽填充的模版
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="css/bootstrap.css" />
<link rel="stylesheet" href="css/my-components.css" />
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<div id="container">
<header-bar :title="sss">
<!--組件標簽包含的HTML預設為填充到插槽的模版-->
<input /><button>搜索</button>
</header-bar>
</div>
<script type="text/javascript" src="js/my-components.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: "#container",
data: {
sss: "自定義標題"
}
});
</script>
</body>
</html>
具名插槽
當組件中的插槽數量 > 1 時,需要給組件中的 slot 標簽添加 name 屬性指定插槽的名字
定義組件
Vue.component("page-frame", {
template: '<div>
<div id="header" style="width:100%;
height:100px;background:pink">
<slot name="s1"></slot>
</div>
<div style="width:100%; height:580px">
<slot name="s2"></slot>
</div>
<div id="footer" style="width:100%;
height:40px;background:lightgray">{{cr}}</div>
</div>',
props: ["title", "cr"]
});
引用組件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="container">
<page-frame title="標題" cr="vue學習">
<!--定義一個模版,填充到組件的name=s1的 插槽-->
<template slot="s1">
<input type="text" placeholder="歌曲名、歌手" />
<button type="button" @click="doSearch">搜索</button>
</template>
<!--定義一個模版,填充到組件的name=s2的 插槽-->
<template slot="s2">
<table class="table table-bordered table-condensed">
<tr>
<th>序號</th>
<th>歌曲ID</th>
<th>歌曲名</th>
<th>歌手</th>
<th>專輯</th>
<th>時長</th>
<th>操作</th>
</tr>
</table>
</template>
</page-frame>
</div>
</body>
</html>
插槽作用域
定義組件時,將組件中的數據綁定到 slot 標簽
Vue.component("page-frame", {
template: '<div>
<div id="header" style="width:100%;height:100px;background:pink">
<slot name="s1"></slot>
</div>
<div style="width:100%; height:580px">
<slot name="s2" v-bind:musics="songs"></slot>
</div>
<div id="footer" style="width:100%;height:40px;background:lightgray">{{cr}}</div>
</div>',
props: ["title", "cr"],
data: function() {
return {
songs: [{}, {}]
};
}
});
引⽤組件時,在填充插槽的模版上使⽤ slot-scope
屬性獲取插槽綁定的值
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="container">
<page-frame title="標題" cr="vue學習">
<template slot="s1">
<input type="text" placeholder="歌曲名、歌手" />
<button type="button" @click="doSearch">搜索</button>
</template>
<!--在使用模版填充組件插槽時,可以使用slot-scope屬性獲取組件插槽綁定的數據的集合 -->
<template slot="s2" slot-scope="res">
<table class="table table-bordered table-condensed">
<tr>
<th>序號</th>
<th>歌曲ID</th>
<th>歌曲名</th>
<th>歌手</th>
<th>專輯</th>
<th>時長</th>
<th>操作</th>
</tr>
<tr v-for="song,index in res.musics">
<!--遍歷省略-->
</tr>
</table>
</template>
</page-frame>
</div>
</body>
</html>
插槽 slot 補充
內容分發:在Vue.js
中我們使用<slot>
元素作為承載分發內容的出口,作者稱其為插槽,可應用在組合組件的場景中。
測試:如準備一個待辦事項組件(to-do),該組件由待辦標題(to-do-title)和待辦事項(to-do-items)組成,但這三個組件又相互獨立,該如何操作?
代碼示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>插槽slot</title>
<!--引入Vue.js-->
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
</head>
<body>
<div id="app10">
<to-do>
<to-do-title slot="to-do-title" v-bind:title="toDoTitle"></to-do-title>
<to-do-items slot="to-do-items" v-for="item in toDoList" v-bind:item="item"></to-do-items>
</to-do>
</div>
<script type="text/javascript">
Vue.component("to-do", {
// template: '<div>' +
// '<slot></slot>' +
// '<ul>' +
// '<slot></slot>' +
// '</ul>' +
// '</div>'
// 使用折行轉義字元,使多行html模板更簡潔
template: '<div>\
<slot name="to-do-title"></slot>\
<ul>\
<slot name="to-do-items"></slot>\
</ul>\
</div>'
});
Vue.component("to-do-title", {
props: ['title'],
template: '<p>{{title}}</p>'
});
Vue.component("to-do-items", {
props: ['item'],
template: '<li>{{item}}</li>'
});
var vm = new Vue({
el: "#app10",
data: {
toDoTitle: "待辦事項",
toDoList: ['起床', '洗漱', '工作']
}
});
</script>
</body>
</html>
Vue 中使用 Element-UI 組件
element-ui 官網鏈接:https://element.eleme.cn/#/zh-CN/component/table
vue2.x 鏈接:https://v2.cn.vuejs.org/v2/guide/installation.html
下麵是在 Vue 中使用 Element-UI 表單組件示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue + element-ui 組件使用示例</title>
<!-- 第一步:引入樣式和組件庫 -->
<!-- 引入element-ui的樣式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入vue2.0的組件庫,element-ui的組件庫是基於vue的,需要提前引入 -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<!-- 引入element-ui的組件庫 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="container">
<!-- 第二步:在vue容器中複製進指定element-ui組件的模板代碼 -->
<template>
<el-table :data="tableData" border style="width: 100%">
<el-table-column prop="date" label="日期" width="180">
</el-table-column>
<el-table-column prop="name" label="姓名" width="180">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
</el-table>
</template>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#container",
// 第三步:引入示例數據
data: {
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀區金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀區金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀區金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀區金沙江路 1516 弄'
}]
}
});
</script>
</body>
</html>
自定義事件內容分發
- 通過組件無法直接操作 Vue 對象的數據,可以通過組件調前端,通過前端操作 Vue 對象的數據,實現組件操作 Vue 對象數據。
- 核心:自定義事件
this.$emit('myEvent')
- 例如:在組件中添加一個刪除按鈕,要求點擊刪除,將指定列表數據刪除
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>插槽slot之自定義事件分發</title>
<!--引入Vue.js-->
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
</head>
<body>
<div id="app10">
<to-do>
<to-do-title slot="to-do-title" v-bind:title="toDoTitle"></to-do-title>
<to-do-items slot="to-do-items"
v-for="(luis, index) in toDoList"
v-bind:item="luis"
v-bind:index="index"
v-on:rm="removeItem(index)"></to-do-items><!--綁定自定義事件-->
</to-do>
</div>
<script type="text/javascript">
Vue.component("to-do", {
// template: '<div>' +
// '<slot></slot>' +
// '<ul>' +
// '<slot></slot>' +
// '</ul>' +
// '</div>'
// 使用折行轉義字元,使多行html模板更簡潔
template: '<div>\
<slot name="to-do-title"></slot>\
<ul>\
<slot name="to-do-items"></slot>\
</ul>\
</div>'
});
Vue.component("to-do-title", {
props: ['title'],
template: '<p>{{title}}</p>'
});
Vue.component("to-do-items", {
props: ['item', 'index'],
// template: '<li>{{item}} <button @click="remove">刪除</button></li>',
template: '<li>{{index}}---{{item}} <button v-on:click="remove">刪除</button></li>',
methods: {
remove: function (index) {
//自定義事件分發
//不能直接通過組件控制Vue對象中的方法;可通過組件調前端,再通過前端來控制Vue對象
this.$emit("rm", index);
}
}
});
var vm = new Vue({
el: "#app10",
data: {
toDoTitle: "待辦事項",
toDoList: ['起床', '洗漱', '工作']
},
methods: {
removeItem: function (index) {
//刪除指定數組下標處指定個數的元素
this.toDoList.splice(index, 1);
}
}
});
</script>
</body>
</html>
Vue 入門小結
核心:數據驅動,組件化
優點:借鑒了 AngularJS 的模塊化開發和 React 的虛擬 Dom;虛擬 Dom 就是把 Dom 的操作放到記憶體中執行。
常用屬性:
v-if
v-else-if
v-else
v-for
v-on
綁定事件,簡寫@
v-model
數據雙向綁定v-bind
給組件綁定參數,簡寫:
組件化:
- 組合組件 slot 插槽
- 組件內部綁定事件需要使用到
this.$emit("事件名", 參數);
- 計算屬性的特色,緩存計算數據
遵循 SoC 關註度分離原則,Vue 是純粹的視圖框架,並不包含如 Ajax 之類的通信功能,為瞭解決通信問題,我們需要使用 Axios 框架做非同步通信。
說明:
- 以上屬於 Vue 的基礎語法,包括示例都是為了演示語法的使用,實際開發不會採用此方式!
- Vue 的開發都是要基於 NodeJS,實際開發都是採用的 vue-cli 腳手架,vue-router 實現路由(跳轉),vuex 實現狀態管理(會話管理),Vue UI 界面,一般使用 ElementUI(餓了麽出品),或使用 ICE(阿裡巴巴出品)來快速搭建前端項目!
Axios 非同步通信
vue 可以實現數據的渲染,但是如何獲取數據呢?
vue 本身不具備通信能力,通常結合 axios(一個專註於非同步通信的 js 框架)來使用。
- Axios 中文文檔:http://www.axios-js.com/zh-cn/docs/
如果使用 IDEA 寫代碼需要保證設置中 JavaScript 規範為 ECS 6+,如下:
什麼是 Axios
- Axios 是一個基於 promise 的 HTTP 庫,可以用在瀏覽器和 node.js 中,其主要作用就是實現 AJAX 非同步通信。
為什麼使用 Axios
- 由於
Vue.js
是一個視圖層框架,並且其開發者(尤雨溪)嚴格遵守 SOC(關註度分離原則),所以Vue.js
並不包含 AJAX 的通信功能,為瞭解決通信問題,作者單獨開發了一個名為vue-resource
的插件,不過在進入 2.0 版本以後,其停止了對該插件的維護並推薦了Axios
框架。建議少用 jQuery,因為它操作 DOM 太頻繁。 - 對於非同步通信:
- 原生 ajax:實現步驟複雜
- jQuery:笨重
- Axios:簡潔高效,對 RESTful 支持良好
安裝
可使用 npm、bower、cdn 等,此處選擇使用 cdn:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
使用案例
非同步請求
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!-- vue -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<!-- axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="container">
<button type="button" @click="test1">測試1</button>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#container",
methods: {
test1: function() {
//發送非同步請求
// axios.get(url).then(fn);
// axios.get(url,{}).then(fn)
axios.get("http://localhost:9999/music/detail", {
params: {
id: "25640392"
}
})
.then(function(res) {
console.log(res);
});
}
}
});
</script>
</body>
</html>
Axios 提供了多種非同步請求方法,實現對 RESTful 風格的支持。
get 請求
無參傳遞:
axios.get(url).then(fn);
有參傳遞:
axios.get(url,{}).then(fn)
//使⽤axios的get請求傳遞參數,需要將參數設置在params下 axios.get("http://localhost:9999/music/detail",{ params:{ id:"25640392" } }) .then(function(res){ console.log(res); });
post 請求
axios.post(url,{}).then(fn)
axios.post("http://localhost:9999/music/search",{s:"阿刁"}) .then(function(res){ console.log(res); });
自定義請求:自定義請求方式、請求參數、請求頭、請求體(post)
axios({ url:"http://localhost:9999/music/search", method:"post", params:{ //設置請求⾏傳值 s:"成都", limit:15 }, headers:{ //設置請求頭 }, data:{ //設置請求體(post/put) } }).then(function(res){ console.log(res) });
其他
- delete
- put
- option
併發請求
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!-- vue -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<!-- axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="container">
<button type="button" @click="test1">測試1</button>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#container",
methods: {
test1: function() {
//發送非同步請求
axios.all([listMusics(), getMusicDetail()]).then(axios.spread(function(r1, r2) {
// 兩個請求現在都執行完成
console.log(r1);
console.log(r2);
}));
}
}
});
function listMusics() {
return axios.get('http://localhost:9999/music/search?s=成都');
}
function getMusicDetail() {
return axios.get('http://localhost:9999/music/detail?id=25640392');
}
</script>
</body>
</html>
箭頭函數
箭頭函數是一種語法,需要明白其使用格式。
先要註意:axios 的回調函數的參數 res,並不是介面返回的數據,而是表示一個響應對象;res.data 才表示介面響應回來的數