从0开始学习vue第四节,vue的指令

1.vue常用内置指令介绍

1.1 渲染控制类指令

1.1.1 v-if

  • 作用:用来控制是否渲染页面元素。当传入表达式的结果为true时,渲染该元素。当传入表达式的结果为false时,不渲染该元素。
  • 例子:
<html>
    <header>

    </header>
    <body>
        <div id="root">
            <p v-if="showMessage">{{ message1 }}</p>
            <p v-else>{{ message2 }}</p>
            <button @click="showMessage = !showMessage">点我显示消息</button>
        </div>
    </body>
    <script src="./js/vue.global.js"></script>
    <script>
        let vue = Vue.createApp({
            data() {
                return {
                    message1: '我是码小飞',
                    message2: '我不是码小飞',
                    showMessage: false
                }
            }
        });
        vue.mount('#root')
    </script>
</html>

v-if还可以配合v-else-if指令进行多分支条件渲染控制,用法与v-if类似在此不在演示。

1.1.2 v-show

  • 作用:用来控制页面元素是否显示。如果表达式结果为true,则显示该元素。如果表达式结果为false,则不显示该元素。
  • 例子:
<html>
    <header>

    </header>
    <body>
        <div id="root">
            <p v-show="showMessage">{{ message }}</p>
            <button @click="showMessage = !showMessage">点我显示消息</button>
        </div>
    </body>
    <script src="./js/vue.global.js"></script>
    <script>
        let vue = Vue.createApp({
            data() {
                return {
                    message: '我是码小飞',
                    showMessage: false,

                }
            }
        });
        vue.mount('#root')
    </script>
</html>

v-show与v-if的异同:
v-show和v-if都可以用来控制页面元素是否显示,但实现原理也有不同。
v-if是控制页面元素是否真的渲染,当表达式结果发生变化时,页面dom元素会被重新渲染。
v-show是用来控制页面元素是否显示,不论表达式结果是真是假,页面元素都会被渲染好,只是元素的display属性会再表达式结果发生变化时进行调整。
当我们页面元素初次需要渲染很多时,建议使用v-if来减少初次渲染的元素数量来提升页面性能(因为判断条件结果为false的元素不会被渲染了)
当我们页面元素较少但需要频繁地进行显示/隐藏的切换时,建议使用v-show来优化页面性能(因为v-show显示/隐藏页面元素的成本较小)

1.1.3 v-for

  • 作用:用来渲染页面的列表元素,会将传入的属性循环遍历显示在页面上。v-for既可以遍历一个列表也可以遍历一个对象中的所有属性。
  • 例子:
<html>
    <header>

    </header>
    <body>
        <div id="root">
            <!--遍历数组-->
            <p v-for="(item, index) in userList" :key="item.id">
                {{index}}-{{item.id}}-{{item.userName}}-{{item.age}}
            </p>
            <!--遍历对象-->
            <p v-for="(value, key) of goods">
                {{key}}-{{value}}
            </p>
        </div>
    </body>
    <script src="./js/vue.global.js"></script>
    <script>
        let vue = Vue.createApp({
            data() {
                return {
                    userList: [
                        {id: 'u1001', userName: 'tom', age: 28},
                        {id: 'u1002', userName: 'jerry', age: 25}
                    ],
                    goods: {
                        id: 10001,
                        name: '水果手机',
                        prince: 9999
                    }
                }
            }
        });
        vue.mount('#root')
    </script>
</html>

注意事项:

  • v-for中使用in或of遍历的效果是一样的,可以任意选择
  • 使用v-for中的得到的item、index、value、key等变量均为局部变量,超出v-for作用域范围是不生效的
  • v-for支持嵌套遍历,即一个v-for遍历中可以嵌套另一个v-for
  • v-for渲染出的列表,如果后期需要对列表进行修改(特别是增删),最好对每个dom节点设置属性key,且key的值需要在列表中是唯一的。key是vue用来对dom元素进行状态管理的一个重要属性,用来帮助vue来区分页面的dom元素,在页面中不可见。
  • 尽量不要使用index作为key(因为index是可以变化的,当元素增或删都会引起下标的变化)。使用index作为key时,列表中元素顺序更新后,可能会引起vue的模板渲染错误,因为一些存有临时状态的元素会错乱(比如input标签),还会导致页面元素更新速度慢。引起问题的原因是由于vue更新dom时的diff比较算法导致的,感兴趣可以自行了解一下。

1.2 元素控制类指令

1.2.1 v-text

  • 作用:用来更新元素的文本内容
  • 用法:
<span v-text="msg"></span>
<!-- 等同于 -->
<span>{{msg}}</span>

1.2.2 v-html

  • 作用:更新元素内的innerHTMl
  • 用法:
<div v-html="html"></div>

注意事项:v-html只能对可信内容使用,不能对用户的输入内容使用v-html,因为这可能会导致XSS攻击

1.2.3 v-once

  • 作用:仅渲染元素和组件一次,并跳过之后的更新。可以用来记录元素最开始的状态。
  • 用法:
<!-- 单个元素 -->
<span v-once>This will never change: {{msg}}</span>
<!-- 带有子元素的元素 -->
<div v-once>
  <h1>comment</h1>
  <p>{{msg}}</p>
</div>
<!-- 组件 -->
<MyComponent v-once :comment="msg" />
<!-- `v-for` 指令 -->
<ul>
  <li v-for="i in list" v-once>{{i}}</li>
</ul>

1.2.4 v-cloak

  • 作用:用于隐藏尚未完成编译的 DOM 模板。我们在页面上编写的插值语法、指令等内容会在vue开始工作后才会被解析。但当我们的页面引入的css或js文件较大时,vue可能还来不及工作,此时页面上的插值语法等内容会被直接渲染在页面上,导致我们的页面出现了未处理的DOM元素,此时我们可以使用v-cloak来隐藏这些未处理的DOM元素
  • 用法:
<div v-cloak>
  {{ message }}
</div>
[v-cloak] {
  display: none;
}

当vue开始工作后,会将我们dom元素的v-cloak指令给去除掉。使dom元素显现出来。

1.2.5 v-pre

  • 作用:跳过该元素及其所有子元素的编译。当我们在元素上设置此指令后,vue会将元素中的所有内容原封不动的渲染出来
  • 用法:
<span v-pre>{{ this will not be compiled }}</span>

上面例子中{{}}并不会被vue当作插值语法解析

2.自定义指令

在使用vue框架时,我们除了可以使用已经为我们封装好的内部指令,还可以根据实际需求封装我们的自定义指令。
当我们有许多共同的dom元素操作时,就可以这些操作封装成一个自定义指令,来简化我们的代码,这也是vue官方推荐我们的做法。

2.1 局部指令

我们在组件中使用directives关键字来声明自定义指令,用例如下:

<html>
    <header>

    </header>
    <body>
        <div id="root">
            <p v-common-pre="'码小飞'">自定义指令</p>
        </div>
    </body>
    <script src="./js/vue.global.js"></script>
    <script>
        let vue = Vue.createApp({
            data() {
                return {
                    
                }
            },
            directives: {
                'common-pre': {
                    mounted(el, binding, vnode, prevVnode) {
                        el.innerText = binding.value + "-" + el.innerText;
                    },
                    updated(el, binding, vnode, prevVnode) {
                        console.log('updated');
                        el.innerText = binding.value + "-" + el.innerText;
                    }
                }
            }
        });
        vue.mount('#root')
    </script>
</html>

在上述例子中,我们创建了一个名为common-pre的自定义指令。指令接收一个前缀值,作用是在使用指令的dom元素内将前缀拼接到dom元素的文本内容里。在自定义指令中我们声明了mounted、updated两个方法,vue会在处理到指令声明的html标签时自动调用我们的方法。mounted会在元素挂载到页面时被调用,updated会在元素所在模板发生更新时被调用。

注意事项:

  • 我们在使用html标签中使用指令时需要加入v-的前缀,否则vue会把指令当作普通的attribute,并不会做处理。
  • 指令定义推荐使用kebab-case的命名法则,不推荐使用camelCase命名法则,因为vue在处理html上的指令时都会按kebab-case命名法去处理。

上面的例子是自定义指令的完整写法,如果我们只声明mounted、updated方法,还可以使用简写方法

directives: {
    'common-pre'(el, binding, vnode, prevVnode){
        el.innerText = binding.value + "-" + el.innerText;
    }
}

指令参数还可以传递对象字面量,如{color:'white'},感兴趣的同学可以自己试一试

2.2 全局指令

上面的例子是注册局部指令,局部指令的作用域只在其声明的组件内可以使用。当我们想要在整个应用中声明指令时,需要使用组件的directive方法进行注册,指令的声明方法与局部指令一样,注册后的指令即可在整个应用中使用。

const app = createApp({})

// 使 v-focus 在所有组件中都可用
app.directive('focus', {
  /* 在此处编写组件的声明,简写和完整写法都可以 */
})

2.3 指令的钩子函数和函数参数

除了上述例子中mounted和updated两个钩子函数外,指令还有一些钩子函数

const myDirective = {
  // 在绑定元素的 attribute 前
  // 或事件监听器应用前调用
  created(el, binding, vnode, prevVnode) {
    // 下面会介绍各个参数的细节
  },
  // 在元素被插入到 DOM 前调用
  beforeMount(el, binding, vnode, prevVnode) {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都挂载完成后调用
  mounted(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件更新前调用
  beforeUpdate(el, binding, vnode, prevVnode) {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都更新后调用
  updated(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件卸载前调用
  beforeUnmount(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件卸载后调用
  unmounted(el, binding, vnode, prevVnode) {}
}

当我们需要对指令行为进行细粒度控制时,就要根据实际情况选择合适的钩子函数进行实现。比如当我们需要在获取元素的焦点,就不能把获取焦点的代码写在created钩子内,而需要写到mounted钩子内。

所有钩子函数都传递了四个参数,参数作用分别如下:

  • el:代表指令所在的真实dom元素
  • binding:代表指令的绑定对象,其内部属性如下
    value:传递给指令的值。例如在 v-my-directive="1 + 1" 中,值是 2。
    oldValue:之前的值,仅在 beforeUpdate 和 updated 中可用。无论值是否更改,它都可用。
    arg:传递给指令的参数 (如果有的话)。例如在 v-my-directive:foo 中,参数是 "foo"。
    modifiers:一个包含修饰符的对象 (如果有的话)。例如在 v-my-directive.foo.bar 中,修饰符对象是 { foo: true, bar: true }。
    instance:使用该指令的组件实例。
    dir:指令的定义对象。
  • vnode:代表绑定元素的底层 VNode。
  • prevNode:代表之前的渲染中指令所绑定元素的 VNode。仅在 beforeUpdate 和 updated 钩子中可用。
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码小飞飞飞飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值