简介

主要讲解vue中如何定义自定义标签。
自定义标签使用vue的配置对象中的directives属性进行配置。

比如下面代码定义一个自定义标签v-big,可以把绑定的表达式乘以十倍渲染到元素的text区,相当于v-text,只是他表达式要数字并且会乘以10倍后渲染。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义指令</title>
</head>
<body>
    <div id="root">
        <!-- 使用自定义指令v-big -->
        <!-- 作用是把表达式中的值*10倍后再渲染到元素的文本中 -->
        <div>{{name}}</div>
        <div v-big="n"></div>
        <button @click="n++">点击按钮n+1</button>

    </div>

    <script src="./js/vue.js"></script>
    <script>
        const vm = new Vue({
            el:"#root",
            data:{
                n:1,
                name:"yehaocong"
            },
            //这个属性是配置自定义属性的
            directives:{
                //简便写法,直接写成函数的形式,但是这种方法虽然简便,但是功能没有完整写法那么强大。
                //指令的使用时要加v- ,也就是v-方法名
                //该方法会传入两个参数,第一个是指令绑定的元素对象,第二个是绑定信息。
                
                //该函数有两个触发时机:
                //1. 初始化时,也就是模板第一次加载渲染时。
                //2. 模板被重新解析时,这个不仅限函数设计的属性被更改,只要是这个模板的属性被更改导致模板重新解析,就会调用该函数。

                big(element,binding){
                    console.log("big");
                    console.log(element);
                    console.log(binding);
                    element.innerText = binding.value * 10;
                }
            }
        })
    </script>
</body>
</html>

效果:
在这里插入图片描述
在这里插入图片描述

完整写法:
完整写法能够完成简便写法一些无法完成的功能,比如写一个具备以下功能自定义指令。

写一个v-fbind指令,该指令用于绑定input元素的value值,但是可以使得input框获取焦点。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义指令</title>
</head>
<body>
    <div id="root">
        <input type="text" v-fbind="n"> <br><br>
        <button @click="n++">点击n+1</button>
    </div>
</body>

<script src="./js/vue.js"></script>
<script>
    const vm = new Vue({
        el:"#root",
        data:{
            n:1
        },
        directives:{
            //先使用简便写法看是否能完成功能
            fbind(element,binding){
                element.value = binding.value;
                //聚焦
                element.focus();
            }
        }
    })
</script>
</html>

效果:
在这里插入图片描述
点击一下页面的按钮,使得n加一,重新解析模板。
在这里插入图片描述
这个的原因是,初始化时执行聚焦的代码时,input元素与指令才刚刚绑定,并没有插入到页面html中,此时使用聚焦代码是不生效的,因为页面实际上还不存在该元素。

然后点击,重新调用fbind函数,此时,由于已经不是初始化了,input框已经真正存在html页面结构中,所以聚焦成功。

所以使用简便方式无法进行聚焦,需要使用完整形式。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义指令</title>
</head>
<body>
    <div id="root">
        <input type="text" v-fbind="n"> <br><br>
        <button @click="n++">点击n+1</button>
    </div>
</body>

<script src="./js/vue.js"></script>
<script>
    const vm = new Vue({
        el:"#root",
        data:{
            n:1
        },
        directives:{
            //完整形式,写成一个对象。
            //有三个函数会在一定的时机调用:
            //1. bind 函数,就是在指令与元素绑定时调用,也就是第一个调用时机。
            //2. update函数,在模板重新解析时的回调函数,也就是第二个调用时机。
            //3. inserted函数,会在元素插入到页面html结构后调用。
            //三个回调函数都会接收element和binding
            fbind:{
                bind(element,binding){
                    //在这里进行数据的绑定
                    element.value = binding.value;
                },
                update(element,binding){
                    //重新渲染时需要进行数据绑定
                    element.value = binding.value;
                    //聚焦
                    element.focus();
                },
                inserted(element,binding){
                    //聚焦
                    element.focus();
                }
            }
        }
    })
</script>
</html>

效果:
在这里插入图片描述
在这里插入图片描述
因为bind函数常常会有update函数的逻辑一致,所以简便方式就是直接封装bind和update函数。

函数的this是window。

上面的自定义指令的定义形式都是局部的,也就是只有该vm对象管理的模板才能用。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义指令</title>
</head>
<body>
    <div id="root">
        <input type="text" v-fbind="n"> <br><br>
        <button @click="n++">点击n+1</button>
    </div>
    <!-- 定义第二个容器,使用v-fbind指令,但是管理该容器的vm对象不定义该指令 -->
    <div id="root1">
        <input type="text" v-fbind="n"> <br><br>
        <button @click="n++">点击n+1</button>
    </div>
</body>

<script src="./js/vue.js"></script>
<script>
    const vm = new Vue({
        el:"#root",
        data:{
            n:1
        },
        directives:{
            //完整形式,写成一个对象。
            //有三个函数会在一定的时机调用:
            //1. bind 函数,就是在指令与元素绑定时调用,也就是第一个调用时机。
            //2. update函数,在模板重新解析时的回调函数,也就是第二个调用时机。
            //3. inserted函数,会在元素插入到页面html结构后调用。
            //三个回调函数都会接收element和binding
            fbind:{
                bind(element,binding){
                    //在这里进行数据的绑定
                    element.value = binding.value;
                },
                update(element,binding){
                    //重新渲染时需要进行数据绑定
                    element.value = binding.value;
                    //聚焦
                    element.focus();
                },
                inserted(element,binding){
                    //聚焦
                    element.focus();
                }
            }
        }
    })

    const vm1 = new Vue({
        el:"#root1",
        data:{
            n:1
        }
    })
</script>
</html>

效果:
在这里插入图片描述

定义全局指令

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义指令</title>
</head>
<body>
    <div id="root">
        <input type="text" v-fbind="n"> <br><br>
        <button @click="n++">点击n+1</button>
    </div>
    <!-- 定义第二个容器,使用v-fbind指令,但是管理该容器的vm对象不定义该指令 -->
    <div id="root1">
        <input type="text" v-fbind="n"> <br><br>
        <button @click="n++">点击n+1</button>
    </div>
</body>

<script src="./js/vue.js"></script>
<script>

    //使用VUE.directive方法进行全局指令的定义。
    //有两种形式:
    //1. Vue.directive("指令名称",函数)  对应简便形式
    //2. Vue.directive("指令名称",对象)  对应完整形式

    Vue.directive("fbind",{
        bind(element,binding){
                    //在这里进行数据的绑定
                    element.value = binding.value;
                },
                update(element,binding){
                    //重新渲染时需要进行数据绑定
                    element.value = binding.value;
                    //聚焦
                    element.focus();
                },
                inserted(element,binding){
                    //聚焦
                    element.focus();
                }
    })

    const vm = new Vue({
        el:"#root",
        data:{
            n:1
        }
        // ,
        // directives:{
        //     //完整形式,写成一个对象。
        //     //有三个函数会在一定的时机调用:
        //     //1. bind 函数,就是在指令与元素绑定时调用,也就是第一个调用时机。
        //     //2. update函数,在模板重新解析时的回调函数,也就是第二个调用时机。
        //     //3. inserted函数,会在元素插入到页面html结构后调用。
        //     //三个回调函数都会接收element和binding
        //     fbind:{
        //         bind(element,binding){
        //             //在这里进行数据的绑定
        //             element.value = binding.value;
        //         },
        //         update(element,binding){
        //             //重新渲染时需要进行数据绑定
        //             element.value = binding.value;
        //             //聚焦
        //             element.focus();
        //         },
        //         inserted(element,binding){
        //             //聚焦
        //             element.focus();
        //         }
        //     }
        // }
    })

    const vm1 = new Vue({
        el:"#root1",
        data:{
            n:1
        }
    })
</script>
</html>

效果:
在这里插入图片描述

Logo

前往低代码交流专区

更多推荐