一、使用vue實現(xiàn)對數(shù)組的增刪改查
提醒:絕對定位 + margin(例如position:fixed;top:0;right:0;bottom:0;left:0結(jié)合 margin:auto),可以讓明確寬高的盒子垂直居中在窗口中。
css樣式:
<style>
table {
border-collapse: collapse;
}
th,td {
padding: 2px 15px;
border: 1px solid #ccc;
text-align: center;
}
#edit{
border: 1px solid #eee;
width: 300px;
height: 220px;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
padding: 10px;
}
#edit .close {
position: absolute;
right: 10px;
top: 10px;
background-color: red;
width: 30px;
height: 30px;
border-radius: 50%;
text-align: center;
line-height: 30px;
color: white;
cursor: pointer;
}
</style>
html部分:
<div id="app">
<button @click="showadd=true">添加</button>
<hr>
<table>
<thead>
<tr>
<td>學(xué)號</td>
<td>姓名</td>
<td>年齡</td>
<td>性別</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in students" :key="index">
<td>{{item.no}}</td>
<td>{{item.name}}</td>
<td>{{item.age}}</td>
<td>{{item.sex}}</td>
<td>
<button @click="getOne(item.no)">修改</button>
<button @click="deleteStu(index)">刪除</button>
</td>
</tr>
</tbody>
</table>
<div id="edit" v-show="showadd">
<!-- 在修改界面中,不能修改學(xué)號 -->
<p>學(xué)號:<input type="text" v-model="student.no" :readonly="!isAdd"><span v-show="isNorepeat"
style="color: red;font-size: 14px;">學(xué)號重復(fù)</span></p>
<p>姓名:<input type="text" v-model="student.name"></p>
<p>年齡:<input type="text" v-model="student.age"></p>
<p>性別:<input type="text" v-model="student.sex"></p>
<p>
<button v-if="isAdd" @click="addstudent">添加</button>
<button v-else @click="updatestudent">修改</button>
<button @click="clear">取消</button>
</p>
<div class="close" @click="close">X</div>
</div>
</div>
vue:
<script>
new Vue({
el: "#app",
// data數(shù)據(jù)形式有兩種,一種是對象;還有一種是函數(shù),返回一個對象。
data: {
// 定義一個學(xué)生數(shù)組
students: [
{
no: '1001',
name: '劉德華',
age: 40,
sex: '男'
},
{
no: '1002',
name: '蔡依林',
age: 22,
sex: '女'
},
{
no: '1003',
name: '張杰',
age: 30,
sex: '男'
}
],
// 是否顯示編輯窗口
showadd: false,
// 學(xué)生對象
student: {
no: '',
name: '',
age: 0,
sex: ''
},
// 是否是添加狀態(tài)
isAdd: true,
// 學(xué)號是否重復(fù)
isNorepeat: false,
// 表單內(nèi)容是否為空
isnull: false
},
methods: {
// 添加學(xué)生方法
addstudent() {
// 將表單數(shù)據(jù)展開后,返回一個新的對象
let stu = { ...this.student }
// 驗證學(xué)號是否重復(fù)
this.check(stu.no)
// 如果學(xué)號不重復(fù)并且表單內(nèi)容不為空
if (!this.isNorepeat && !this.checknull()) {
// 將學(xué)生對象添加到學(xué)生數(shù)組中
this.students.push(stu)
// 調(diào)用清空表單數(shù)據(jù)的方法
this.clear()
}
},
// 清空表單數(shù)據(jù)的方法
clear() {
this.student = {
no:'',
name:'',
age:0,
sex:''
}
},·
// 關(guān)閉編輯窗口
close() {
this.showadd = false;
this.isAdd = true
this.clear()
},
// 根據(jù)學(xué)號查詢學(xué)生對象
getOne(no) {
// 打開編輯窗口
this.showadd = true
// 編輯窗口是修改狀態(tài)
this.isAdd = false
// 根據(jù)學(xué)號查詢學(xué)生對象
let stu = this.students.find(s => s.no === no)
this.student = { ...stu }
},
//修改學(xué)生信息
updatestudent() {
// 根據(jù)學(xué)號,找到原始數(shù)組中指定的學(xué)生對象
let stu = this.students.find(s => s.no === this.student.no)
// 修改數(shù)組里面指定學(xué)生對象的屬性
stu.name = this.student.name
stu.age = this.student.age
stu.sex = this.student.sex
},
// 刪除學(xué)生
deleteStu(index) {
if (confirm('確定刪除該學(xué)生嗎?')) {
this.students.splice(index, 1)
}
},
// 學(xué)號的重復(fù)驗證
check(no) {
let r = this.students.some(s => s.no === this.student.no)
if (r) {
this.isNorepeat = true
} else {
this.isNorepeat = false
}
},
// 表單內(nèi)容是否為空的驗證
checknull() {
if (!this.student.no) {
alert('學(xué)號不能為空');
} else if (!this.student.name) {
alert('姓名不能為空');
} else if (this.student.age == 0) {
alert('年齡不能為空');
} else if (!this.student.sex) {
alert('性別不能為空');
} else {
return false;
}
return true
}
},
})
</script>
二、vue的生命周期
每個 Vue 實例在被創(chuàng)建時都要經(jīng)過一系列的初始化過程——例如,需要設(shè)置數(shù)據(jù)監(jiān)聽、編譯模板、將實例掛載到 DOM 并在數(shù)據(jù)變化時更新 DOM 等。同時在這個過程中也會運行一些叫做生命周期鉤子的函數(shù),這給了用戶在不同階段添加自己的代碼的機會。

1、beforeCreate 創(chuàng)建之前(數(shù)據(jù)初始化之前)
beforeCreate生命周期函數(shù),一般在開發(fā)中很少使用,除非要設(shè)置Vue實例的內(nèi)容。
在beforeCreate的時候,Vue實例身上的數(shù)據(jù)還沒有初始化完成。
new Vue({
beforeCreate() {
// 設(shè)置Vue實例的內(nèi)容時才需要用到該生命周期函數(shù)
this.__proto__.fn = function(){
alert('哈哈!')
}
//Vue實例,已經(jīng)創(chuàng)建完成
console.log(this);
//Vue實例身上的數(shù)據(jù)還沒有初始化完成
console.log(this.name+' '+this.age); // undefined undefined
}
})
2、created 數(shù)據(jù)初始化完成
(1)created生命周期函數(shù)
created生命周期函數(shù),通常用于初始化Vue管理的數(shù)據(jù),比如:發(fā)生ajax請求會放在這里。
在created階段,數(shù)據(jù)初始化已經(jīng)完成,數(shù)據(jù)已經(jīng)和data屬性進行了綁定。但是,在created方法中無法獲取到對應(yīng)的$el,也就是無法獲取Dom。
(2)el選項和template選項
created方法執(zhí)行完畢后進行的步驟:
① 判斷對象中有沒有el選項(el選項指定掛載的容器)
如果有el選項,繼續(xù)執(zhí)行判斷是否有template選項;如果沒有el選項,執(zhí)行完created方法后就會停止整個生命周期的流程,直到執(zhí)行了vm.$mount(el)。例如在下面的代碼,將el選項去掉了,但是手動執(zhí)行vm.$mount(el),也能夠使暫停的生命周期進行下去。
② 判斷在對象中是否有template選項
如果Vue實例對象中有template參數(shù)選項,則將其作為模板編譯成render函數(shù),來完成渲染。如果沒有template參數(shù)選項,則將el指定的外部HTML作為模板編譯。如果兩種情況都不符合,則報錯。
template參數(shù):是一個字符串模板,作為VUE實例的標識使用,模板會替換Vue實例對象掛載的元素,掛載的元素內(nèi)容會被忽略。
注意:Vue的編譯實際上就是指Vue把模板編譯成render函數(shù)的過程。當Vue選項對象中有render渲染函數(shù)時,Vue構(gòu)造函數(shù)將直接使用渲染函數(shù)渲染DOM樹;當選項對象中沒有render渲染函數(shù)時,Vue構(gòu)造函數(shù)首先通過將template模板編譯生成渲染函數(shù),然后再渲染DOM樹;而當Vue選項對象中既沒有render渲染函數(shù),也沒有template模板時,會通過el屬性獲取掛載元素的outerHTML來作為模板,并編譯生成渲染函數(shù)。換言之,在進行DOM樹的渲染時,render渲染函數(shù)的優(yōu)先級最高,template次之且需編譯成渲染函數(shù),而掛載點el屬性對應(yīng)的元素若存在,則在前兩者均不存在時,其outerHTML才會用于編譯與渲染。
<div id="app">
</div>
new Vue({
// 指定掛載的容器
// el: "#app",
// 指定模板(如果有模板,vue會渲染整個模板;如果沒有模板)
// template:"<div><h2>{{name}}</h2><h2>{{age}}</h2></div>",
created() {
console.log(this)
console.log(this.$el); // undefined
console.log(this.name + ' ' + this.age) // 張三, 20
}
})
setTimeout(() => {
// 通過vue實例的$mount方法,手動掛載容器
// 通過el選項指定掛載容器,當模板渲染成功后,會立刻掛載頁面
// $mount方法的好處是,可以自行選擇掛載的時機。
vm.$mount('#app')
}, 1000);
3、beforeMount 掛載之前
beforeMount生命周期函數(shù),一般在開發(fā)中很少使用。
在beforeMount階段,模板成功渲染(編譯模板,把data里面的數(shù)據(jù)和模板生成html,完成了el和data初始化),但是內(nèi)容還沒有掛載到頁面,此時頁面是模板。
beforeMount() {
// 可以獲取$el內(nèi)容
console.log(this.$el);
// 可以修改數(shù)據(jù),但是內(nèi)容沒有掛載到頁面,并且后續(xù)內(nèi)容會被真正的數(shù)據(jù)替換掉。
document.querySelector('#name').innerHTML = "哈哈"
}
4、mounted 掛載完成
mounted生命周期函數(shù),通常用于對DOM的重新改動。
mounted() {
// 可以獲取$el內(nèi)容
console.log(this.$el);
// 可以修改數(shù)據(jù),并成功渲染到頁面
document.querySelector('#name').innerHTML = "呵呵"
}
5、beforeUpdate 數(shù)據(jù)更新之前
在beforeUpdate階段,數(shù)據(jù)已經(jīng)發(fā)生了變化,但是頁面還沒有重新渲染。
<div id="app">
<h2 id="name">{{name}}</h2>
<h2 id="age">{{age}}</h2>
<div>
<!-- 點擊按鈕修改name、age數(shù)據(jù) -->
<button @click="name='李四'">修改姓名</button>
<button @click="age=30">修改年齡</button>
</div>
</div>
beforeUpdate() {
console.log(this.name+' '+this.age);
console.log(this.$el);
},
6、updated 數(shù)據(jù)更新完成
在updated階段,數(shù)據(jù)已經(jīng)發(fā)生變化,頁面也已經(jīng)重新渲染。
<div id="app">
<h2 id="name">{{name}}</h2>
<h2 id="age">{{age}}</h2>
<div>
<!-- 點擊按鈕修改name、age數(shù)據(jù) -->
<button @click="name='李四'">修改姓名</button>
<button @click="age=30">修改年齡</button>
</div>
</div>
updated() {
console.log(this.name+' '+this.age);
console.log(this.$el);
},
7、beforeDestroy 銷毀之前
beforeDestroy生命周期函數(shù),在開發(fā)中使用頻率會高一點。
在beforeDestroy階段,對數(shù)據(jù)做任何的修改,都不會重新渲染到頁面。該階段,實例仍然完全可用,我們通常會在這個生命周期函數(shù)中做一些收尾的工作。 比如:停掉開啟的定時器,初始化一些數(shù)據(jù)等等。
注意:銷毀后,當前Vue實例對象還在,只是該對象不能在重新掛載頁面了。
<div id="app">
<h2 id="name">{{name}}</h2>
<h2 id="age">{{age}}</h2>
<div>
<!-- 點擊按鈕調(diào)用銷毀Vue實例的方法 -->
<button @click="destroy">不過了</button>
</div>
</div>
methods: {
destroy(){
// 調(diào)用銷毀當前Vue實例的方法
this.$destroy()
}
},
beforeDestroy() {
console.log(this);
this.name = '王五'
}
8、destroyed 銷毀完成
destroyed生命周期函數(shù),幾乎不用。
在destroyed階段,所有的事件監(jiān)聽器會被移出,所有的子實例也會被銷毀,該鉤子在服務(wù)器端渲染期間不被調(diào)用。
<div id="app">
<h2 id="name">{{name}}</h2>
<h2 id="age">{{age}}</h2>
<div>
<!-- 點擊按鈕調(diào)用銷毀Vue實例的方法 -->
<button @click="destroy">不過了</button>
</div>
</div>
methods: {
destroy(){
// 調(diào)用銷毀當前Vue實例的方法
this.$destroy()
}
},
destroyed() {
console.log(this);
this.name = '王五'
}