一、使用vue实现对数组的增删改查
提醒:绝对定位 + margin(例如position:fixed;top:0;right:0;bottom:0;left:0结合 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>学号</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">
<!-- 在修改界面中,不能修改学号 -->
<p>学号:<input type="text" v-model="student.no" :readonly="!isAdd"><span v-show="isNorepeat"
style="color: red;font-size: 14px;">学号重复</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数据形式有两种,一种是对象;还有一种是函数,返回一个对象。
data: {
// 定义一个学生数组
students: [
{
no: '1001',
name: '刘德华',
age: 40,
sex: '男'
},
{
no: '1002',
name: '蔡依林',
age: 22,
sex: '女'
},
{
no: '1003',
name: '张杰',
age: 30,
sex: '男'
}
],
// 是否显示编辑窗口
showadd: false,
// 学生对象
student: {
no: '',
name: '',
age: 0,
sex: ''
},
// 是否是添加状态
isAdd: true,
// 学号是否重复
isNorepeat: false,
// 表单内容是否为空
isnull: false
},
methods: {
// 添加学生方法
addstudent() {
// 将表单数据展开后,返回一个新的对象
let stu = { ...this.student }
// 验证学号是否重复
this.check(stu.no)
// 如果学号不重复并且表单内容不为空
if (!this.isNorepeat && !this.checknull()) {
// 将学生对象添加到学生数组中
this.students.push(stu)
// 调用清空表单数据的方法
this.clear()
}
},
// 清空表单数据的方法
clear() {
this.student = {
no:'',
name:'',
age:0,
sex:''
}
},·
// 关闭编辑窗口
close() {
this.showadd = false;
this.isAdd = true
this.clear()
},
// 根据学号查询学生对象
getOne(no) {
// 打开编辑窗口
this.showadd = true
// 编辑窗口是修改状态
this.isAdd = false
// 根据学号查询学生对象
let stu = this.students.find(s => s.no === no)
this.student = { ...stu }
},
//修改学生信息
updatestudent() {
// 根据学号,找到原始数组中指定的学生对象
let stu = this.students.find(s => s.no === this.student.no)
// 修改数组里面指定学生对象的属性
stu.name = this.student.name
stu.age = this.student.age
stu.sex = this.student.sex
},
// 删除学生
deleteStu(index) {
if (confirm('确定删除该学生吗?')) {
this.students.splice(index, 1)
}
},
// 学号的重复验证
check(no) {
let r = this.students.some(s => s.no === this.student.no)
if (r) {
this.isNorepeat = true
} else {
this.isNorepeat = false
}
},
// 表单内容是否为空的验证
checknull() {
if (!this.student.no) {
alert('学号不能为空');
} 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 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
1、beforeCreate 创建之前(数据初始化之前)
beforeCreate生命周期函数,一般在开发中很少使用,除非要设置Vue实例的内容。
在beforeCreate的时候,Vue实例身上的数据还没有初始化完成。
new Vue({
beforeCreate() {
// 设置Vue实例的内容时才需要用到该生命周期函数
this.__proto__.fn = function(){
alert('哈哈!')
}
//Vue实例,已经创建完成
console.log(this);
//Vue实例身上的数据还没有初始化完成
console.log(this.name+' '+this.age); // undefined undefined
}
})
2、created 数据初始化完成
(1)created生命周期函数
created生命周期函数,通常用于初始化Vue管理的数据,比如:发生ajax请求会放在这里。
在created阶段,数据初始化已经完成,数据已经和data属性进行了绑定。但是,在created方法中无法获取到对应的$el,也就是无法获取Dom。
(2)el选项和template选项
created方法执行完毕后进行的步骤:
① 判断对象中有没有el选项(el选项指定挂载的容器)
如果有el选项,继续执行判断是否有template选项;如果没有el选项,执行完created方法后就会停止整个生命周期的流程,直到执行了vm.$mount(el)。例如在下面的代码,将el选项去掉了,但是手动执行vm.$mount(el),也能够使暂停的生命周期进行下去。
② 判断在对象中是否有template选项
如果Vue实例对象中有template参数选项,则将其作为模板编译成render函数,来完成渲染。如果没有template参数选项,则将el指定的外部HTML作为模板编译。如果两种情况都不符合,则报错。
template参数:是一个字符串模板,作为VUE实例的标识使用,模板会替换Vue实例对象挂载的元素,挂载的元素内容会被忽略。
注意:Vue的编译实际上就是指Vue把模板编译成render函数的过程。当Vue选项对象中有render渲染函数时,Vue构造函数将直接使用渲染函数渲染DOM树;当选项对象中没有render渲染函数时,Vue构造函数首先通过将template模板编译生成渲染函数,然后再渲染DOM树;而当Vue选项对象中既没有render渲染函数,也没有template模板时,会通过el属性获取挂载元素的outerHTML来作为模板,并编译生成渲染函数。换言之,在进行DOM树的渲染时,render渲染函数的优先级最高,template次之且需编译成渲染函数,而挂载点el属性对应的元素若存在,则在前两者均不存在时,其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生命周期函数,一般在开发中很少使用。
在beforeMount阶段,模板成功渲染(编译模板,把data里面的数据和模板生成html,完成了el和data初始化),但是内容还没有挂载到页面,此时页面是模板。
beforeMount() {
// 可以获取$el内容
console.log(this.$el);
// 可以修改数据,但是内容没有挂载到页面,并且后续内容会被真正的数据替换掉。
document.querySelector('#name').innerHTML = "哈哈"
}
4、mounted 挂载完成
mounted生命周期函数,通常用于对DOM的重新改动。
mounted() {
// 可以获取$el内容
console.log(this.$el);
// 可以修改数据,并成功渲染到页面
document.querySelector('#name').innerHTML = "呵呵"
}
5、beforeUpdate 数据更新之前
在beforeUpdate阶段,数据已经发生了变化,但是页面还没有重新渲染。
<div id="app">
<h2 id="name">{{name}}</h2>
<h2 id="age">{{age}}</h2>
<div>
<!-- 点击按钮修改name、age数据 -->
<button @click="name='李四'">修改姓名</button>
<button @click="age=30">修改年龄</button>
</div>
</div>
beforeUpdate() {
console.log(this.name+' '+this.age);
console.log(this.$el);
},
6、updated 数据更新完成
在updated阶段,数据已经发生变化,页面也已经重新渲染。
<div id="app">
<h2 id="name">{{name}}</h2>
<h2 id="age">{{age}}</h2>
<div>
<!-- 点击按钮修改name、age数据 -->
<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生命周期函数,在开发中使用频率会高一点。
在beforeDestroy阶段,对数据做任何的修改,都不会重新渲染到页面。该阶段,实例仍然完全可用,我们通常会在这个生命周期函数中做一些收尾的工作。 比如:停掉开启的定时器,初始化一些数据等等。
注意:销毁后,当前Vue实例对象还在,只是该对象不能在重新挂载页面了。
<div id="app">
<h2 id="name">{{name}}</h2>
<h2 id="age">{{age}}</h2>
<div>
<!-- 点击按钮调用销毁Vue实例的方法 -->
<button @click="destroy">不过了</button>
</div>
</div>
methods: {
destroy(){
// 调用销毁当前Vue实例的方法
this.$destroy()
}
},
beforeDestroy() {
console.log(this);
this.name = '王五'
}
8、destroyed 销毁完成
destroyed生命周期函数,几乎不用。
在destroyed阶段,所有的事件监听器会被移出,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用。
<div id="app">
<h2 id="name">{{name}}</h2>
<h2 id="age">{{age}}</h2>
<div>
<!-- 点击按钮调用销毁Vue实例的方法 -->
<button @click="destroy">不过了</button>
</div>
</div>
methods: {
destroy(){
// 调用销毁当前Vue实例的方法
this.$destroy()
}
},
destroyed() {
console.log(this);
this.name = '王五'
}