ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Vue 自定义过滤器完全指南:从全局/私有过滤器到时间格式化实战(千古前端教程系列)

Vue 自定义过滤器完全指南:从全局/私有过滤器到时间格式化实战(千古前端教程系列) 文档教程前端【免费下载链接】Web千古前端图文教程超详细的前端入门到进阶知识库。从零开始学前端做一名精致优雅的前端工程师。项目地址https://gitcode.com/gh_mirrors/we/Web点击查看免费下载本篇以千古前端图文教程仓库中的 06-自定义过滤器时间格式化举例 为核心系统讲解 Vue 2.x 中自定义过滤器的完整用法过滤器的概念与适用位置、全局过滤器Vue.filter()的注册与多参数调用、多个过滤器串联、私有过滤器的定义与就近原则并通过时间格式化这一高频实战场景深入演示 Date 对象、字符串模板、String.prototype.padStart()与 ES6 默认参数的综合运用。读完本篇你将能独立编写可复用、可传参、可串联的 Vue 过滤器并在列表、详情等页面中优雅地完成日期时间的格式化展示。一、过滤器的概念与适用场景概念Vue.js 允许我们自定义过滤器可被用作一些常见的文本格式化。过滤器可以用在两个地方mustache插值表达式即{{ }}模板语法v-bind 表达式如v-bind:id、:id这种属性绑定。过滤器应该被添加在 JavaScript 表达式的尾部由管道符|指示。也就是说过滤器是表达式加工管线的最后一环先计算表达式再把计算结果交给过滤器做进一步格式化最终输出到页面。需要特别说明的是过滤器是 Vue 模板层面的文本格式化工具它与 JavaScript 数组的filter()方法完全是两回事。在仓库配套教程 05-Vue的举例列表功能 中this.list.filter(item ...)是数组的原生过滤方法用于按条件筛选数据二者不要混淆。Vue 1.x 中的系统过滤器了解即可Vue 1.x 提供了一系列内置的固定逻辑过滤器称之为系统过滤器目的是让程序员更容易地实现常见的文本格式化如capitalize、uppercase、currency等。重要提醒系统过滤器是Vue 1.0中存在的特性在Vue 2.0 中已经被删除。同样被废弃的还有 1.x 中用于列表过滤的filterBy指令仓库教程 05-Vue的举例列表功能 第 612 行明确备注在 1.x 版本中可以通过 filterBy 指令来实现过滤但是在 2.x 中已经被废弃了。正因 2.x 删除了系统过滤器Vue 同时提供了一个接口供程序员定义属于自己的特殊逻辑这就是自定义过滤器。下面我们重点展开。二、自定义全局过滤器2.1 全局过滤器的基本使用我们可以用全局方法Vue.filter()自定义一个全局过滤器。这样每一个 Vue 对象实例每一个 VM 实例都可以拿到这个过滤器。它接收两个参数参数说明第一个参数过滤器的名称必须与模板管道符后面写的名称完全一致第二个参数具体的过滤器函数回调函数举例将 msg 字符串曾经我也是一个单纯的少年单纯的我傻傻的问谁是世界上最单纯的男人中的单纯全部替换为邪恶。1在插值表达式中这样调用p{{ msg | msgFormat }}/p上方代码的含义管道符前面的msg要把msg这段文本进行过滤管道符后面的msgFormat通过msgFormat这个过滤器来进行操作。2定义过滤器msgFormat// Vue.filter 中的第一个参数是过滤器的名称第二个参数是具体的过滤器函数 // 定义一个 Vue 全局的过滤器名字叫做 msgFormat Vue.filter(msgFormat, function (myMsg) { // function 的第一个参数指的是管道符前面的 msg // 字符串的 replace 方法第一个参数除了可写一个字符串之外还可以定义一个正则 return myMsg.replace(/单纯/g, 邪恶) })上方代码解释Vue.filter(过滤器的名称, 具体的过滤器函数)中的第一个参数指的是过滤器的名称必须和管道符后面的名称完全一致第二个参数是具体的过滤器函数过滤器函数 function 中第一个参数指的就是管道符前面的msg即被过滤的原始文本replace()方法是用来做字符串替换的。如果第一个参数只写成字符串单纯那么只会替换 msg 中的第一个单纯字样所以这里用正则/单纯/g去匹配 msg 中所有的单纯字样g标志表示全局匹配。最终完整版代码如下!DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 meta http-equivX-UA-Compatible contentieedge titleDocument/title script srcvue2.5.16.js/script /head body div idapp !-- 通过 过滤器 msgFormat 对 msg 进行过滤-- p{{ msg | msgFormat }}/p /div script // 定义一个 Vue 全局的过滤器名字叫做 msgFormat Vue.filter(msgFormat, function (myMsg) { // 字符串的 replace 方法第一个参数除了可写一个字符串之外还可以定义一个正则 // 将 myMsg 中的所有单纯字样修改为邪恶 return myMsg.replace(/单纯/g, 邪恶) }) // 创建 Vue 实例得到 ViewModel var vm new Vue({ el: #app, data: { msg: 曾经我也是一个单纯的少年单纯的我傻傻的问谁是世界上最单纯的男人 }, methods: {} }); /script /body /html网页显示效果模板中直接输出替换后的字符串原 msg 中的单纯全部变为邪恶。关于书写位置Vue.filter()这类全局注册代码应写在new Vue({...})创建实例之前。这一点在仓库配套教程 07-自定义按键修饰符自定义指令 中也有印证——其中自定义全局按键修饰符Vue.config.keyCodes.f2 113的书写位置与自定义全局过滤器的位置是并列的即都写在实例创建之前的全局区。2.2 给过滤器添加多个参数上面的举例中{{ msg | msgFormat }}的过滤器的调用并没有加参数其实它还可以添加多个参数。接下来我们在上面的基础上逐步改进。改进一过滤器加一个参数。将 msg 这个字符串中的单纯改为 xxx 变量。代码如下!DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 meta http-equivX-UA-Compatible contentieedge titleDocument/title script srcvue2.5.16.js/script /head body div idapp !-- 【重要】通过 过滤器 msgFormat 对 msg 进行过滤。括号里的参数代表 function 中的 arg2-- p{{ msg | msgFormat(xxx) }}/p /div script // 定义一个 Vue 全局的过滤器名字叫做 msgFormat Vue.filter(msgFormat, function (myMsg, arg2) { // 字符串的 replace 方法第一个参数除了可写一个字符串之外还可以定义一个正则第二个参数代表要替换为上面的 xxx // 将 myMsg 中的所有单纯字样修改为 arg2 return myMsg.replace(/单纯/g, arg2) }) // 创建 Vue 实例得到 ViewModel var vm new Vue({ el: #app, data: { msg: 曾经我也是一个单纯的少年单纯的我傻傻的问谁是世界上最单纯的男人 }, methods: {} }); /script /body /html注意代码中那行重要的注释括号里的参数代表 function 中的 arg2。也就是说调用过滤器时写在()里的实参会按顺序映射到过滤器函数的第 2 个、第 3 个……形参上第 1 个形参永远是管道符左边的值。改进二过滤器加两个参数。!DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 meta http-equivX-UA-Compatible contentieedge titleDocument/title script srcvue2.5.16.js/script /head body div idapp !-- 通过 过滤器 msgFormat 对 msg 进行过滤-- !-- 【重要】括号里的第一个参数代表 function 中的 arg2括号里的第二个参数代表 function 中的 arg3-- p{{ msg | msgFormat(【牛x】, 【参数arg3】) }}/p /div script // 定义一个 Vue 全局的过滤器名字叫做 msgFormat 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运行效果原字符串中的所有单纯都被替换为【牛x】【参数arg3】。这里可以看到多个参数可以在过滤器函数内自由拼接组合灵活性很高。改进三同时使用多个过滤器。对 msg 同时使用多个过滤器例如!DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 meta http-equivX-UA-Compatible contentieedge titleDocument/title script srcvue2.5.16.js/script /head body div idapp !-- 通过 两个过滤器msgFormat、myFilter2对 msg 进行过滤-- !-- 将 msg 交给第一个过滤器来处理然后将处理的结果交给第二个过滤器来处理-- p{{ msg | msgFormat(【牛x】, 【参数arg3】) | 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上方代码中添加了多个过滤器实现的思路是将 msg 交给第一个过滤器来处理然后将处理的结果交给第二个过滤器来处理——即管道式的链式传递前一个过滤器的返回值自动成为后一个过滤器的输入。三、实战举例时间格式化时间格式化是过滤器最典型的应用场景服务器返回的时间戳或 ISO 时间字符串直接显示给用户既不友好也不规范通过过滤器可以一行代码完成格式化。下面给出两种递进写法。3.1 举例 1基于 Date 对象的基础格式化!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title script srcvue2.5.16.js/script /head body div idapp {{ time }} br / {{ time | datefmt }} /div div idapp1 {{ time | datefmt }} /div /body script // 定义一个名称为 datefmt 的全局过滤器 Vue.filter(datefmt, function (input) { // 过滤器的逻辑将 input 的值格式化成 yyyy-MM-dd 字符串输出 var res ; var year input.getFullYear(); var month input.getMonth() 1; var day input.getDate(); res year - month - day; return res; }); new Vue({ el: #app1, data: { time: new Date() } }) new Vue({ el: #app, data: { time: new Date() } }); /script /html这个例子还展示了全局过滤器的一个关键特性同一个全局过滤器可以被多个 VM 实例共享。页面上同时存在#app和#app1两个 Vue 实例它们都在data.time中存放了new Date()并且都通过{{ time | datefmt }}使用了同一个datefmt过滤器无需在每个实例里重复定义。其中有两个新手容易踩的坑需要重点强调Date.prototype.getMonth()返回的是0~11的月份索引所以展示真实月份必须 1new Date()对象在插值表达式中直接输出时会显示为类似Fri May 25 2018 14:06:51 GMT0800的原始格式可读性差这正是需要过滤器格式化的原因。3.2 举例 2更高级的写法字符串模板 pattern 参数上面的举例 1时间格式化的过滤器我们还有个更高端的写法——使用 ES6 字符串模板并让过滤器支持可选的格式化参数!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title script srcvue2.5.16.js/script /head body div idapp 2018-05-25T14:06:51.618Z br / {{ 2018-05-25T14:06:51.618Z | dateFormat }} /div /body script Vue.filter(dateFormat, function (dateStr, pattern ) { // 根据给定的时间字符串得到特定的时间 var dt new Date(dateStr) // yyyy-mm-dd var y dt.getFullYear() var m dt.getMonth() 1 var d dt.getDate() // return y - m - d if (pattern.toLowerCase() yyyy-mm-dd) { // 如果调用过滤器的参数写的是 yyyy-mm-dd那就按照这种 yyyy-mm-dd 的格式写 // 这里用的是字符串模板 return ${y}-${m}-${d} } else { // 否则比如说调用过滤器时不写参数后面就补上 时-分-秒 var hh dt.getHours() var mm dt.getMinutes() var ss dt.getSeconds() return ${y}-${m}-${d} ${hh}:${mm}:${ss} } }) new Vue({ el: #app, data: { time: new Date() } }); /script /html这个版本与前一个版本相比有两个明显升级入参从 Date 对象变为时间字符串{{ 2018-05-25T14:06:51.618Z | dateFormat }}直接把 ISO 8601 格式的字符串传给过滤器过滤器内部通过new Date(dateStr)解析为 Date 对象——这样后端返回的字符串时间也可以直接套用过滤器通过第二个参数 pattern 控制输出格式传入yyyy-mm-dd时只输出日期不传参时输出完整的年-月-日 时:分:秒。3.3 举例 2 的改进用 padStart 补零运行上面代码时会发现箭头处的时间有些问题比如小时6、分钟4、秒7显示为单数字写成06、04、07更符合直觉。为了实现补零可以使用 ES6 中的字符串新方法String.prototype.padStart(maxLength, fillString)String.prototype.padEnd(maxLength, fillString)pad在英文中指的是补充。padStart的意思就是如果字符串长度不足maxLength就用fillString从开头补齐。实现举例!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title script srcvue2.5.16.js/script /head body div idapp 2018-05-25T14:06:51.618Z br / {{ 2018-05-25T14:06:51.618Z | dateFormat }} /div /body script Vue.filter(dateFormat, function (dateStr, pattern) { // 根据给定的时间字符串得到特定的时间 var dt new Date(dateStr) // yyyy-mm-dd var y dt.getFullYear() var m (dt.getMonth() 1).toString().padStart(2, 0) var d dt.getDate().toString().padStart(2, 0) if (pattern pattern.toLowerCase() yyyy-mm-dd) { // 如果调用过滤器的参数写的是 yyyy-mm-dd那就按照这种 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() } }); /script /html运行效果月份、日期、时、分、秒全部以两位数字呈现如2018-05-25 14:06:51格式规范统一。补零用到的关键技术点getMonth() 1得到数字后先.toString()转成字符串再.padStart(2, 0)不足两位时在左侧补0达到05、06这样的效果年份一般已是四位无需补零。3.4 pattern 参数的正确写法与 ES6 默认参数上面代码中if (pattern pattern.toLowerCase() yyyy-mm-dd)这个判断逻辑是先保证 pattern 参数传进来了然后继续后面的判断。我们不能直接写成if (pattern.toLowerCase() yyyy-mm-dd)。因为万一在调用的时候不传递参数 pattern那么 if 语句就相当于执行if (undefined.toLowerCase() yyyy-mm-dd)而undefined上没有toLowerCase方法会直接报错。不过ES6 中有个新特性叫默认参数Default Parameters我们可以利用它来彻底规避这个问题!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title script srcvue2.5.16.js/script /head body div idapp 2018-05-25T14:06:51.618Z br / {{ 2018-05-25T14:06:51.618Z | dateFormat }} /div /body script Vue.filter(dateFormat, function (dateStr, pattern ) { // 根据给定的时间字符串得到特定的时间 var dt new Date(dateStr) // yyyy-mm-dd var y dt.getFullYear() var m (dt.getMonth() 1).toString().padStart(2, 0) var d dt.getDate().toString().padStart(2, 0) if (pattern.toLowerCase() yyyy-mm-dd) { // 如果调用过滤器的参数写的是 yyyy-mm-dd那就按照这种 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() } }); /script /html通过pattern 为第二个形参设置默认值即使调用时不传参pattern也始终是一个字符串pattern.toLowerCase()可以安全执行。相比pattern pattern.toLowerCase()的防御式写法默认参数让代码更简洁、意图更清晰。四、自定义私有过滤器私有过滤器局部过滤器在某一个 Vue 对象内部定义的过滤器称之为私有过滤器。这种过滤器只有在当前 Vue 对象的 el 指定的监管区域内有用其他实例无法使用。举例日期格式化!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title script srcvue2.5.16.js/script /head body div idapp {{ time }} br / {{ time | datefmt }} /div /body script new Vue({ el: #app, data: { time: new Date() }, // 在某一个 vue 对象内部定义的过滤器称之为私有过滤器 // 这种过滤器只有在当前 vue 对象 el 指定的监管的区域有用 filters: { // input 是自定义过滤器的默认参数input 的值永远都是取自于 | 左边的内容 datefmt: function (input) { // 定义过滤器的内容将 input 的值格式化成 yyyy-MM-dd 字符串输出 var res ; var year input.getFullYear(); var month input.getMonth() 1; var day input.getDate(); res year - month - day; return res; } } }); /script /html上面的代码中我们在 Vue 实例中通过filters关键字在里面定义了一个局部过滤器datefmt。要点私有过滤器写在 Vue 实例配置对象的filters: { ... }选项里是普通对象字面量形式而非Vue.filter()全局注册过滤器函数的第一个参数input的值永远取自于|左边的内容页面第一行显示的是默认的 Date 原始格式第二行显示的是格式化之后的日期说明过滤器起到了作用。使用场景建议如果某个格式化逻辑只在一个组件/实例内用到优先用私有过滤器避免污染全局命名空间如果多个组件都要用例如全站统一的时间展示格式则应注册为全局过滤器。五、总结过滤器的核心规则过滤器调用采用就近原则如果私有过滤器和全局过滤器名称一致这时候优先调用私有过滤器。也就是说在 Vue 解析过滤器时会先查找实例自身的filters找不到再去全局Vue.filter()注册表里找。过滤器函数的第一个参数永远是管道符左边的值其余参数来自调用时()内依次传入的实参过滤器可以链式串联{{ msg | filterA | filterB }}表示 filterA 的输出作为 filterB 的输入全局过滤器用Vue.filter(name, fn)注册写在创建 Vue 实例之前所有实例共享私有过滤器写在实例的filters选项内仅当前实例的 el 监管区域可用时间格式化是过滤器的典型实战new Date(dateStr)解析 →getFullYear()/getMonth() 1/getDate()取年月日 →padStart(2, 0)补零 → 字符串模板拼接即可得到yyyy-MM-dd HH:mm:ss规范格式防御参数为空时可优先使用 ES6 默认参数pattern 避免undefined.toLowerCase()报错。延伸阅读本文核心内容对应仓库教程 06-自定义过滤器时间格式化举例全局注册类代码Vue.filter、Vue.config.keyCodes、Vue.directive等的书写位置与并列关系可参考 07-自定义按键修饰符自定义指令列表场景中数组filter方法与filterBy指令的废弃说明可参考 05-Vue的举例列表功能过滤器的调用位置插值表达式与 v-bind 表达式与模板语法的关系可结合 02-Vue的系统指令 一起学习。补充说明原文档 06-自定义过滤器时间格式化举例 末尾还顺带提及了 axios在 Vue 中专门用来发送 ajax 请求、基于 Promise、不依赖 Vue.js 库该主题与过滤器无关属于后续章节的内容铺垫此处不再展开。赞分享文档教程前端【免费下载链接】Web千古前端图文教程超详细的前端入门到进阶知识库。从零开始学前端做一名精致优雅的前端工程师。项目地址https://gitcode.com/gh_mirrors/we/Web点击查看免费下载相关推荐Vero-Qwen3I-8B-i1-GGUF快速上手指南从下载到部署的完整教程Vero Qwen3I 8B i1 GGUF快速上手指南从下载到部署的完整教程 想要快速上手 Vero Qwen3I 8B i1 GGUF视觉语言模型 吗这MikroORM Filters 完整实战从实体级过滤器到全局过滤器与关系 JOIN 过滤MikroORM Filters 完整实战从实体级过滤器到全局过滤器与关系 JOIN 过滤 导读 MikroORM 的 Filters过滤器机制允许你在实后端MikroORM 7.2 过滤器Filters完全指南实体级、全局过滤器与关系过滤实战MikroORM 7.2 过滤器Filters完全指南实体级、全局过滤器与关系过滤实战 导读 MikroORM 的过滤器机制允许你在实体层预先定义查询条件后端上一篇如何快速搭建AI图像生成服务3步实现FLUX.1-schnell高效部署下一篇Perfetto 轨迹查询实战trace_processor 会话模式、PerfettoSQL 与标准库模块创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表