欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

VUE教程02 常用指令及自定义指令

程序员文章站 2022-05-15 13:48:50
...


指令就是Vue内部提供的一些自定义属性,这些属性中封装好了Vue内部实现的一些功能。只要使用这些指令就可以使用Vue中实现的这些功能

v-once指令

Vue双向数据绑定的特点是只要数据发生变化, 界面就会跟着变化,该指令让界面不要跟着数据变化, 只渲染一次。通过vue调试工具修改vue对象节点的值发现原始数据的标签不会更改,当前数据会更新

<!--这里就是MVVM中的View-->
<div id="app">
    <p v-once>原始数据: {{ name }}</p>
    <p>当前数据: {{ name }}</p>
</div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
            name: "zhangsan",
        }
    });
</script>

v-text及v-html指令

v-text就相当于过去学习的innerText ,v-html就相当于过去学习的innerHTML

<!--这里就是MVVM中的View-->
<div id="app">
    <!--插值的方式: 可以将指定的数据插入到指定的位置-->
    <p>++++{{ name }}++++</p>
    <!--插值的方式: 不会解析HTML-->
    <p>++++{{ msg }}++++</p>
    <!--v-text的方式: 会覆盖原有的内容-->
    <p v-text="name">++++++++</p>
    <!--v-text的方式: 也不会解析HTML-->
    <p v-text="msg">++++++++</p>
    <!--v-html的方式: 会覆盖原有的内容-->
    <p v-html="name">++++++++</p>
    <!--v-html的方式:会解析HTML-->
    <p v-html="msg">++++++++</p>
</div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
            name: "zhansan",
            msg: "<span>我是span</span>"
        }
    });
</script>

结果展示
VUE教程02 常用指令及自定义指令

v-if指令

如果v-if取值是true就渲染元素, 如果不是就不渲染元素。如果条件不满足就不创建这个元素(重点)。v-if可以从模型中获取数据,也可以直接赋值一个表达式
v-else指令可以和v-if指令配合使用, 当v-if不满足条件时就执行v-else就显示v-else中的内容。v-else不能单独出现,v-if和v-else中间不能出现其它内容
v-else-if可以和v-if指令配合使用, 当v-if不满足条件时就依次执行后续v-else-if, 哪个满足就显示哪个
示例

<div id="app">
    <p v-if="show">我是true</p>
    <p v-if="hidden">我是false</p>
    <p v-if="true">我是true</p>
    <p v-if="false">我是false</p>
    <p v-if="age >= 18">我是true</p>
    <p v-if="age < 18">我是false</p>

    <p v-if="age >= 18">成年人</p>
    <p>中间的内容</p>
    <p v-else>未成年人</p>

    <p v-if="score >= 80">优秀</p>
    <p v-else-if="score >= 60">良好</p>
    <p v-else></p>
</div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
            show: true,
            hidden: false,
            age: 17,
            score: 50
        }
    });
</script>

v-show指令

v-show和v-if的能够一样都是条件渲染, 取值为true就显示, 取值为false就不显示。
v-if: 只要取值为false就不会创建元素
v-show: 哪怕取值为false也会创建元素, 只是如果取值是false会设置元素的display为none
由于取值为false时v-if不会创建元素, 所以如果需要切换元素的显示和隐藏, 每次v-if都会创建和删除元素
由于取值为false时v-show会创建元素并设置display为none, 所有如果需要切换元素的显示和隐藏,不会反复创建和删除, 只是修改display的值。
所以: 如果企业开发中需要频繁切换元素显示隐藏, 那么推荐使用v-show, 否则使用v-if
示例代码

<div id="app">
    <p v-show="show">我是true</p>
    <p v-show="hidden">我是false</p>
    <p v-show="true">我是true</p>
    <p v-show="false">我是false</p>
    <p v-show="age >= 18">我是true</p>
    <p v-show="age < 18">我是false</p>
    <p v-show="show">我是段落1</p>
    <p v-show="hidden">我是段落2</p>
</div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
            show: true,
            hidden: false,
            age: 18
        }
    });
</script>

v-for指令

相当于JS中的for in循环, 可以根据数据多次渲染元素。可以遍历 数组, 字符, 数字, 对象
示例

<div id="app">
    <ul>
        <li v-for="(value, index) in list">{{index}}---{{value}}</li>
        <li v-for="(value, index) in 'abcdefg'">{{index}}---{{value}}</li>
        <li v-for="(value, index) in 6">{{index}}---{{value}}</li>
        <li v-for="(value, key) in obj">{{key}}---{{value}}</li>
    </ul>
</div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
            list: ["张三", "李四", "王五", "赵六"],
            obj: {
                name: "lnj",
                age: 33,
                gender: "man",
                class: "ccdd"
            }
        }
    });
</script>

v-for为了提升性能, 在更新已渲染过的元素列表时,会采用“就地复用”策略。也正是因为这个策略, 在某些时刻会导致我们的数据混乱。
为了解决这个问题, 我们可以在渲染列表的时候给每一个元素加上一个独一无二的key,v-for在更新已经渲染过的元素列表时, 会先判断key是否相同, 如果相同则复用, 如果不同则重新创建。
不能使用index的作为key,因为当列表的内容新增或者删除时index都会发生变
示例(由于key的问题导致添加数据时复选框显示不正确):

<div id="app">
    <form>
        <input type="text" v-model="name">
        <input type="submit" value="添加" @click.prevent="add">
    </form>
    <ul>
        <li v-for="(person,index) in persons" :key="person.id">
<!--        <li v-for="(person,index) in persons" :key="index">-->
            <input type="checkbox">
            <span>{{index}} --- {{person.name}}</span>
        </li>
    </ul>
</div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
            persons: [
                {name: "zs", id: 1},
                {name: "ls", id: 2},
                {name: "ww", id: 3}
                ],
            name: ""
        },
        // 专门用于存储监听事件回调函数
        methods: {
            add(){
                let lastPerson = this.persons[this.persons.length - 1];
                let newPerson = {name: this.name, id: lastPerson.id + 1};
                // this.persons.push(newPerson);
                this.persons.unshift(newPerson);
                this.name = "";
            }
        },
        // 专门用于定义计算属性的
        computed: {
        }
    });
</script>

v-bind指令

在企业开发中想要给"元素"绑定数据, 我们可以使用{{}}, v-text, v-html
但是如果想给"元素的属性"绑定数据, 就必须使用v-bind,所以v-bind的作用是专门用于给"元素的属性"绑定数据的
格式:v-bind:属性名称=“绑定的数据” 或 :属性名称=“绑定的数据”
赋值的数据可以是任意一个合法的JS表达式,例如: :属性名称=“age + 1”
示例:

<div id="app">
    <p>{{name}}</p>
    <p v-text="name"></p>
    <p v-html="name"></p>
    <!--注意点: 如果要给元素的属性绑定数据, 那么是不能够使用插值语法的-->
    <input type="text" value="{{name}}">
    <!--注意点: 虽然通过v-model可以将数据绑定到input标签的value属性上
                但是v-model是有局限性的, v-model只能用于input/textarea/select
                但是在企业开发中我们还可能需要给其它标签的属性绑定数据-->
    <input type="text" v-model="name">
    <input type="text" v-bind:value="name">
    <input type="text" :value="name">
    <input type="text" :value="age + 1">
</div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
            name: "cc666",
            age: 18
        }
    });
</script>

绑定class

对于class和style属性而言, 它的格式比较特殊。
通过v-bind绑定类名方式:

  1. :class="[‘需要绑定类名’, …]" 数组中单引号类名,引擎去style中查找
  2. :class=“需要绑定类名” 直接赋值一个类名(没有放到数组中)默认回去Model中查找
  3. :class="[需要绑定类名]" 数组中的类名没有用引号括起来也会去Model中查找
  4. :class="[flag?‘active’:’’]" 数组的每一个元素都可以是一个三目运算符按需导入
  5. :class="[{‘active’: true}]" 可以使用对象来替代数组中的三目运算符按需导入
  6. 绑定的类名太多可以将类名封装到Model中
obj: {
    'color': true,
    'size': true,
    'active': false,
}

示例:

    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .size{
            font-size: 100px;
        }
        .color{
            color: red;
        }
        .active{
            background: skyblue;
        }
    </style>
<div id="app">
    <p class="size color active">我是段落</p>
    <!--
    注意点:
    如果需要通过v-bind给class绑定类名, 那么不能直接赋值
    默认情况下v-bind会去Model中查找数据, 但是Model中没有对应的类名, 所以无效, 所以不能直接赋值
    -->
    <p :class="size">我是段落</p>
    <!--
    注意点:
    如果想让v-bind去style中查找类名, 那么就必须把类名放到数组中
    但是放到数组中之后默认还是回去Model中查找
    -->
    <p :class="[size]">我是段落</p>
    <!--
    注意点:
    将类名放到数组中之后, 还需要利用引号将类名括起来才会去style中查找
    -->
    <p :class="['size', 'color', 'active']">我是段落</p>
    <!--
    注意点:
    如果是通过v-bind类绑定类名, 那么在绑定的时候可以编写一个三目运算符来实现按需绑定
    格式: 条件表达式 ? '需要绑定的类名' : ''
    -->
    <p :class="['size', 'color', flag ? 'active' : '']">我是段落</p>
    <!--
    注意点:
    如果是通过v-bind类绑定类名, 那么在绑定的时候可以通过对象来决定是否需要绑定
    格式: {'需要绑定的类名' : 是否绑定}
    -->
    <p :class="['size', 'color',{'active' : false}]">我是段落</p>
    <!--
    注意点:
    如果是通过v-bind类绑定类名, 那么还可以使用Model中的对象来替换数组
    -->
    <p :class="obj">我是段落</p>
</div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
            flag: false,
            obj:{
                'size': false,
                'color': false,
                'active': true,
            }
        }
    });
</script>

绑定style

通过v-bind给style属性绑定数据方式:

  1. 将数据放到对象中
    :style="{color:‘red’,‘font-size’:‘50px’}"
  2. 将数据放到Model对象中
obj: {
    color: 'red',
    'font-size': '80px',
}

如果属性名称包含-, 那么必须用引号括起来。如果需要绑定Model中的多个对象, 可以放到一个数组中赋值

示例:

<div id="app">
    <p style="color: red">我是段落</p>
    <!--
    注意点:
    和绑定类名一样, 默认情况下v-bind回去Model中查找, 找不到所以没有效果
    -->
    <p :style="color: red">我是段落</p>
    <!--
    注意点:
    我们只需要将样式代码放到对象中赋值给style即可
    但是取值必须用引号括起来
    -->
    <p :style="{color: 'red'}">我是段落</p>
    <!--
    注意点:
    如果样式的名称带-, 那么也必须用引号括起来才可以
    -->
    <p :style="{color: 'red', 'font-size': '100px'}">我是段落</p>
    <p :style="obj">我是段落</p>
    <!--
    注意点:
    如果Model中保存了多个样式的对象 ,想将多个对象都绑定给style, 那么可以将多个对象放到数组中赋值给style即可
    -->
    <p :style="[obj1, obj2]">我是段落</p>
</div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
            obj1:{
                "color": "blue",
                "font-size": "100px"
            },
            obj2: {
                "background-color": "red"
            }
        }
    });
</script>

v-on指令

v-on指令专门用于给元素绑定监听事件,v-on绑定的事件被触发之后, 会去Vue实例对象的methods中查找对应的回调函数
格式:v-on:事件名称=“回调函数名称” 或 @事件名称=“回调函数名称” (函数名称 后面可以写()也可以不写)
可以给绑定的回调函数传递参数 如:<button @click="myFn('lnj', 33, $event)">我是按钮</button>
示例

<div id="app">
    <button onclick="alert('lnj')">我是按钮</button>
    <!--
    注意点:
    1.如果是通过v-on来绑定监听事件, 那么在指定事件名称的时候不需要写on
    2.如果是通过v-on来绑定监听事件, 那么在赋值的时候必须赋值一个回调函数的名称, 如下这种直接写代码不管用
    -->
    <button v-on:click="alert('lnj')">我是按钮</button>
    <!--
    注意点:
    当绑定的事件被触发后, 会调用Vue实例的methods对象中对应的回调函数
    -->
    <button v-on:click="myFn">我是按钮</button>
    <button @click="myFn">我是按钮</button>
</div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
        },
        methods: {
            myFn(){
                alert('lnj')
            }
        }
    });
</script>

在事件中有很多东西需要我们处理, 例如事件冒泡,事件捕获, 阻止默认行为等
那么在Vue中如何处理以上内容呢, 我们可以通过v-on修饰符来处理
常见修饰符
.once - 只触发一次回调。
.prevent - 调用 event.preventDefault()。
.stop - 调用 event.stopPropagation()。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.capture - 添加事件侦听器时使用 capture 模式。
使用示例

<div id="app">
    <!--注意点: 默认情况下事件的回调函数可以反复的执行, 只要事件被触发就会执行-->
    <button v-on:click="myFn">我是按钮</button>
    <!--如果想让事件监听的回调函数只执行一次, 那么就可以使用.once修饰符-->
    <button v-on:click.once ="myFn">我是按钮</button>
    <!--如果想阻止元素的默认行为, 那么可以使用.prevent修饰符-->
    <a href="http://www.it666.com" v-on:click.prevent="myFn">我是A标签</a>
    <!--
    默认情况下载嵌套的元素中, 如果都监听了相同的事件, 那么会触发事件冒泡
    如果想阻止事件冒泡, 那么可以使用.stop修饰符
    -->
    <!----><div class="a" @click="myFn1">
        <div class="b" @click.stop="myFn2">
            <div class="c" @click="myFn3"></div>
        </div>
    </div>
    <!--
    如果想让回调只有当前元素触发事件的时候才执行, 那么就可以使用.self修饰符
    -->
    <!----><div class="a" @click="myFn1">
        <div class="b" @click.self="myFn2">
            <div class="c" @click="myFn3"></div>
        </div>
    </div>
    <!--
    默认情况下是事件冒泡, 如果想变成事件捕获, 那么就需要使用.capture修饰符
    -->
    <div class="a" @click.capture="myFn1">
        <div class="b" @click.capture="myFn2">
            <div class="c" @click.capture="myFn3"></div>
        </div>
    </div>
</div>
<script>
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
        },
        // 专门用于存储监听事件回调函数
        methods: {
            myFn(){
                alert('lnj');
            },
            myFn1(){
                console.log("爷爷");
            },
            myFn2(){
                console.log("爸爸");
            },
            myFn3(){
                console.log("儿子");
            }
        }
    });
</script>

按键修饰符
我们可以通过按键修饰符监听特定按键触发的事件,例如: 可以监听当前事件是否是回车触发的, 可以监听当前事件是否是ESC触发的等。可以使用系统预定义修饰符也可以使用自定义修饰符。

<div id="app">
    <input type="text" @keyup.enter="myFn">
    <input type="text" @keyup.f2="myFn">
</div>
<script>
    Vue.config.keyCodes.f2 = 113;
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
        },
        // 专门用于存储监听事件回调函数
        methods: {
            myFn(){
                alert("lnj");
            }
        }
    });
</script>

自定义全局指令

在Vue中除了可以使用Vue内置的一些指令以外, 我们还可以自定义指令。
定义全局指令语法:

ue.directive('自定义指令名称', {
    生命周期名称: function (el) {
        指令业务逻辑代码
    }
});

自定义指令时一定要明确指令的业务逻辑代码更适合在哪个阶段执行
例如: 指令业务逻辑代码中没有用到元素事件, 那么可以在bind阶段执行
例如: 指令业务逻辑代码中用到了元素事件, 那么就需要在inserted阶段执行
使用时需要加上v-, 而在自定义时不需要加上v-

<div id="app">
     <p v-color>我是段落</p
    <input type="text" v-focus>
</div>
<script>
    /*
    directive方法接收两个参数
    第一个参数: 指令的名称
    第二个参数: 对象
    注意点: 在自定义指令的时候, 在指定指令名称的时候, 不需要写v-
    注意点: 指令可以在不同的生命周期阶段执行
    bind: 指令被绑定到元素上的时候执行
    inserted: 绑定指令的元素被添加到父元素上的时候执行
    * */
    Vue.directive("color", {
        // 这里的el就是被绑定指令的那个元素
        bind: function (el) {
            el.style.color = "red";
        }
    });
    Vue.directive("focus", {
        // 这里的el就是被绑定指令的那个元素
        inserted: function (el) {
            el.focus();
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
        },
        // 专门用于存储监听事件回调函数
        methods: {
        }
    });
</script>

在执行自定义指令对应的方法的时候, 除了会传递el给我们, 还会传递一个对象给我们。这个对象中就保存了指令传递过来的参数。示例如下:

<div id="app">
    <p v-color="'blue'">我是段落</p>
    <p v-color="curColor">我是段落</p>
</div>
<script>
    Vue.directive("color", {
        // 这里的el就是被绑定指令的那个元素
        bind: function (el, obj) {
            // el.style.color = "red";
            el.style.color = obj.value;
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app',
        // 这里就是MVVM中的Model
        data: {
            curColor: 'green'
        },
        // 专门用于存储监听事件回调函数
        methods: {
        }
    });
</script>

自定义局部指令

自定义全局指令在任何一个Vue实例控制的区域中都可以使用
自定义局部指令只能在自定义的那个Vue实例中使用
局部指令定义方式:给创建Vue实例时传递的对象添加,指令定义内容即可,如下:

directives: {
    // key: 指令名称
    // value: 对象
    'color': {
        bind: function (el, obj) {
            el.style.color = obj.value;
        }
    }
}

示例如下:

<div id="app1">
<!-- 由于 app1 Vue对象中没有定义 color指令因此 该指令在 App1中不起作用-->
    <p v-color="'blue'">我是段落</p>
</div>
<div id="app2">
    <p v-color="'red'">我是段落</p>
</div>
<script>
    // 这里就是MVVM中的View Model
    let vue1 = new Vue({
        el: '#app1',
        // 这里就是MVVM中的Model
        data: {},
        // 专门用于存储监听事件回调函数
        methods: {}
    });
    // 这里就是MVVM中的View Model
    let vue2 = new Vue({
        el: '#app2',
        // 这里就是MVVM中的Model
        data: {},
        // 专门用于存储监听事件回调函数
        methods: {},
        // 专门用于定义局部指令的
        directives: {
            "color": {
                // 这里的el就是被绑定指令的那个元素
                bind: function (el, obj) {
                    el.style.color = obj.value;
                }
            }
        }
    });
</script>