目录
- 一、自定义指令v-mycolor
- 二、使用钩子函数的自定义指令
- 三、Vue实现简单的学生信息管理系统
除了核心功能默认内置的指令,Vue.js允许注册自定义指令。添加一个自定义指令,有两种方式:
(1)通过Vue.directive()函数注册一个全局的指令
(2)通过组件directives属性,对该组件添加一个局部的指令
一、自定义指令v-mycolor
示例:
<div id="root"> | |
<div v-mycolor="color" id="demo"> | |
{{hello}} | |
</div> | |
</div> | |
<script> | |
Vue.config.productionTip = false; | |
Vue.directive('mycolor', function(el, binding, vnode) { | |
el.style = 'color:' + binding.value; | |
}); | |
const vm = new Vue({ | |
el: '#root', | |
data: { | |
hello:"你好", | |
color:'red' | |
}, | |
methods: { | |
} | |
}) | |
</script> |
执行结果:
通过以上示例,可以看到网页上的"你好"是红色,说明自定义指令起到了作用。
在自定义指令中,可以传递是三个参数:
el:指令所绑定的元素,可以用来直接操作DOM。
binding:一个对象,包含指令的很多信息。
vnode:Vue.js编译生成的虚拟节点。
自定义指令生命周期:
(1)bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个绑定时执行一次的初始化动作
(2)nserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在与document中)。
(3)update:被绑定于元素所在的模板更新时调用,而无论绑定至是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。
(4)componentUpdated:被绑定元素所在模板完成一次更新周期时调用。
(5)unbind:只调用一次,指令与元素解绑时调用
二、使用钩子函数的自定义指令
钩子函数的参数如下所示:
el:与上面介绍的一样,el是指令所绑定的元素,可以用来直接操作DOM;
示例:
<div id="root"> | |
<div v-mycolor="color" id="demo"> | |
{{num}} | |
</div> | |
<div> | |
<button @click="add">Add</button> | |
</div> | |
</div> | |
<script> | |
Vue.config.productionTip = false; | |
Vue.directive('mycolor',{ | |
bind:function(){ | |
console.log('1-绑定时调用bind'); | |
}, | |
inserted:function(el,binding,vnode){ | |
alert('绑定到节点时调用inserted'); | |
console.log('2-绑定到节点时调用inserted'); | |
el.style='color:'+binding.value; | |
}, | |
update:function(el,binding,vnode){ | |
alert('3-组件更新时调用update'); | |
console.log('3-组件更新时调用update'); | |
el.style='color:green'; | |
}, | |
componentUpdated:function(){ | |
console.log('4-组件更新完成时调用componentUpdated'); | |
} | |
}) | |
const vm = new Vue({ | |
el: '#root', | |
data: { | |
num:10, | |
color:'red' | |
}, | |
methods: { | |
add:function(){ | |
this.num++; | |
} | |
} | |
}) | |
</script> |
执行结果:
运行后,浏览器会弹出"绑定到节点时调用inserted",这时文字的颜色会变成红色,且浏览器的控制中输出:
当点击"Add"按钮时,浏览器会弹出"3-组件更新时调用update",这时文字会由"10"变成11,字体颜色会变成绿色:
三、Vue实现简单的学生信息管理系统
实现学生信息的增删改查和分页功能,及按照学生年龄进行降序排序,升序排序和原顺序
全部源代码:
<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>Document</title> | |
<script src="../../vue-2.7.14.js"></script> | |
<style> | |
* { | |
margin: 0px; | |
padding: 0px; | |
} | |
#root { | |
margin: 0px auto; | |
width: 900px; | |
height: auto; | |
background-color: orange; | |
} | |
div { | |
margin: 0px auto; | |
border: 2px solid black; | |
width: 98%; | |
text-align: center; | |
padding-top: 10px; | |
padding-bottom: 10px; | |
} | |
table { | |
width: 98%; | |
margin: 1px auto; | |
border: 2px solid black; | |
border-collapse: collapse; | |
} | |
th, | |
td { | |
border: 2px solid black; | |
padding: 5px; | |
} | |
label { | |
margin-left: 10px; | |
} | |
input { | |
height: 30px; | |
} | |
button { | |
width: 100px; | |
height: 30px; | |
} | |
span { | |
margin-left: 50px; | |
margin-right: 50px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="root"> | |
<div> | |
<h2>学生信息管理系统</h2> | |
<div> | |
<h2>添加信息</h2><br> | |
<div> | |
<input type="text" placeholder="请输入学号" v-model="id"> | |
<input type="text" placeholder="请输入姓名" v-model="name"> | |
<input type="text" placeholder="请输入性别" v-model="sex"> | |
<input type="text" placeholder="请输入年龄" v-model="age"> | |
<button v-on:click="add">提交</button> | |
</div><br> | |
<div> | |
<h2>查询信息</h2><br> | |
<input type="text" placeholder="请输入要查询的姓名" v-model.lazy="keyword"> | |
<button @click="search()">查询</button> | |
</div> | |
</div><br> | |
<div> | |
<table> | |
<tr> | |
<th>序号</th> | |
<th>学号</th> | |
<th>姓名</th> | |
<th>性别</th> | |
<th>年龄</th> | |
<th>创建时间</th> | |
<th>操作</th> | |
</tr> | |
<tr v-for="(student,index) in dataShow" :key="student.id"> | |
<td>{{index+1}}</td> | |
<td>{{student.id}}</td> | |
<td>{{student.name}}</td> | |
<td>{{student.sex}}</td> | |
<td>{{student.age}}</td> | |
<td>{{student.ctime | newTime}}</td> | |
<td> | |
<button @click.prevent='toEdit(student.id)'>修改</button> | |
<button @click.prevent="del(index)">删除</button> | |
</td> | |
</tr> | |
<tr> | |
<td align="right" colspan="7">共计 {{count}} 人</td> | |
</tr> | |
</table> | |
</div><br> | |
<div> | |
<select v-model="pageSize" v-on:change="changePageSize"> | |
<option value="5">5页</option> | |
<option value="10">10页</option> | |
<option value="15">15页</option> | |
<option value="20">20页</option> | |
</select> | |
<button v-on:click="firstPage" :disabled="currentPage === 1">首页</button> | |
<button v-on:click="previousPage" :disabled="currentPage === 1">上一页</button> | |
<button v-on:click="nextPage" :disabled="currentPage === totalPages">下一页</button> | |
<button v-on:click="lastPage" :disabled="currentPage === totalPages">尾页</button> | |
<span>当前是第{{ currentPage }}页 / 总共{{ totalPages }}页</span> | |
</div> | |
<br> | |
<div v-show="flag"> | |
<h2>修改信息</h2> | |
<br><br> | |
<label>学号:<input type="text" placeholder="请输入学号" v-model="id2"></label> | |
<label>姓名:<input type="text" placeholder="请输入姓名" v-model="name2"></label> | |
<br><br> | |
<label>性别:<input type="text" placeholder="请输入性别" v-model="sex2"></label> | |
<label>年龄:<input type="text" placeholder="请输入年龄" v-model="age2"></label> | |
<br><br> | |
<button @click="add2(editIndex)">保存</button> | |
</div> | |
<div> | |
<span><button style="width: 150px;" v-on:click="sortType=2">按年龄升序</button></span> | |
<span><button style="width: 150px;" v-on:click="sortType=1">按年龄降序</button></span> | |
<span><button style="width: 150px;" v-on:click="sortType=0">原顺序</button></span> | |
</div> | |
</div> | |
</div> | |
<script> | |
Vue.config.productionTip = false; | |
Vue.filter("newTime", (value) => { | |
year = value.getFullYear(); | |
month = value.getMonth() + 1; | |
day = value.getDate(); | |
return `${year}年${month}月${day}日`; | |
// return year + "年" + month + "月" + day + "日" | |
}) | |
const vm = new Vue({ | |
el: '#root', | |
data: { | |
flag: false,//true表示修改窗口展开,false表示窗口关闭 | |
id: "", | |
name: "", | |
sex: "", | |
age: "", | |
id2: "", | |
name2: "", | |
sex2: "", | |
age2: "", | |
keyword: "", | |
time: "", | |
sortType: 0,//0表示原顺序,1表示降序,2表示升序 | |
editIndex: null, // 保存正在编辑的对象的索引,初始值不能为0及0以上的数 | |
students: [ | |
{ id: "00001", name: "张三", sex: "男", age: 20, ctime: new Date() }, | |
{ id: "00002", name: "李四", sex: "女", age: 19, ctime: new Date() }, | |
{ id: "00003", name: "王五", sex: "男", age: 18, ctime: new Date() }, | |
{ id: "00004", name: "赵六", sex: "男", age: 19, ctime: new Date() }, | |
{ id: "00005", name: "李力", sex: "男", age: 21, ctime: new Date() }, | |
{ id: "00006", name: "二狗", sex: "男", age: 17, ctime: new Date() }, | |
{ id: "00007", name: "狗蛋", sex: "女", age: 20, ctime: new Date() }, | |
{ id: "00008", name: "三炮", sex: "男", age: 19, ctime: new Date() }, | |
{ id: "00009", name: "刘仁", sex: "女", age: 19, ctime: new Date() }, | |
{ id: "00010", name: "四儿", sex: "男", age: 22, ctime: new Date() } | |
], | |
newStudents: [], | |
currentPage: 1,//当前页数,默认为1 | |
pageSize: 5,//每页显示数量 | |
}, | |
computed: { | |
//计算有几组学生信息 | |
count() { | |
return this.fillPersons.length; | |
}, | |
dataShow() { | |
let start = (this.currentPage - 1) * this.pageSize; | |
let end = Math.min((this.currentPage) * this.pageSize, this.count); | |
return this.fillPersons.slice(start, end); | |
}, | |
//计算总页数 | |
totalPages() { | |
return Math.ceil(this.count / this.pageSize) || 1; | |
}, | |
//对学生信息进行排序 | |
fillPersons() { | |
// 找到第一个满足条件的元素就终止过滤操作 | |
const arr = this.students.filter((p) => { | |
return p.name.indexOf(this.keyword) !== -1; | |
}); | |
//对学生信息进行升序降序和原顺序排序 | |
if (this.sortType) { | |
arr.sort((p1, p2) => { | |
return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age; | |
}); | |
} | |
return arr; | |
} | |
}, | |
methods: { | |
//更改每页显示的记录数时更新当前页码,以确保在更改每页记录数后, | |
// 用户仍然可以看到正确的记录列表。 | |
changePageSize() { | |
this.currentPage = 1; | |
}, | |
//首页 | |
firstPage() { | |
this.currentPage = 1; | |
}, | |
//上一页 | |
previousPage() { | |
this.currentPage -= 1; | |
}, | |
//下一页 | |
nextPage() { | |
this.currentPage += 1; | |
}, | |
//尾页 | |
lastPage() { | |
this.currentPage = this.totalPages; | |
}, | |
//添加操作 | |
add() { | |
//添加进对应的学生信息 | |
this.students.push({ | |
id: this.id, | |
name: this.name, | |
sex: this.sex, | |
age: this.age, | |
ctime: new Date() | |
}); | |
//重新赋空值 | |
this.id = "", | |
this.name = "", | |
this.sex = "", | |
this.age = "" | |
}, | |
//删除操作 | |
del(index) { | |
//根据下标删除对应的学生信息 | |
this.students.splice(index, 1); | |
}, | |
//查询操作 | |
search() { | |
//判断是否输入查询内容 | |
if (this.keyword) { | |
// this.students = this.newStudents; | |
//找到满足条件的元素并赋值 | |
var list = this.students.filter(item => item.name.indexOf(this.keyword) > -1); | |
if (list.length != 0) { | |
alert("查询成功"); | |
this.students = list; | |
} else { | |
alert("查询失败"); | |
this.students = []; | |
} | |
this.keyword = '' | |
} else { | |
alert("请输入要查找的姓名"); | |
} | |
}, | |
// 修改操作 | |
toEdit(id) { | |
//定位索引 | |
this.editIndex = id; | |
// flag 调成 true,调出修改操作窗口 | |
this.flag = true; | |
// filter 操作:找到第一个满足条件的元素就终止过滤操作 | |
let student = this.students.filter(stu => { | |
// 注意:此时的返回值 student 是一个对象 | |
return stu.id == id; | |
}); | |
// 此时在文本框中显示的是:已经选中的学生信息 | |
this.id2 = student[0].id; | |
this.name2 = student[0].name; | |
this.sex2 = student[0].sex; | |
this.age2 = student[0].age; | |
}, | |
// 修改保存操作 | |
add2(editIndex) { | |
// flag 调成 false,就表示是关闭修改操作窗口 | |
this.flag = false; | |
//查找需要修改的的下标 | |
var index = this.students.findIndex((item) => { | |
if (item.id == this.editIndex) { | |
return true; | |
} | |
}) | |
//删除对应下标的学生信息 | |
this.students.splice(index, 1); | |
// //把最最新的学生信息重新添加 | |
this.students.push({ | |
id: this.id2, | |
name: this.name2, | |
sex: this.sex2, | |
age: this.age2, | |
ctime: new Date() | |
}); | |
// //重新赋空值 | |
this.id2 = "", | |
this.name2 = "", | |
this.sex2 = "", | |
this.age2 = "" | |
}, | |
} | |
}) | |
</script> | |
</body> | |
</html> |
执行结果:
上图只展示了主界面,其他功能请自行复制粘贴到vscode中执行修改!