Vue常用操作
Vue常用操作: https://cn.vuejs.org/v2/api/
對Vue2的掌握,我們主要從
vue基礎指令、過濾器、監聽器、計算屬性、全局元件、父子元件、元件注冊、元件之間通信、自定義事件、插槽、路由、過渡動畫、vue生命周期開始着手。
一、Vue指令
-
内容渲染指令
内容渲染指令用來輔助開發者渲染DOM元素的文本内容,常用的内容渲染指令有: v-text、{{}}、v-html、v-once、v-pre、v-clock。
v-text:向頁面注入文本,相當于innerText。v-html:向頁面注入元素,相當于innerHTML。v-once:隻渲染元素群組件一次,v-pre:用于跳過這個元素和它子元素的編譯過程,标簽内怎麼編寫頁面就展示什麼。v-clock:在某些情況下(例如網絡延遲等),我們浏覽器可能會直接顯示出未編譯的插值運算符,也就是一閃而過看到{{}}這些雙括号的模闆,我們可以采用該指令。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
<style>
[v-clock] {
display: none;
}
</style>
</head>
<body>
<div id="app">
<!-- v-tetx相當于innerText,把username 對應的值渲染到第一個p标簽中 -->
<p v-text="username">姓名</p>
<!-- {{}}插值運算把gender對應的值渲染第二個p标簽中-->
<p>性别:{{gender}}</p>
<!-- v-html相當于innerHTML,把包含HTML标簽的字元串渲染到頁面上-->
<p v-html="hobby">愛好</p>
<hr />
<!-- v-once元素群組件隻會被渲染一次 -->
<p v-once>原始值:{{msg}}</p>
<p>後面值:{{msg}}</p>
<input type="text" v-model="msg" />
<!-- v-pre跳過元素和子元素的編譯過程,原始展示 -->
<p v-pre>{{msg}}}</p>
<!-- 解決因為網絡延遲導緻的插值運算值還沒有及時渲染時情況 -->
<p v-clock>{{msg}}</p>
</div>
<script>
const vm = new Vue({
el:'#app',
data:{
username:'張三',
gender:'男',
hobby:'<font color="red">王者榮耀</font>',
msg:'這是一條測試消息'
}
});
</script>
</body>
</html>
測試結果:

内容渲染指令使用
-
屬性綁定指令
v-bind動态地綁定一個或多個特性。給一個标簽動态綁定一個屬性、樣式、一些類,或者将一個對象綁定到一個标簽上。鑒于v-bind使用較多,官方推薦使用簡寫
:屬性。<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
<style>
.active {
background-color: orange;
}
.fontActive {
font-size: 20px;
}
</style>
</head>
<body>
<div id="app">
<!-- 綁定一個屬性 ,v-bind可以簡寫-->
<img v-bind:src="imgSrc" height="100" width="100" />
<img :src="imgSrc" height="100" width="100"/>
<!-- 綁定一個樣式 -->
<p :style='{color:fontColor}'>我愛Vue</p>
<!-- 綁定一個類 -->
<p v-for="(course,index) in courses" :class='index==acticeIndex?"active":""'>
{{course}}
</p>
<p :class=['active',{'fontActive':bool}]>多個樣式</p>
<!-- 綁定一個有屬性的對象-->
<p v-bind="{id:1,name:'mytext'}">綁定有屬性的對象</p>
</div>
<script>
const vm = new Vue({
el:'#app',
data:{
//綁定屬性
imgSrc:'img/1.jpeg',
//綁定樣式
fontColor:'red',
bool:true,
//綁定class
courses:['html','css','javascript'],
acticeIndex:2
}
});
</script>
</body>
</html>
測試結果:
v-bind指令使用
補充:vue指令中可以使用JavaScript表達式: 在 vue 提供的模闆渲染文法中,除了支援綁定簡單的資料值之外,還支援 Javascript 表達式的運算,例如- 事件綁定指令
vue 提供了 v-on 事件綁定指令,用來輔助程式員為 DOM 元素綁定事件監聽。v-on針對事件,動态綁定事件。表示形式有v-on:事件=“事件函數”或者簡寫@事件=“事件函數”,通過v-on綁定的事件處理函數,需要在methods節點中聲明。原生DOM對象有onclikc、oninput、onkeyup等原生時間,vue相應替換分别為:v-on:click、v-on:input、v-on:keyup。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
<style>
.active {
background-color: orange;
}
.fontActive {
font-size: 20px;
}
</style>
</head>
<body>
<div id="app">
<h3>count的值為: {{count}}</h3>
<!-- "v-on:事件"完整寫法 -->
<button v-on:click="addCount">+1</button>
<!-- "v-on:事件"簡寫形式,把v-on:簡寫為 @符号 -->
<!-- 如果事件處理函數中的代碼足夠簡單,隻有一行代碼,則可以簡寫到行内 -->
<button @click="count+=1">+1</button>
</div>
<script>
const vm = new Vue({
el:'#app',
data:{
count:0
},
methods:{
addCount(){
this.count+=1;
}
}
});
</script>
</body>
</html>
1.綁定事件并傳參
在使用v-on指令綁定事件時,可以使用()進行傳參,示例如下:
綁定事件并傳參
2.$event
$event是vue提供的特殊變量,用來表示原生的事件參數對象event。$event可以解決事件參數對象event被覆寫的問題,示例如 下:
$event使用
3.事件修飾符
在事件處理函數中調用 event.preventDefault() 或 event.stopPropagation() 是非常常見的需求。是以,vue 提供了事件修飾符的概念,來輔助程式員更友善的對事件的觸發進行控制。常用的 5 個事件修飾符如下:
事件修飾符 | 說明 |
.prevent | 阻止預設行為(例如:阻止a連結的跳轉、阻止表單的送出等) |
.stop | 阻止事件冒泡 |
.capture | 以捕獲模式觸發目前的事件處理函數 |
.once | 綁定的事件隻能觸發一次 |
.self | 隻有在event.target 是目前元素自身時觸發事件處理函數 |
4.按鍵修飾符
在監聽鍵盤事件時,我們經常需要判斷詳細的按鍵。此時,可以為鍵盤相關的事件添加按鍵修飾符,例如:
-
雙向綁定指令
vue 提供了 v-model 雙向資料綁定指令,用來輔助開發者在不操作 DOM 的前提下,快速擷取表單的資料。
為了友善對使用者輸入的内容進行處理,vue 為 v-model 指令提供了 3 個修飾符,分别是:
示例 | ||
.number | 自動将使用者的輸入值轉為數值類型 | <input v-model.number="age" /> |
.trim | 自動過濾使用者輸入的首尾空白字元 | <input v-model.trim="msg" /> |
.lazy | 在“change”時而非“input”時更新 | <input v-model.lazy="msg" /> |
-
條件渲染指令
條件渲染指令用來輔助開發者按需控制 DOM 的顯示與隐藏。條件渲染指令有如下兩個,分别是:v-if(v-else-if、v-else)、v-show。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
</head>
<body>
<div id="app">
<div v-show="score<60">差</div>
<div v-show="score>=60&&score<90">良</div>
<div v-show="score>=90">優秀</div>
<!-- v-if、v-else-if、v-else相當于if、else if、else,隻會展示符合條件的元素,其他元素均移除 -->
<div v-if="score<60">差</div>
<div v-else-if="score>=60&&score<90">良</div>
<div v-else>優秀</div>
</div>
<script>
const vm = new Vue({
el:'#app',
data:{
score:80
}
});
</script>
</body>
</html>
v-if和v-show差別
v-if 和 v-show 的差別:實作原理不同:
⚫ v-if 指令會動态地建立或移除 DOM 元素,進而控制元素在頁面上的顯示與隐藏;
⚫ v-show 指令會動态為元素添加或移除 style="display: none;" 樣式,進而控制元素的顯示與隐藏;
性能消耗不同:
v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。是以:
⚫ 如果需要非常頻繁地切換,則使用 v-show 較好
⚫ 如果在運作時條件很少改變,則使用 v-if 較好
-
清單渲染指令
v-for基于資料源多次渲染元素或者模闆塊,也可以為數組索引指定别名(或者用于建立對象的鍵)。v-for 指令還支援一個可選的第二個參數,即目前項的索引。文法格式為 (item, index) in items。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
</head>
<body>
<div id="app">
<!--周遊數組-->
<p v-for="(score,index) in scores">{{index +':'+score}}</p>
<!-- 周遊對象數組 -->
<table border="1" align="center" width="300">
<thead style="background-color: orange;">
<tr align="center">
<td>姓名</td>
<td>年齡</td>
<td>性别</td>
</tr>
</thead>
<tbody>
<tr v-for="p in persons" align="center">
<td>{{p.name}}</td>
<td>{{p.age}}</td>
<td>{{p.sex}}</td>
</tr>
</tbody>
</table>
<!-- 對字元串進行周遊 -->
<p v-for ="str in hobby">
{{str}}
</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
scores: [100, 90, 80, 70],
persons: [
{ name: '張三', age: 23, sex: '男' },
{ name: '李四', age: 24, sex: '女' },
{ name: '王五', age: 25, sex: '男' },
{ name: '趙六', age: 26, sex: '女' },
],
hobby:'籃球'
}
});
</script>
</body>
</html>
v-for指令使用
使用 key 維護清單的狀态當清單的資料變化時,預設情況下,vue 會盡可能的複用已存在的 DOM 元素,進而提升渲染的性能。但這種預設的性能優化政策,會導緻有狀态的清單無法被正确更新。
為了給 vue 一個提示,以便它能跟蹤每個節點的身份,進而在保證有狀态的清單被正确更新的前提下,提升渲染的性能。此時,需要為每項提供一個唯一的 key 屬性:
①key 的值隻能是字元串或數字類型
②key 的值必須具有唯一性(即:key 的值不能重複)
③建議把資料項 id 屬性的值作為 key 的值(因為 id 屬性的值具有唯一性)
④使用 index 的值當作 key 的值沒有任何意義(因為 index 的值不具有唯一性)
⑤建議使用 v-for 指令時一定要指定 key 的值(既提升性能、又防止清單狀态紊亂)
二、過濾器
過濾器(Filters)是 vue 為開發者提供的功能,常用于文本的格式化。過濾器可以用在兩個地方:插值表達式和 v-bind 屬性綁定。在建立 vue 執行個體期間,可以在 filters 節點中定義過濾 器。
過濾器分為:私有過濾器(在filters節點下定義的過濾器,隻能在目前vm執行個體所控制的el區域内使用)和全局過濾器(全局過濾器可以在多vue執行個體之間共享過濾器)。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
</head>
<body>
<div id="app">
<!-- 私有過濾器使用 -->
<p>{{sex | sexFormatter}}</p>
<!-- 全局過濾器使用 -->
<p>{{str | capitalize}}</p>
<!-- 連續調用多個過濾器 -->
<p>{{message | filterA | filterB}}</p>
<!-- 過濾器傳參 -->
<p>{{message | maxLength(5)}}</p>
</div>
<script>
//全局過濾器 -獨立于每個vm執行個體之外,必須定義在vm執行個體之前
//Vue.filter()方法接受兩個參數:
//第一個參數,是全局過濾器的"名字"
//第二個參數,是全局過濾器的"處理函數"
Vue.filter('capitalize',function(value){
return value.toUpperCase().split('').reverse().join('');
});
//全局過濾器 - 控制文本的最大長度
Vue.filter('maxLength',function(str,len = 4){
if(str.length<=len) return str;
return str.slice(0,len)+'...';
});
const vm = new Vue({
el:'#app',
data:{
sex:0,
str: 'abc',
message:'chensheng'
},
filters:{ //局部過濾器
sexFormatter(sex){
if(sex==0){
return "男";
}else{
return "女";
}
},
filterA(value){ //将首字母大寫
return value.charAt(0).toUpperCase()+value.slice(1);
},
filterB(value){ //将字元串反轉
return value.split('').reverse().join('');
}
}
});
</script>
</body>
</html>
過濾器使用
三、監聽器
如果我們需要監聽某個值的變化,當這個值變化是,進行一些操作,可以使用監聽器。監聽器的屬性名稱是watch,和data平級。監聽器中的資料是方法,接收兩個參數,分别為改變後的值和改變前的值。如果想讓wath偵聽器立即被調用,則需要使用immediate選項。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
</head>
<body>
<div id="app">
firstName:<input type="text" v-model="firstName" />
lastName:<input type="text" v-model="lastName" />
<h2>{{fullName}}</h2>
person:<input type="text" v-model="person.username" />
</div>
<script>
const vm = new Vue({
el:'#app',
data:{
firstName:'',
lastName:'',
fullName:'',
person:{username:'admin'}
},
watch:{
firstName(newVal,oldVal){
//在vue中,操作data、method必須使用this
this.fullName = this.firstName + this.lastName;
},
lastName(newVal,oldVal){
this.fullName = this.firstName + this.lastName;
},
person:{ //監聽對象内屬性變化,handler是固定寫法,當username值變化時,自動調用handler處理函數
handler(newVal){
console.info('如果監聽對象内屬性變化,則使用這種方式'+newVal.username);
},
deep: true, //如果watch偵聽的是一個對象,如果對象中的屬性值發生了變化,則無法被監聽到,需要使用deep選項才能偵聽
immediate:true //表示頁面初次渲染好之後,就立即觸發目前的watch偵聽器
},
'person.username':{
handler(newVal){
console.info('如果隻想監聽對象單個屬性變化,則使用這種方式'+newVal)
}
}
}
});
</script>
</body>
</html>
watch監聽器使用
四、計算屬性
計算屬性指的是通過一系列運算之後,最終得到一個屬性值。這個動态計算出來的屬性值可以被模闆結構或 methods 方法使用。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
</head>
<body>
<div id="app">
<p @click='show()'>計算屬性: {{reverseMsg}}</p>
</div>
<script>
const vm = new Vue({
el:'#app',
data:{
msg: 'hello world'
},
computed: {
//計算屬性的getter
reverseMsg: function() {
//this指向vm執行個體
return this.msg.split('').reverse().join('');
}
},
methods:{
show(){
console.info(this.reverseMsg); //在methods中調用屬性
}
}
});
</script>
</body>
</html>
計算屬性使用
計算屬性和 method差別?- 當頁面重新渲染(不是重新整理)的時候,計算屬性不會變化,直接讀取緩存使用,适合較大量的計算和改變頻率較低的屬性;而method就是當頁面重新渲染的時候(頁面元素的data變化,頁面就會重新渲染),都會重新調用method。
- 計算屬性是一個屬性,而不是方法。雖然寫法是方法,但是我們使用的時候是直接視為一個屬性去操作的,使用方式和data一緻。
- 計算屬性中使用到的data中的資料隻要發生了變化,計算屬性就會重新計算。如果兩次擷取計算屬性的時候,裡面使用到的屬性沒有發生變化,計算屬性會直接使用之前緩存的值。
- 計算屬性。在computed中,可以定義一些屬性,這些屬性叫做計算屬性,他本質上就是一個方法,但是,我們使用的時候是當做屬性來使用。計算屬性使用的過程中,一定不要加(),它就是一個屬性,和data裡的屬性用法一樣。
- 隻要極速暗屬性中所用到的data中的屬性發生了變化,就會立即去重新計算屬性的值。
- 計算屬性的結果會被緩存起來,友善下次調用,如果計算屬性中用到的data都沒有變化,就不會重新求值。
- 在計算屬性中,無論如何都需要return一個值,用來代表這個屬性的值。
- Computed用法視為一個屬性,并且結果會被緩存。
- Methods表示方法,表示一個具體的操作,主要用來寫業務邏輯
- Watch是一個對象,key是需要監聽的表達式,value是對應的回調函數,主要用來監聽某些資料的變化,進而執行某些具體的業務邏輯。可以看做是計算屬性和methods的結合體。
五、全局元件
元件是可複用的Vue執行個體,且帶一個名字,可以複用。我們搭建的頁面其實是一個個元件組裝而成,可以分為局部元件和全局元件。
- 局部元件:隻屬于目前Vue的執行個體,其他執行個體無法共享這個局部元件。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
</head>
<body>
<div id="app">
<my-date></my-date>
</div>
<script>
//1、建立元件構造器
let partialTemplate = Vue.extend({
template:`
<div>
<input type='date'/>
<p>今天天氣好晴朗!</p>
</div>
`
});
const vm = new Vue({
el: '#app',
// 注冊局部元件,隻屬于目前的vue執行個體
components:{
'my-date':partialTemplate
}
});
</script>
</body>
</html>
局部元件簡潔寫法:
const vm = new Vue({
el: '#app',
// 注冊局部元件,隻屬于目前的vue執行個體
components:{
'my-date':{
template:`
<div>
<input type='date'/>
<p>今天天氣好晴朗!</p>
</div>
`
}
}
});
vue注冊局部元件
- 全局元件:屬于所有的Vue執行個體所有。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
</head>
<body>
<div id="app">
<my-date></my-date>
</div>
<script>
//1. 建立元件構造器
let ProFile = Vue.extend({
//1.1 模闆選項
template:`
<div>
<input type="date"/>
<p>今天天氣好晴朗!</p>
</div>
`
});
//2. 注冊全局元件,參數1自定義元件名稱,參數2元件
Vue.component('my-date',ProFile);
const vm = new Vue({
el: '#app'
});
</script>
</body>
</html>
測試結果同上!
六、父子元件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
</head>
<body>
<div id="app">
<parent></parent>
</div>
<script>
// 1. 子元件構造器
let Child1 = Vue.extend({
template: `<img src="img/estar.ico" width="200">`
});
let Child2 = Vue.extend({
template: `<p>孤獨的星星!</p>`
});
// 2. 父元件構造器
Vue.component('parent', {
components: { //注冊子元件
'my-child1': Child1,
'my-child2': Child2
},
template: ` //組裝父元件
<div>
<my-child1></my-child1>
<my-child2></my-child2>
</div>
`
});
new Vue({
el: '#app'
});
</script>
</body>
</html>
父子元件
- template标簽和script标簽注冊元件
一、使用template來注冊元件【常用】
<body>
<div id="app">
<!-- 使用父元件 -->
<my-div></my-div>
</div>
<template id="parent">
<!-- 隻能有一個出口,最外層必須有标簽包裹 -->
<div>
<img src="img/estar.ico" width="200">
<p>孤獨的星星!</p>
</div>
</template>
<script>
//執行個體化元件
Vue.component('my-div', {
template: '#parent'
});
new Vue({
el: '#app'
});
</script>
</body>
二、使用script來注冊元件,必須聲明類型type=”text/template” 【不推薦使用】
<body>
<div id="app">
<!-- 使用父元件 -->
<my-div></my-div>
</div>
<script type="text/template" id="parent">
<!-- 隻能有一個出口,最外層必須有标簽包裹 -->
<div>
<img src="img/estar.ico" width="200">
<p>孤獨的星星!</p>
</div>
</script>
<script>
//執行個體化元件
Vue.component('my-div', {
template: '#parent'
});
new Vue({
el: '#app'
});
</script>
</body>
- 元件中data使用
下述在元件中直接調用data中的資料會報錯,如下所示:
首先,如果不是一個方法,Vue直接會報錯。其次,原因在于Vue讓每一個元件對象都傳回一個新的對象,如果是同一個對象的,元件會在多次使用後互相影響。如果我們不寫成方法傳回對象的話,那麼就是所有元件公用一個data。
u 我們将data定義成函數,這樣每個按鈕點選後都會産生自己獨享的變量,而不是共享的變量。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
</head>
<body>
<div id="app">
<!-- 使用元件 -->
<my-btn></my-btn>
<my-btn></my-btn>
<my-btn></my-btn>
</div>
<template id="btn_group">
<button @click="counter++">按鈕點選次數{{counter}}</button>
</template>
<script>
//執行個體化元件
Vue.component('my-btn', {
template: '#btn_group',
data() {
return { counter: 0 }
}
});
new Vue({
el: '#app'
});
</script>
</body>
</html>
測試結果:(描述,我們點選不同的按鈕統計的counter都是自己的)
u 如果我們将counter定義到外面來
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
</head>
<body>
<div id="app">
<!-- 使用元件 -->
<my-btn></my-btn>
<my-btn></my-btn>
<my-btn></my-btn>
</div>
<template id="btn_group">
<button @click="counter++">按鈕點選次數{{counter}}</button>
</template>
<script>
//元件将共享一個countDate
let countDate = { counter: 0 };
Vue.component('my-btn', {
template: '#btn_group',
data() {
return countDate;
}
});
new Vue({
el: '#app'
});
</script>
</body>
</html>
測試結果:(描述:我們點選其中一個按鈕其他按鈕點選次數也會随之改變,共享一個counter值)
七、元件通信
父子元件之間的通信,父元件通過 prop 給子元件下發資料,子元件通過$emit觸發事件給父元件發送消息,即
prop 向下傳遞,事件向上傳遞。
-
父元件向子元件傳值(簡單的單層元件之間的值傳遞)
首先在父元件中使用v-bind将數組綁定給子元件,再在子元件中,使用props收。
<body>
<div id="app">
<my-div :msg='孤獨的星星' imgsrc='img/estar.ico'></my-div>
</div>
<template id="my_div">
<div>
<h1>{{msg}}</h1>
<img :src="imgsrc" width="100" height="100" />
</div>
</template>
<script>
//執行個體化元件
Vue.component('my-div', {
template: '#my_div',
props:['msg','imgsrc'] //父元件通過props向子元件傳遞值
});
new Vue({
el: '#app'
});
</script>
</body>
或者使用綁定的方式将父元件的值傳遞給子元件:
<body>
<div id="app">
<!-- 使用綁定的方式,将父元件的資料綁定給子元件 -->
<my-div :msg='msg' :imgsrc='imgsrc'></my-div>
</div>
<template id="my_div">
<div>
<h1>{{msg}}</h1>
<img :src="imgsrc" width="100" height="100" />
</div>
</template>
<script>
//執行個體化元件
const myCom = Vue.component('my-div', {
template: '#my_div',
props:['msg','imgsrc'] //父元件通過props向子元件傳遞值,或者寫法如下
//props: {
// msg: {
// type: String, //type支援的類型有: String、Number、Boolean、Array、Object、Date、Function、Symbol
// default: '我是預設值,父元件沒有傳給我msg'
// }
// }
});
new Vue({
el: '#app',
data:{
msg:'孤獨的星星',
imgsrc:'img/estar.ico'
},
components:{
myCom
}
});
</script>
</body>
父元件向子元件傳值之單層元件傳值
-
父元件向子元件傳值(多層元件之間的值傳遞)
多層元件傳值示意圖
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
</head>
<body>
<div id="app">
<!-- 使用父元件 -->
<my-parent :imgtitle="title" :imgsrc="img"></my-parent>
</div>
<!-- 定義子元件 -->
<template id="my_img">
<img :src="imgsrc" width="200" />
</template>
<template id="my_title">
<h2>{{title}}</h2>
</template>
<!-- 定義父元件 -->
<template id="my_parent">
<div>
<child1 :imgsrc="imgsrc"></child1>
<child2 :title="imgtitle"></child2>
</div>
</template>
<script>
//1.子元件的執行個體
let child1 = Vue.extend({
template: '#my_img',
props: ['imgsrc']
});
let child2 = Vue.extend({
template: '#my_title',
props: ['title']
});
//2.注冊父元件
Vue.component('my-parent', {
props: ['imgtitle', 'imgsrc'],
components: {
'child1': child1,
'child2': child2
},
template: '#my_parent'
});
new Vue({
el: '#app',
data: {
title: '孤獨的星星',
img: 'img/estar.ico'
}
});
</script>
</body>
</html>
父元件向子元件傳值之多層元件傳值
-
父元件向子元件傳遞事件
我們知道父元件是使用props傳遞資料給子元件,但如果子元件要把資料傳遞回去,則應該使用自定義事件來完成!
使用$on(eventName)監聽事件,使用$emit(eventName)來觸發事件,另外父元件可以在使用子元件的地方直接使用v-on來監聽子元件除法的事件。
描述: 我們在父元件中自定義一個total事件,當我們觸發這個total()事件的時候通過$emit('total')來觸發外界定義的@total="allcounter()"中
的具體的方法allcounter()。注意在此案例中按鈕與按鈕之間是互相獨立的,互不影響。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
</head>
<body>
<div id="app">
<!—自定義事件-->
<my-btn @total="allcounter()"></my-btn>
<my-btn @total="allcounter()"></my-btn>
<my-btn @total="allcounter()"></my-btn>
<my-btn @total="allcounter()"></my-btn>
<p>所有按鈕一共點選了{{totalCounter}}次</p>
</div>
<template id="my_btn">
<button @click="total()">點選了{{counter}}次</button>
</template>
<script>
Vue.component('my-btn', {
template: '#my_btn',
data() {
return {
counter: 0
}
},
methods: {
total() {
this.counter += 1; //不同的按鈕享有不同的counter
// 通知外界,我調用了這個方法
this.$emit('total');
}
}
});
new Vue({
el: '#app',
data: {
totalCounter: 0 //公共的資料
},
methods: {
allcounter() {
this.totalCounter += 1;
}
}
});
</script>
</body>
</html>
測試結果:(描述我們低級不同的按鈕分别統計不同的按鈕點選次數,互不影響)
-
父元件調用子元件方法
$refs是和ref一起使用的。通過ref給某個子元件綁定一個特定的ID,然後我們使用$refs.ID就可以通路到子元件了。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
</head>
<body>
<div id="app">
<button @click="countAdd">點我</button>
<!-- 第一步,給子元件綁定一個ref -->
<my-com ref="myComp"></my-com>
</div>
<template id="myTemp">
<div>
{{count}}
</div>
</template>
<script>
let myCom = Vue.extend({
template: '#myTemp',
data() {
return {
count: 1
}
},
methods: {
addCount() {
this.count++
}
}
})
let app = new Vue({
el: '#app',
methods: {
countAdd() {
// 第二步,在父元件中使用this.$refs.id就行了
console.log(this.$refs.myComp.count)
this.$refs.myComp.addCount()
}
},
components: {
myCom
}
})
</script>
</body>
</html>
八、插槽
Slot插槽實作内容分發,結合日常生活中的電路闆,有指定插孔,我們可以插入任何電器插頭(匿名插槽),也有專門針對手機的USB插頭(實名插槽),無法插入其他電器插頭。
- 匿名插槽
<body>
<div id="app">
<my-slot>
<img src="img/estar.ico" width="200" alt="">
<p>{{msg}}</p>
</my-slot>
</div>
<template id="my_slot">
<div>
<header>插槽的頭部</header>
<!--預留一個插槽,沒有則顯示該插槽内容-->
<slot>可以替換任何标簽,預設顯示提示的内容</slot>
<footer>插槽的尾部</footer>
</div>
</template>
<script>
Vue.component('my-slot', {
template: '#my_slot'
});
new Vue({
el: '#app',
data: {
msg: '孤獨的星星'
}
});
</script>
</body>
- 實名插槽
<body>
<div id="app">
<my-computer>
<div slot="cpu">core-i7 6700HQ處理器</div>
<div slot="memory">Kingston-32G記憶體條</div>
</my-computer>
</div>
<template id="my_computer">
<div>
<slot name="cpu">預設插cpu的</slot>
<slot name="memory">預設插記憶體條的</slot>
<slot name="hard-drive">預設插硬碟的</slot>
</div>
</template>
<script>
Vue.component('my-computer', {
template: '#my_computer'
});
new Vue({
el: '#app'
});
</script>
九、路由
參考部落格: https://www.jianshu.com/p/9a7d79249741
https://www.jianshu.com/p/2acf9e23793a
前端路由和後端路由:
- 後端路由:對于普通的網站,所有的超連結都是url位址,所有url都對應伺服器上對應的資源
-
前端路由:對于單頁面應用程式來說,主要通過url的hash(#)來實作不同頁面的切換,同時hash還有一個特點HTTP請求中不會包含hash相關的内容,是以單頁面程式中的頁面跳轉主要用hash實作
在單頁面應用程式中這種通過hash來改變頁面的方式稱作前端路由差別于後端路由
==>
由于Vue在開發時對路由支援的不足,于是官方補充了vue-router插件。vue的單頁面應用是基于路由群組件的,路由用于設定通路路徑,并将路徑群組件映射起來。- 引入vue-router
<script src="lib/vue-router.js"></script>
或者: <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
- 路由入門
建立一個路由對象,當導入vue-router包之後,在window全局對象中就有一個路由的構造函數VueRouter在new路由對象的時候可以傳遞一個配置對象,這個配置對象的route表示路由器的比對規則每個路由規則都是一個對象,這個規則對象身上必須有兩個屬性
屬性1 path表示監聽哪個路由連結位址
屬性2 component,表示如果路由是前面比對到的path,則展示component屬性對應的元件,component屬性值必須是一個元件模闆對象,不能是元件的引用名稱
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="lib/vue-2.6.12.js"></script>
<script src="lib/vue-router.js"></script>
<style>
ul li {
float: left;
width: 300px;
height: 70px;
box-sizing: border-box;
background-color: pink;
list-style: none;
line-height: 70px;
text-align: center;
}
ul li a {
text-decoration: none;
font-size: 20px;
}
.content {
clear: both;
width: 900px;
box-sizing: border-box;
border: 1px solid blue;
padding-left: 20px;
margin-left: 40px;
}
</style>
</head>
<body>
<div id="app">
<!-- 使用 router-link 元件來導航. -->
<!-- 通過傳入 `to` 屬性指定連結. -->
<!-- <router-link> 預設會被渲染成一個 `<a>` 标簽 -->
<ul>
<li>
<router-link to="/h5">HTML5學院</router-link>
</li>
<li>
<router-link to="/python">Python學院</router-link>
</li>
<li>
<router-link to="/java">Java學院</router-link>
</li>
</ul>
<div class="content">
<!-- 路由出口 -->
<!-- 路由比對到的元件将渲染在這裡 -->
<router-view></router-view>
</div>
</div>
<template id="h5">
<div>
<h2>HTML5學院</h2>
<p>掌握面向未來的神技!</p>
</div>
</template>
<template id="python">
<div>
<h2>Python學院</h2>
<p>人工智能的最佳選擇!</p>
</div>
</template>
<template id="java">
<div>
<h2>Java學院</h2>
<p>掌握面向工資程式設計!</p>
</div>
</template>
<script>
//1.建立元件
const Html5 = Vue.extend({
template: '#h5'
});
const Python = Vue.extend({
template: '#python'
});
const Java = Vue.extend({
template: '#java'
});
//2.定義路由
const routes = [
{ path: '/h5', component: Html5 },
{ path: '/python', component: Python },
{ path: '/java', component: Java },
//配置根路由,預設顯示
{ path: '/', redirect: '/h5' }
];
//3.建立路由執行個體
const router = new VueRouter({
routes
});
//4.建立Vue執行個體并挂載
new Vue({
router
}).$mount('#app');
</script>
</body>
</body>
</html>
測試結果: (描述:我們點選不同的tab切換頁能實作展示不同的内容)
vue路由使用
補充:上述代碼存在一個弊端,就是<router-link
to="/h5">HTML5學院</router-link>路由時我們需要将路由路徑寫死在頁面上,建議采用動态綁定的方式會更好。下面采用給路由命名的方式來解決這個問題
<body>
<div id="app">
<!-- 使用 router-link 元件來導航. -->
<!-- 通過傳入 `to` 屬性指定連結. -->
<!-- <router-link> 預設會被渲染成一個 `<a>` 标簽 -->
<ul>
<li><router-link :to="{name:'h5'}">HTML5學院</router-link></li>
<li><router-link :to="{name:'python'}">Python學院</router-link></li>
<li><router-link :to="{name:'java'}">Java學院</router-link></li>
</ul>
<div class="content">
<!-- 路由出口 -->
<!-- 路由比對到的元件将渲染在這裡 -->
<router-view></router-view>
</div>
</div>
<template id="h5">
<div>
<h2>HTML5學院</h2>
<p>掌握面向未來的神技!</p>
</div>
</template>
<template id="python">
<div>
<h2>Python學院</h2>
<p>人工智能的最佳選擇!</p>
</div>
</template>
<template id="java">
<div>
<h2>Java學院</h2>
<p>掌握面向工資程式設計!</p>
</div>
</template>
<script>
//1.建立元件
const Html5 = Vue.extend({
template: '#h5'
});
const Python = Vue.extend({
template: '#python'
});
const Java = Vue.extend({
template: '#java'
});
//2.定義路由
const routes = [
{ path: '/h5', component: Html5,name:'h5' },
{ path: '/python', component: Python,name:'python' },
{ path: '/java', component: Java ,name:'java'},
//配置根路由,預設顯示
{ path: '/', redirect: '/h5' }
];
//3.建立路由執行個體
const router = new VueRouter({
routes
});
//4.建立Vue執行個體并挂載
new Vue({
router
}).$mount('#app');
</script>
</body>
-
多級子路由
<body> <div id="app"> <!-- 使用 router-link 元件來導航. --> <!-- 通過傳入 `to` 屬性指定連結. --> <!-- <router-link> 預設會被渲染成一個 `<a>` 标簽 --> <ul> <li><router-link to="/h5">HTML5學院</router-link></li> <li><router-link to="/python">Python學院</router-link></li> <li><router-link to="/java">Java學院</router-link></li> </ul> <div class="content"> <!-- 路由出口 --> <!-- 路由比對到的元件将渲染在這裡 --> <router-view></router-view> </div> </div> <template id="h5"> <div> <h2>HTML5學院</h2> <p>掌握面向未來的神技!</p> </div> </template> <template id="python"> <div> <h2>Python學院</h2> <p>人工智能的最佳選擇!</p> </div> </template> <template id="java"> <div> <h2>Java學院</h2> <p>掌握面向工資程式設計!</p> <!--子元件路由--> <router-link to="/java/base">基礎班</router-link> <router-link to="/java/advance">進階班</router-link> <div> <!-- 子元件出口 --> <router-view></router-view> </div> </div> </template> <!-- 定義Java元件下的子元件 --> <template id="base"> <div> <h3>Java基礎班</h3> <p>快速掌握Java的三大特性!</p> </div> </template> <template id="advance"> <div> <h3>Java進階班</h3> <p>掌握高并發高可用的架構!</p> </div> </template> <script> //1.建立元件 const Html5 = Vue.extend({ template: '#h5' }); const Python = Vue.extend({ template: '#python' }); const Java = Vue.extend({ template: '#java' }); //建立Java的子元件 const base = Vue.extend({ template: '#base' }); const advance = Vue.extend({ template: '#advance' }); //2.定義路由 const routes = [ { path: '/h5', component: Html5 }, { path: '/python', component: Python }, { path: '/java', component: Java, children: [ //使用children屬性實作路由嵌套,子路由path前不要加/,否則永遠以根路徑開始請求 {path:'base', component: base}, {path:'advance', component: advance}, // 配置Java元件的根路由,預設顯示 {path:'/', redirect: 'base'} ] }, //配置根路由,預設顯示 { path: '/', redirect: '/h5' } ]; //3.建立路由執行個體 const router = new VueRouter({ routes }); //4.建立Vue執行個體并挂載 new Vue({ router }).$mount('#app'); </script> </body>
vue多級子路由使用
- 路由傳參
- 如果使用查詢字元串 給路由傳遞參數則不需要修改路由規則的path屬性,直接在元件當中使用 {$route.query.字段名}}即可擷取值。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="lib/vue-2.6.12.js"></script>
<script src="lib/vue-router.js"></script>
</head>
<body>
<div id="app">
<!-- 路由入口 -->
<router-link to="/login?username=zs&password=123">登入</router-link>
<div>
<!-- 路由出口 -->
<router-view></router-view>
</div>
</div>
<template id="userInfo">
<div>
使用者:{{$route.query.username}},密碼:{{$route.query.password}}
</div>
</template>
<script>
//1.建立元件
const userInfo = Vue.extend({
template: '#userInfo'
});
//2.定義路由
const routes = [
{ path: '/login', component: userInfo },
//配置根路由,預設顯示
{ path: '/', redirect: 'login' }
];
//3.建立路由執行個體
const router = new VueRouter({
routes
});
//4.建立Vue執行個體并挂載
new Vue({
router
}).$mount('#app');
</script>
</body>
</html>
<router-link to="/login/zs">登入</router-link>
{ path: '/login/:username', component: userInfo }
<template id="userInfo">
<div>
使用者:{{$route.params.username}}
</div>
</template>
十、過渡動畫
Vue中為我們提供了簡單的過渡動畫效果,隻需要按照vue提供的标準去寫一套固定的CSS即可。
<style>
/* v-enter 這個是一個時間點,表示動畫進入之前,元素的起始狀态,此時還沒有進入 */
/* v-leave-to 這是一個時間點,是動畫離開之後,元素的終止狀态,此時,元素動畫已經結束了 */
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateX(50px);
}
/* v-enter-active 表示入場動畫的時間段 */
/* v-leave-active 表示離場動畫的時間段 */
.v-enter-active,
.v-leave-active {
transition: all 0.8s ease;
}
</style>
<body>
<div id="app">
<button @click="flag = !flag">點選</button>
<transition>
<div v-show="flag">這個是第一個div</div>
</transition>
</div>
</body>
<script>
let app = new Vue({
el: '#app',
data: {
flag: true
},
methods: {
}
})
</script>
此時如果我們想要讓div1消失後,div2進來,div2消失後div1進來,應該怎麼辦?隻需要寫兩套動畫即可
<transition>
<div v-show="flag">這個是第一個div</div>
</transition>
<transition>
<div v-show="!flag">這個是第二個div</div>
</transition>
如果div1和div2不想公用一套動畫,應該怎麼辦?這時候我們可以給transition命名,使用name屬性即可。定義了name之後,兩個transition則使用自己獨立的動畫效果。定義了name之後,動畫的相關class,要以name開頭,不能以v開頭。
<transition name="div1">
<div v-show="flag">這個是第一個div</div>
</transition>
<transition name="div2">
<div v-show="!flag">這個是第二個div</div>
</transition>
<style>
/* v-enter 這個是一個時間點,表示動畫進入之前,元素的起始狀态,此時還沒有進入 */
/* v-leave-to 這是一個時間點,是動畫離開之後,元素的終止狀态,此時,元素動畫已經結束了 */
.div1-enter,
.div1-leave-to {
opacity: 0;
transform: translateX(50px);
}
/* v-enter-active 表示入場動畫的時間段 */
/* v-leave-active 表示離場動畫的時間段 */
.div1-enter-active,
.div1-leave-active {
transition: all 0.8s ease;
}
/* v-enter 這個是一個時間點,表示動畫進入之前,元素的起始狀态,此時還沒有進入 */
/* v-leave-to 這是一個時間點,是動畫離開之後,元素的終止狀态,此時,元素動畫已經結束了 */
.div2-enter,
.div2-leave-to {
opacity: 0;
transform: translateX(50px);
}
/* v-enter-active 表示入場動畫的時間段 */
/* v-leave-active 表示離場動畫的時間段 */
.div2-enter-active,
.div2-leave-active {
transition: all 0.2s ease;
}
</style>
十一、生命周期
vue生命周期
vue生命周期示意圖
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="lib/vue-2.6.12.js"></script>
</head>
<body>
<div id="app">
<div id="divId">頁面還沒有渲染 --- {{msg}}</div>
</div>
</body>
<script>
var vue = new Vue({
el: '#app',
data: {
msg: '頁面渲染完畢'
},
methods: {},
filters: {},
beforeCreate() {
// 這是我們第一個遇到的生命周期函數,執行個體被建立出來,還沒有data、methods等時,會執行它
let content = document.getElementById('divId')
console.log('beforeCreate:', content.innerText)
// 在js中,null和undefined是不同的含義。null表示有這個對象,但是這個對象的值是null。undefined表示壓根就沒有這個對象
console.log('beforeCreate', this.msg)
},
created() {
// Vue執行個體建立完畢,methods、data、filters等已經挂載到vue執行個體上。如果需要調用methods,使用data,最早隻能在這裡操作
let content = document.getElementById('divId')
console.log('created', content.innerText)
console.log('created', this.msg)
},
beforeMount() {
// Vue執行個體建立完畢,頁面尚未重新渲染
let content = document.getElementById('divId')
console.log('beforeMounte', content.innerText)
console.log('beforeMounte', this.msg)
},
mounted() {
// 頁面渲染完畢
let content = document.getElementById('divId')
console.log('mounted', content.innerText)
console.log('mounted', this.msg)
}
})
</script>
</html>
十二、實戰演練
案例一: 本地模拟員工資訊的增删改查功能。 源碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!-- 引入layui樣式 -->
<link rel="stylesheet" href="lib/layui/css/layui.css" />
<!--引入vue.js-->
<script src="lib/vue-2.6.12.js"></script>
<!-- 引入layui.js -->
<script src="lib/layui/layui.all.js"></script>
</head>
<body>
<div id="app">
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;">
<legend>員工管理</legend>
</fieldset>
<!-- 搜尋欄 -->
<form class="layui-form">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">姓 名:</label>
<div class="layui-input-inline">
<input type="text" v-model="searchName" placeholder="請輸入姓名" class="layui-input">
</div>
</div>
<div class="layui-inline">
<button type="button" class="layui-btn layui-btn-normal layui-icon layui-icon-search" @click="searchUser">查詢</button>
<button type="reset" class="layui-btn layui-btn-warm layui-icon layui-icon-refresh">重置</button>
<button type="button" class="layui-btn layui-btn layui-icon layui-icon-addition" @click="saveOrUpdateDiv()">添加</button>
</div>
</div>
</form>
<!-- 資料表格 -->
<table class="layui-table">
<thead>
<tr>
<th>編号</th>
<th>姓名</th>
<th>年齡</th>
<th>性别</th>
<th>備注</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item in userList" :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.gender | handlerGender}}</td>
<td>{{item.remark}}</td>
<td>
<button type="button" class="layui-btn layui-btn-normal" @click="saveOrUpdateDiv(item)">編輯</button>
<button type="button" class="layui-btn layui-btn-danger" @click="delUser(item.id)">删除</button>
</td>
</tr>
</tbody>
</table>
<!-- 添加和修改的彈出層開始 -->
<div style="display: none;padding: 20px" id="saveOrUpdateDiv">
<form class="layui-form">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">使用者id</label>
<div class="layui-input-inline">
<input type="text" v-model="user.id" placeholder="輸入使用者id" class="layui-input" readonly>
</div>
<label class="layui-form-label">使用者姓名</label>
<div class="layui-input-inline">
<input type="text" v-model="user.name" placeholder="請輸入姓名" class="layui-input">
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">性别</label>
<div class="layui-input-inline">
<input type="text" v-model="user.gender" placeholder="請輸入性别" class="layui-input">
</div>
<label class="layui-form-label">備注</label>
<div class="layui-input-inline">
<input type="text" v-model="user.remark" placeholder="請輸入備注" class="layui-input">
</div>
</div>
</div>
<div class="layui-form-item" style="text-align: center;">
<div class="layui-input-block">
<button type="button" class="layui-btn layui-btn-normal layui-btn-sm layui-icon layui-icon-release" v-if="!user.id" @click="addUser">新增</button>
<button type="button" class="layui-btn layui-btn-normal layui-btn-sm layui-icon layui-icon-release" v-else @click="editUser(user)">修改</button>
<button type="reset" class="layui-btn layui-btn-warm layui-btn-sm layui-icon layui-icon-refresh">重置</button>
</div>
</div>
</form>
</div>
<!-- 添加和修改的彈出層結束 -->
</div>
</body>
<script>
var mainIndex;
const vm = new Vue({
el: '#app',
data: {
userList: [], //使用者清單
data: [ //資料庫,存放使用者資料
{ id: 1, name: '張三', gender: 1, remark: '姓張名三' },
{ id: 2, name: '李四', gender: 2, remark: '姓李名四' },
{ id: 3, name: '王五', gender: 1, remark: '姓王名五' },
{ id: 4, name: '趙六', gender: 2, remark: '姓趙名六' }
],
user: {},
searchName: '' //搜尋用的名稱
},
filters: {
handlerGender(gender) {
if(gender == 1) {
return '男'
} else {
return '女'
}
}
},
methods: {
saveOrUpdateDiv(user) { //打開新增或者修改的彈出層
if(!user) {
title = '添加使用者';
//清空新增彈出層資料
this.user = {};
} else {
title = '編輯'+user.name+'資訊';
//回顯編輯的資料,注意不能直接 this.user = user;
this.user = { ...user };
//等價于this.user = {id: user.id, name: user.name,gender: user.gender,remark: user.remark}
}
mainIndex = layui.layer.open({
type: 1,
title: title,
content: layui.jquery("#saveOrUpdateDiv"),
area: ['700px', '250px'],
maxmin: true
});
},
getUserList(name) { //加載使用者資料
if(!name) {
name = '';
}
const dataList = this.data.filter(e => e.name.indexOf(name) >= 0);
this.userList = dataList;
},
addUser() { //添加使用者
const user = { ...this.user };
//等價于 const user = {id: this.user.id, name: this.user.name,gender: this.user.gender,remark: this.user.remark};
//随機生成id,範圍在1-100之間
user.id = Math.round(Math.random() * (100 - 1) + 1)
//添加到資料庫裡
this.data.push(user);
//關閉彈出層
layui.layer.close(mainIndex);
//重新加載資料
this.getUserList();
},
delUser(id) {
// 查到指定id所在數組索引下标
const index = this.userList.findIndex(e => e.id === id)
// 删除指定索引位置的資料
this.data.splice(index, 1)
// 删除成功後,重新家在資料
this.getUserList()
},
editUser(user){ //修改使用者
const index = this.data.findIndex(e => e.id === user.id);
this.data[index] = user;
//關閉彈出層
layui.layer.close(mainIndex);
//重新加載資料
this.getUserList();
},
searchUser() { // 搜尋使用者
// 周遊使用者,找到所有複合條件的使用者
this.getUserList(this.searchName)
}
},
created() {
// 進入頁面,元件建立之後,擷取資料
this.getUserList()
}
})
</script>
</html>
vue+layui增删改查
案例二: 本地模拟品牌管理的增删改查功能。 源碼:
<!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>品牌清單案例</title>
<!-- 引入bootstrap樣式-->
<link rel="stylesheet" href="lib/bootstrap.css">
<style>
body {
padding: 15px;
user-select: none;
}
</style>
</head>
<body>
<div id="app">
<!-- 卡片區域 -->
<div class="card">
<div class="card-header">
添加品牌
</div>
<div class="card-body">
<!-- 添加品牌的表單區域 -->
<!-- form 表單元素有 submit 事件 -->
<form @submit.prevent="add">
<div class="form-row align-items-center">
<div class="col-auto">
<div class="input-group mb-2">
<div class="input-group-prepend">
<div class="input-group-text">品牌名稱</div>
</div>
<input type="text" class="form-control" placeholder="請輸入品牌名稱" v-model.trim="brand">
</div>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary mb-2">添加</button>
</div>
</div>
</form>
</div>
</div>
<!-- 表格區域 -->
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">品牌名稱</th>
<th scope="col">狀态</th>
<th scope="col">建立時間</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item in list" :key="item.id">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>
<div class="custom-control custom-switch">
<!-- 使用 v-model 實作雙向資料綁定 -->
<input type="checkbox" class="custom-control-input" :id="'cb' + item.id" v-model="item.status">
<!-- 使用 v-if 結合 v-else 實作按需渲染 -->
<label class="custom-control-label" :for="'cb' + item.id" v-if="item.status">已啟用</label>
<label class="custom-control-label" :for="'cb' + item.id" v-else>已禁用</label>
</div>
</td>
<td>{{ item.time | dateFormat }}</td>
<td>
<a href="javascript:;" @click="remove(item.id)">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
<!-- 隻要導入了 dayjs 的庫檔案,在 window 全局,就可以使用 dayjs() 方法了 -->
<script src="./lib/dayjs.min.js"></script>
<script src="./lib/vue-2.6.12.js"></script>
<script>
// 聲明格式化時間的全局過濾器
Vue.filter('dateFormat', function(time) {
// 1. 對 time 進行格式化處理,得到 YYYY-MM-DD HH:mm:ss
// 2. 把 格式化的結果,return 出去
// 直接調用 dayjs() 得到的是目前時間
// dayjs(給定的日期時間) 得到指定的日期
const dtStr = dayjs(time).format('YYYY-MM-DD HH:mm:ss')
return dtStr
})
const vm = new Vue({
el: '#app',
data: {
// 使用者輸入的品牌名稱
brand: '',
// nextId 是下一個,可用的 id
nextId: 4,
// 品牌的清單資料
list: [
{ id: 1, name: '寶馬', status: true, time: new Date() },
{ id: 2, name: '奔馳', status: false, time: new Date() },
{ id: 3, name: '奧迪', status: true, time: new Date() },
],
},
methods: {
show(item){
console.info(item)
},
// 點選連結,删除對應的品牌資訊
remove(id) {
this.list = this.list.filter(item => item.id !== id)
},
// 阻止表單的預設送出行為之後,觸發 add 方法
add() {
// 如果判斷到 brand 的值為空字元串,則 return 出去
if(this.brand === '') return alert('必須填寫品牌名稱!')
// 如果沒有被 return 出去,應該執行添加的邏輯
// 1. 先把要添加的品牌對象,整理出來
const obj = {
id: this.nextId,
name: this.brand,
status: true,
time: new Date()
}
// 2. 往 this.list 數組中 push 步驟 1 中得到的對象
this.list.push(obj)
// 3. 清空 this.brand;讓 this.nextId 自增 +1
this.brand = ''
this.nextId++
}
},
})
</script>
</body>
</html>
vue+bootstrap增删改查