自定义组件

自定义组件

过滤器

概念

Vue.js 允许我们自定义过滤器,可被用作一些常见的文本格式化。过滤器可以用在两个地方:mustache 插值表达式v-bind表达式。过滤器应该被添加在 JavaScript 表达式的尾部,由"管道"符指示。

Vue提供了一系列的固定逻辑来使程序员更加容易的实现这些功能,这些过滤器称之为系统过滤器。

系统过滤器是Vue1.0中存在的,在Vue2.0中已经删除了。

系统过滤器的使用

可以参考参考文档:http://v1-cn.vuejs.org/api/#过滤器

Vue也提供了一个接口用来供程序员定义属于自己的特殊逻辑,Vue称之为自定义过滤器。我们接下来讲一讲。

自定义全局过滤器

文档地址:http://v1-cn.vuejs.org/guide/custom-filter.html

过滤器的基本使用

我们可以用全局方法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(/hello/g, 'hi')
    })

完整版代码如下:

复制代码
<!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="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

    <style>
        .table {
            width: 800px;
            margin: 20px auto;
            border-collapse: collapse; /*???,???:???????????*/
        }

        .table th {
            background: #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: 10px;
        }
    </style>
    </style>
</head>

<body>
    
    <div id="test">

        <p>{{ msg| myFilter }}</p>
        
    </div>

    <script>

        Vue.filter('myFilter', function (msg) {
            return msg.replace(/hello/g, 'hi')
            
        })
        var vm = new Vue({
            el: '#test',
            data:{
                msg: "hello, tom; hello lucy"
            },
            methods: {

            }
            
        });
    </script>

</body>

</html>
过滤器添加参数

上面的举例代码中,{``{ msg | msgFormat }}中,过滤器的调用并没有加参数,其实它还可以添加多个参数。

接下来,我们在上面的举例代码中进行改进。

改进一:过滤器加一个参数。如下:

将 msg 这个字符串中的"hello"改为 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="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
</head>

<body>
    
    <div id="test">

        <p>{{ msg| myFilter(arg) }}</p>
        
    </div>

    <script>

        Vue.filter('myFilter', function (msg, arg2) {
            return msg.replace(/hello/g, arg2)
            
        })
        var vm = new Vue({
            el: '#test',
            data:{
                msg: "hello, tom; hello lucy",
                arg: "fuck"
            },
            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="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
</head>

<body>
    
    <div id="test">

        <p>{{ msg| myFilter(n1, n2) }}</p>
        
    </div>

    <script>

        Vue.filter('myFilter', function (msg, arg1, arg2) {
            return msg.replace(/hello/g, arg1+arg2)
            
        })
        var vm = new Vue({
            el: '#test',
            data:{
                msg: "hello, tom; hello lucy",
                n1: "fuck",
                n2: "?"
            },
            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="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
</head>

<body>
    
    <div id="test">

        <p>{{ msg| myFilter(n1, n2)| myFilter2 }}</p>
        
    </div>

    <script>

        Vue.filter('myFilter', function (msg, arg1, arg2) {
            return msg.replace(/hello/g, arg1+arg2)
            
        })

        Vue.filter('myFilter2', function (msg) {
            return msg+msg
            
        })
        var vm = new Vue({
            el: '#test',
            data:{
                msg: "hello, tom; hello lucy",
                n1: "fuck",
                n2: "?"
            },
            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="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
</head>

<body>
    
    <div id="test1">
        {{ time }}
        <br /> {{ time | datefmt }}
    </div>

    <div id="test2">
        {{ time | datefmt }}
    </div>

    <script>

        Vue.filter('datefmt', function (msg, pattern="") {
           var res = '';
           var y = msg.getFullYear();
           var m = msg.getMonth()+1;
           var d = msg.getDate();

           if (pattern.toLowerCase()==='yyyy-mm-dd') {
            return `${y}-${m}-${d}`
            
           }else {
                var hh = msg.getHours()
                var mm = msg.getMinutes()
                var ss = msg.getSeconds()

                return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
           }
           
            
        })

        var vm = new Vue({
            el: '#test1',
            data:{
                time: new Date()
            },
            methods: {

            }
            
        })

        new Vue({
            el: "#test2",
            data: {
                time: new Date()
            },
            methods:{}
        })
    </script>

</body>

</html>

自定义私有过滤器

私有过滤器:在某一个 vue 对象内部定义的过滤器称之为私有过滤器。这种过滤器只有在当前vue对象的el指定的监管区域有用。

复制代码
<!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="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
</head>

<body>
    
    <div id="test1">
        {{ time }}
        <br /> {{ time | datefmt }}
    </div>

    <script>

        Vue.filter('datefmt', function (msg, pattern="") {
           var res = '';
           var y = msg.getFullYear();
           var m = msg.getMonth()+1;
           var d = msg.getDate();
           return `${y}-${m}-${d}`

           
            
        })

        var vm = new Vue({
            el: '#test1',
            data:{
                time: new Date()
            },
            methods: {

            },
            filters: {
                datefmt: function (msg) {
                    var y = msg.getFullYear();
                    var m = msg.getMonth()+1;
                    var d = msg.getDate();
                    return `${y}/${m}/${d}`
                }
            }
            
        })

  
    </script>

</body>

</html>

上面的代码中,我们在vue实例中,通过filters关键字,在里面定义了一个局部过滤器datefmt

滤器调用的时候,采用的是就近原则,如果私有过滤器和全局过滤器名称一致了,这时候 优先调用私有过滤器。

修饰符

v-on 按键修饰符

Vue 内置的按键修饰符,通俗一点讲,指的是:监听键盘输入的事件。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符。如下:Vue内置的按键修饰符:

复制代码
.enter
.tab
.delete (捕获 "删除" 和 "退格" 键)
.esc
.space
.up
.down
.left
.right
1.0.8+版本:支持单字母的按键别名。

比如说,keyup指的是:键盘(任何键位)抬起时的监听事件。.enter指的是:按enter键的按键修饰符。我们把这两个结合起来看看。

@keyup.enter举例:按enter键后的监听事件

@keyup.enter="addData"表示:按住enter键后,执行addData()方法。全称v-on:key.enter="addData"。我们还是拿VUE-列表这篇文章中的列表功能来举例。之前是点击"添加"按钮后,列表中会添加一个item。现在要求:在输入框中按enter键后,也能添加一个item。

核心代码如下:

复制代码
	<input type="text" v-model="formData.name" @keyup.enter="addData">

注意,如果写成@keyup="addData",效果却是:只要键盘的任何键位打了字(还没来得及按enter键),就会执行addData()方法,这种效果显然不是我们想要的。所以要加上修饰符.enter,表示只针对enter键。

自定义的按键修饰符

如果我们直接在代码的<input>标签里写@keyup.f2="addData",那么,按住「F2键」后,是没有效果的,因为「F2键」不是内置的按键修饰符(如果F2不能验证,你可以试一下F7)。

我们知道,每个按键都有一个键盘码。参考链接:

通过查阅,我们知道了「F2键」的键盘码为113,那代码可以这样写:(按住F2键后,执行 addData 方法)

复制代码
	<input type="text" v-model="formData.name" @keyup.113="addData">

虽然键盘码很全,但是不好记呀。于是,接下来,我们给键盘码定义别名。

自定义全局按键修饰符

复制代码
    //自定义全局按键修饰符
    Vue.config.keyCodes.f2 = 113;

自定义全局指令

示例1

让指定文本框自动获取焦点

如果我们想实现这个例子,原生js的写法是:

复制代码
    //原生js写法:网页一打开,就让指定的输入框自动获取焦点
    document.getElementById('search').focus()

但我们不建议这样做。我们可以通过Vue中的自定义指令来实现这个例子。步骤如下。

(1)使用Vue.directive()自定义全局指令:

复制代码
    //自定义全局指令 v-focus:让文本框自动获取焦点
    //参数1:指令的名称。注意,在定义的时候,指令的名称前面,不需要加 v- 前缀;但是:在`调用`的时候,必须在指令名称前 加上 v- 前缀
    //参数2:是一个对象,这个对象身上,有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作
    Vue.directive('focus', {
    	//在每个函数中,第一个参数,永远是 el ,表示 被绑定了指令的那个元素,这个 el 参数,是一个原生的JS对象(DOM对象)
        bind: function (el) { // 每当指令绑定到元素上的时候,会立即执行这个 bind 函数,【只执行一次】
            // 在元素 刚绑定了指令的时候,还没有 插入到 DOM中去,这时候,调用 focus 方法没有作用
            //  因为,一个元素,只有插入DOM之后,才能获取焦点
            // el.focus()
        },
        inserted: function (el) {  // inserted 表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】
            el.focus()
            // 和JS行为有关的操作,最好在 inserted 中去执行,放置 JS行为不生效
        },
        updated: function (el) {  // 当VNode更新的时候,会执行 updated, 【可能会触发多次】

        }
    })

完整代码如下:

复制代码
<!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="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

    <style>
        .table {
            width: 800px;
            margin: 20px auto;
            border-collapse: collapse; /*???,???:???????????*/
        }

        .table th {
            background: #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: 10px;
        }
    </style>
    </style>
</head>

<body>
    
    <div id="test">

       <input type="text" id="search" v-model="name" v-focus>
    </div>

    <script>

            Vue.directive('focus',{
                bind: function(el){},
                inserted: function (el) {
                    el.focus();
                    
                },
                update: function(el){}
            })

            new Vue({
                el: "#test",
                data: {
                    name: "hello"
                }
            })
       
    </script>

</body>

</html>
示例2:使用钩子函数获取参数的值

设置DOM元素的color样式 参考举例1中的写法,我们可能会这样给DOM元素设置样式:

复制代码
<!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="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

    <style>
        .table {
            width: 800px;
            margin: 20px auto;
            border-collapse: collapse; /*???,???:???????????*/
        }

        .table th {
            background: #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: 10px;
        }
    </style>
    </style>
</head>

<body>
    
    <div id="test">

       <input type="text" id="search" v-model="name" v-color>
    </div>

    <script>

            Vue.directive('color',{
                bind: function(el){
                    el.style.color = 'red'
                },
                inserted: function (el) {
                    // el.focus();
                    
                },
                update: function(el){}
            })

            new Vue({
                el: "#test",
                data: {
                    name: "hello"
                }
            })
       
    </script>

</body>

</html>

如上方代码所示,我们自定义了一个指令v-color,然后在input标签中用上了这个指令,就给元素设置了color属性。但是这个代码有个弊端是:color的属性值在定义指令的时候,被写死了。如何完善呢?我们可以在DOM元素中传参。一起来看看。

完善代码:

复制代码
<!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">
        搜索框1:
        <input type="text" id="search" v-model="name" v-color="'green'">
    </div>

    <script>

        //自定义全局指令 v-color:设置DOM元素的color属性
        Vue.directive('color', {
            // 样式,只要通过指令绑定给了元素,不管这个元素有没有被插入到页面中去,这个元素肯定有了一个内联的样式
            // 将来元素肯定会显示到页面中,这时候,浏览器的渲染引擎必然会解析样式,应用给这个元素
            // 意思是说,我们可以把样式的代码写到bind中去(即使这个时候,dom元素还没有被创建)
            bind: function (el, binding) { // 每当指令绑定到元素上的时候,会立即执行这个 bind 函数,【只执行一次】

                console.log(binding.name); //打印结果:color
                console.log(binding.value); //打印结果:green
                console.log(binding.expression);  //'green'

                el.style.color = binding.value// 通过bining拿到v-color中传递过来的值

            },
            inserted: function (el) {  // inserted 表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】
                // 和JS行为有关的操作,最好在 inserted 中去执行,防止 JS行为不生效
                //el.focus()
            },
            updated: function (el) {  // 当VNode更新的时候,会执行 updated, 【可能会触发多次】
            }
        })

        new Vue({
            el: '#app',
            data: {
                name: 'smyhvae'
            }
        })
    </script>
</body>

</html>

自定义全局指令的简写形式

在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如上面的代码中,我们可以写成简写形式:

复制代码
        Vue.directive('color', function (el, binding) { //注意,这个function等同于把代码写到了 bind 和 update 中去
            el.style.color = binding.value
        })

自定义私有指令

在某一个 vue 对象内部自定义的指令称之为私有指令。这种指令只有在当前vue对象的el指定的监管区域有用。

代码举例:(设置文字的font-weight属性)

复制代码
<!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">
        <span v-fontweight="600">生命壹号</span>
    </div>
    <script>

        new Vue({
            el: '#app',
            data: {
                name: 'smyhvae'
            },
            //自定义私有指令
            directives: {
                'fontweight': {
                    bind: function (el, binding) {
                        el.style.fontWeight = binding.value;
                    }
                }
            }
        })
    </script>
</body>

</html>

注意, el.style.fontWeight设置属性值,至少要600,否则看不到加粗的效果。

自定义私有指令的简写形式

在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如上面的代码中,我们可以写成简写形式:

复制代码
            //自定义私有指令(简写形式)
            directives: {
                'fontweight': function (el, binding) { //注意,这个function等同于把代码写到了 bind 和 update 中去
                    el.style.fontWeight = binding.value;
                }
            }
相关推荐
CodeCraft Studio6 小时前
文档开发组件Aspose 25.12全新发布:多模块更新,继续强化文档、图像与演示处理能力
前端·.net·ppt·aspose·文档转换·word文档开发·文档开发api
PPPPickup6 小时前
easychat项目复盘---获取联系人列表,联系人详细,删除拉黑联系人
java·前端·javascript
老前端的功夫6 小时前
前端高可靠架构:医疗级Web应用的实时通信设计与实践
前端·javascript·vue.js·ubuntu·架构·前端框架
前端大卫7 小时前
【重磅福利】学生认证可免费领取 Gemini 3 Pro 一年
前端·人工智能
孜燃7 小时前
Flutter APP跳转Flutter APP 携带参数
前端·flutter
脾气有点小暴7 小时前
前端页面跳转的核心区别与实战指南
开发语言·前端·javascript
lxh01137 小时前
最长递增子序列
前端·数据结构·算法
vipbic7 小时前
我封装了一个“瑞士军刀”级插件,并顺手搞定了自动化部署
vue.js·nuxt.js
Youyzq8 小时前
前端项目发布到cdn上css被编译失效问题rgba失效和rgb失效
前端·css·算法·cdn
San30.8 小时前
深入 JavaScript 内存机制:从栈与堆到闭包的底层原理
开发语言·javascript·udp