过滤器
自定义全局过滤器
全局过滤器的基本使用
使用全局方法Vue.filter()
自定义一个全局过滤器。
每一个Vue对象实例(每一个VM实例)都可以拿到这个过滤器。它接收两个参数:过滤器的名称、过滤器函数
- 在插值表达式中使用
<p>{{msg | msgFormat}}</p>
管道符前面的msg即为要过滤的文本内容)
管道符后面的msgFormat即为过滤器
Linux管道符(管道操作符):可以把一个命令的标准输出传送到另一个命令的标准输入中,连续的
|
意味着第一个命令的输出为第二命令的输入,第二个命令的输入为第一个命令的输出,第二个命令的输出为第三个命令的输入…以此类推
- 定义过滤器
// Vue.filter 中的第一个参数是过滤器的名称,第二个参数是具体的过滤器函数
// 定义一个 Vue 全局的过滤器,名字叫做 msgFormat
Vue.filter('msgFormat', function (myMsg) { // function 的第一个参数指的是管道符前面的 msg
// 字符串的 replace 方法,第一个参数,除了可写一个 字符串之外,还可以定义一个正则
// 这里是将msg中所有的单纯替换为邪恶
return myMsg.replace(/单纯/g, '邪恶')
})
Vue.filter('名称', 函数)
其中第一个参数指的过滤器的名称(必须与管道符后的名称完全一致),第二个参数为过滤器函数- 过滤器函数function中,第一个参数指管道符前面的msg
String.prototype.replace()
该方法用于替换匹配的字符串,一般情况下只替换第一个匹配(除非使用带有g
的正则表达式)
示例代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="../code/lib/vue.js"></script>
</head>
<body>
<div id="app">
<p>{{ msg }}</p>
<p>{{ msg | msgFormat }}</p>
</div>
<script>
// 定义一个 Vue全局的过滤器,名字叫做 msgFormat
// 所谓的全局过滤器,就是所有的VM实例都共享的
Vue.filter ('msgFormat', function(msg) {
return msg.replace(/单纯/g, '邪恶')
})
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: '曾经,我也是一个单纯的少年,单纯的我,傻傻的问,谁是世界上最单纯的男人'
},
methods: {}
});
</script>
</body>
</html>
示例效果:
给过滤器添加一个或多个参数
过滤器加一个参数
将msg中的单纯替换为xxx变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="vue2.5.16.js"></script>
</head>
<body>
<div id="app">
<!-- 通过过滤器 msgFormat 对 msg 进行过滤。括号里的参数代表 function中的 arg2-->
<p>{{ msg | msgFormat('牛bee') }}</p>
</div>
<script>
// 定义一个 Vue全局的过滤器,名字叫做 msgFormat
// 所谓的全局过滤器,就是所有的VM实例都共享的
Vue.filter('msgFormat', function (msg, arg2) {
// 字符串的 replace 方法:第一个参数,除了可写一个 字符串之外,还可以定义一个正则;第二个参数代表要替换为上面的xxx
//将 myMsg 中的所有`单纯`字样,修改为 arg2
return msg.replace(/单纯/g, arg2)
})
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: '曾经,我也是一个单纯的少年,单纯的我,傻傻的问,谁是世界上最单纯的男人'
},
methods: {}
});
</script>
</body>
</html>
过滤器加两个参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="vue2.5.16.js"></script>
</head>
<body>
<div id="app">
<!-- 通过 过滤器 msgFormat 对 msg 进行过滤-->
<!-- 括号里的第一个参数代表 function 中的 arg2,括号里的第二个参数代表 function 中的 arg3-->
<p>{{ msg | msgFormat('niubee', '+++') }}</p>
</div>
<script>
// 定义一个 Vue全局的过滤器,名字叫做 msgFormat
// 所谓的全局过滤器,就是所有的VM实例都共享的
Vue.filter('msgFormat', function (myMsg, arg2, arg3) {
// 字符串的 replace 方法:第一个参数,除了可写一个 字符串之外,还可以定义一个正则;第二个参数代表要替换为 xxx
//将 myMsg 中的所有`单纯`字样,修改为`arg2 + arg3`
return myMsg.replace(/单纯/g, arg2 + arg3)
})
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: '曾经,我也是一个单纯的少年,单纯的我,傻傻的问,谁是世界上最单纯的男人'
},
methods: {}
});
</script>
</body>
</html>
同时使用多个过滤器
添加多个过滤器的实现思路:将msg交给第一个过滤器来处理,然后将处理后的结果交给第二个处理器来处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="../../code/lib/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 通过 两个过滤器(msgFormat、myFilter2)对 msg 进行过滤-->
<!-- 将 msg 交给第一个过滤器来处理,然后将处理的结果交给第二个过滤器来处理-->
<p>{{ msg }}</p>
<p>{{ msg | msgFormat('niubee', '+++') | myFilter2}}</p>
</div>
<script>
// 定义一个 Vue 全局的过滤器,名字叫做 msgFormat
Vue.filter('msgFormat', function (myMsg, arg2, arg3) {
// 字符串的 replace 方法:第一个参数,除了可写一个 字符串之外,还可以定义一个正则;第二个参数代表要替换为 xxx
//将 myMsg 中的所有`单纯`字样,修改为`arg2 + arg3`
return myMsg.replace(/单纯/g, arg2 + arg3)
})
//定义第二个全局过滤器
Vue.filter('myFilter2', function (myMsg) {
//在字符串 msg 的最后面加上【后缀】
return myMsg + '[--第二个过滤器--]'
})
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: '曾经,我也是一个单纯的少年,单纯的我,傻傻的问,谁是世界上最单纯的男人'
},
methods: {}
});
</script>
</body>
</html>
示例1:时间格式化
使用ES6新增的字符串方法
String.prototype.padStart(maxLength, fillString='')
或String.prototype.padEnd(maxLength, fillString='')
来填充字符串。pad
即补充
.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="../../code/lib/vue.js"></script>
</head>
<body>
<div id="app">
{{ time }}
<br/>
{{ time | dataFormat }}
<br>
{{ time | dataFormat('yyyy-mm-dd') }}
</div>
<div id="app1">
<br>
{{ time | dataFormat }}
</div>
</body>
<script>
// 定义一个名称为 datafmt的全局过滤器
// pattern需要指定默认值 防止调用toLowerCase报错
Vue.filter('dataFormat', function (input, pattern="") {
// 过滤器的逻辑:将input的值格式化成 yyyy-MM-dd 字符串输出
var dt = new Date(input)
// yyyy-mm-dd
var y = dt.getFullYear()
var m = (dt.getMonth() + 1).toString().padStart(2,'0')
var d = dt.getDate().toString().padStart(2,'0')
// 如果调用过滤器的参数写的是 yyyy-mm-dd,那就按照 yyyy-mm-dd 的这种格式写
if(pattern.toLowerCase() === 'yyyy-mm-dd') {
return `${y}-${m}-${d}`
} else {
var hh = dt.getHours().toString().padStart(2,'0')
var mm = dt.getMinutes().toString().padStart(2,'0')
var ss = dt.getSeconds().toString().padStart(2,'0')
return `${y}-${m}-${d} ${hh}:${mm}:${ss} ~~`
}
});
new Vue({
el: '#app',
data: {
time: new Date()
}
})
new Vue({
el: '#app1',
data: {
time: new Date()
}
});
</script>
</html>
pattern
参数:
在做if(pattern && pattern.toLowerCase() === 'yyyy-mm-dd')
判断时,逻辑上是先保证pattern参数穿进来了,然后再继续后面的判断
如果写成了if(pattern.toLowerCase() === 'yyyy-mm-dd')
则可能在调用的时候不传入pattern参数从而造成错误。此时if语句相当于if(undefined.toLowerCase() === 'yyyy-mm-dd')
举例2:列表功能
使用ES6新增
String.prototype.includes()
返回布尔值,表示是否找到了参数字符串
<!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>
<script src="../code/lib/vue.js"></script>
<style>
*{
margin: 0;
padding: 0;
}
.table {
width: 800px;
margin: 20px auto;
border-collapse: collapse; /* 将表格的两边框合并为一条,这一行不能少。 */
}
.table th {
background-color: #0094ff;
color: white;
font-size: 16px;
border: 1px solid black;
padding: 5px;
}
.table tr td {
text-align: center;
font-size: 16px;
padding: 5px;
border: 1px solid black;
}
.form {
width: 800px;
margin: 20px auto;
}
.form button {
margin-left: 5px;
}
.form label {
width: 100%;
}
</style>
</head>
<body>
<div id="app">
<div class="form">
编号:<input type="text" v-model="formData.id">
名称:<input type="text" v-model="formData.name">
<button @click="addData">添加</button>
<label>
搜索名称关键字:
<input id="sch" type="text" v-model="formData.keywords">
</label>
</div>
<table class="table">
<th>编号</th>
<th>名称</th>
<th>创建时间</th>
<th>操作</th>
<!-- v-for 中的数据,都是直接从 data 上的list中直接渲染过来的 -->
<!-- 现在我们自定义一个 search 方法,同时把所有的关键字,通过传参的形式,传递给了 search方法 -->
<!-- 在 search 方法内部,通过执行for循环,把所有符合搜索关键字的数据,保存到一个新数组中并返回 -->
<tr v-for="item in search(formData.keywords)" :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.ctime | dataFormat('yyyy-mm-dd')}}</td>
<td><a href="#" @click.prevent="delData(item.id)">删除</a></td>
</tr>
<!-- 无数据时,增加提示 -->
<tr v-if="list.length == 0">
<td colspan="4">列表无数据</td>
</tr>
</table>
</div>
<script>
// 全局的过滤器,进行时间的格式化
Vue.filter('dataFormat', function (dataStr, pattern="") {
//根据给定时间字符串,得到特定时间
var dt = new Date(dataStr)
var y = dt.getFullYear()
var m = (dt.getMonth() + 1).toString().padStart(2,'0')
var d = dt.getDate().toString().padStart(2,'0')
// return y + '-' + m + '-' + d
// 统一改成小写
if(pattern.toLowerCase() === 'yyyy-mm-dd') {
return `${y}-${m}-${d}`
} else {
var hh = dt.getHours().toString().padStart(2,'0')
var mm = dt.getMinutes().toString().padStart(2,'0')
var ss = dt.getSeconds().toString().padStart(2,'0')
return `${y}-${m}-${d} ${hh}:${mm}:${ss} ~~~~~`
}
})
var vm = new Vue({
el: '#app',
data: {
list: [
{id: 1, name: '奔驰', ctime: new Date},
{id: 2, name: 'AE86', ctime: new Date}
],
//用户添加的数据
formData: {
id: '',
name: '',
keywords: '',
},
},
methods: {
addData() { //添加内容的方法
var p = {id: this.formData.id, name: this.formData.name, ctime: new Date()}
this.list.push(p)
this.formData.id = ''
this.formData.name = ''
},
delData(id) { //根据ID删除数据
if(!confirm('是否要删除数据?')) {
return
}
// //1
// var index = this.list.findIndex((item)=>{
// return item.id == id
// })
// this.list.splice(index, 1)
//2
this.list.some((item, i) => {
if(item.id == id) {
this.list.splice(i, 1)
return true
}
})
},
search(keywords) { //根据关键字,进行数据的搜索
// var newList = []
// this.list.forEach(item => {
// // item.formData.name.indexOf() 错误
// if(item.name.indexOf(keywords) != -1) {
// newList.push(item)
// }
// })
// return newList
// 注意: forEach some filter findIndex 这些都属于数组的新方法
// 都会对数组的每一项进行遍历,执行相关的操作
return this.list.filter(item => {
// if(item.name.indexOf(keywords) != -1)
// ES6中,为字符串提供了一个新方法,叫做 String.prototype.includes('要包含的字符串')
// 如果包含则返回true,否则返回false
if(item.name.includes(keywords)) {
return item
}
})
}
}
});
document.getElementById("sch").focus()
</script>
</body>
</html>
自定义私有过滤器
私有过滤器:即在一个vue对象内部定义的过滤器。这种过滤器只有在当前vue对象的el指定的监管区域有作用。
过滤器调用的时候,采用的是就近原则,如果私有过滤器和全局过滤器名称一致了,这时候 优先调用私有过滤器。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="../code/lib/vue.js"></script>
</head>
<body>
<div id="app">
<p>{{ msg }}</p>
全局过滤器: <span>{{ msg | msgFormat('牛bee')}}</span>
</div>
<div id="app2">
私有过滤器: <span>{{ msg | msgFormat('Crazy')}}</span>
</div>
<script>
// 定义一个 Vue全局的过滤器,名字叫做 msgFormat
// 所谓的全局过滤器,就是所有的VM实例都共享的
Vue.filter ('msgFormat', function(msg, arg) {
return msg.replace(/单纯/g, arg)
})
var vm = new Vue({
el: '#app',
data: {
msg: '曾经,我也是一个单纯的少年,单纯的我,傻傻的问,谁是世界上最单纯的男人'
},
methods: {}
});
// 如何定义一个私有的过滤器(局部)
var vm2 = new Vue ({
el: '#app2',
data: {
msg: '曾经,我也是一个单纯的少年,单纯的我,傻傻的问,谁是世界上最单纯的男人'
},
methods: {
},
filters: { // 定义私有过滤器 过滤器有两个条件 【过滤器名称 和 处理函数】
// 过滤器调用的时候,采用的是就近原则,如果私有过滤器和全局过滤器名称一致了,这时候 优先调用私有过滤器
msgFormat: function(msg, arg) {
return msg.replace(/单纯/g, arg)
}
}
})
</script>
</body>
</html>