Vue.js 常用指令(一)

类似于 Vue.js 这种前端框架,提倡的是减少开发人员对 DOM 的直接操作,而是只关心对数据的操作,不用关心 DOM 元素的渲染。

v-cloak、v-text、v-bind、v-on 和 v-html

  • v-cloak:用于解决差值表达式闪烁问题
  • v-text:没有闪烁问题的,会覆盖元素中原本的内容,但是插值表达式 只会替换自己的这个占位符,不会把整个元素的内容清空
  • v-html:能够渲染 html 标签元素,而不是将其当做字符串渲染
  • v-bind:用于绑定属性
  • v-on:绑定事件

示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        /*v-cloak 需要指定 css 属性,即在渲染完成之前隐藏标签元素*/
        [v-cloak] {
            display: none;
        }
    </style>
</head>
<body>
    <div id="app">
        <p v-cloak>{{ msg }}</p>		<!--{{ }} 即为插值表达式-->
        <p v-text="msg">===</p>
        <p v-html="msg2"></p>
        <input type="button" v-bind:title="mytitle" value="按钮">
        <input type="button" value="按钮" v-on:click="show">
    </div>

    <script src="./lib/vue-2.4.0.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg: '123',
                msg2: '<h1>标题一</h1>',
                mytitle: '自定义title'
            },
             methods: {
                show: function() {
                    alert('Hello v-on!')
                }
            }
        })    
    </script>
</body>
</html>

v-on 和 跑马灯效果

效果:前后循环

步骤:

  • 截取第一个字符,和后面的字符,进行后前拼接,实现前面的在后面,后面的在前面
  • 开启定时器,循环跑
  • 关闭定时器

知识点:

  • v-on:绑定点击事件
  • substring:字符串截取
  • 定时器实现循环
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <input type="button" value="运行" @click="run">
        <input type="button" value="停止" @click="stop">
    
        <h4>{{ msg }}</h4>
    </div>
   

    <script src="./lib/vue-2.4.0.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg: '猥琐发育,别浪!!',
                intervalId: null,   // 计时器 ID
            },
            methods: {
                // 运行事件,截取字符串
                run() {
                    // 若 定时器 ID不为 null,说明是不是重新开始的计时器,直接返回,不需要重新开启一个新的计时器
                    if (this.intervalId !== null) return;

                    // 箭头函数中没有 this,即函数内的 this 和函数外的 this 一致
                    this.intervalId = setInterval(()=>{
                        var start = this.msg.substring(0, 1);
                        var end = this.msg.substring(1);
                        this.msg = end + start;
                    }, 400)
                    
                },

                // 停止计时器
                stop() {
                    clearInterval(this.intervalId);
                    // 重新赋值为 null,避免因停止后再启动,不能开启定时器
                    this.intervalId = null; 
                }
            }
        })
    </script>
</body>
</html>

Tips:在 vm 实例中,若要访问 data 中的数据,只需调用 this.属性即可,this 便代表 vm 实例!

v-on 和事件修饰符

  • .stop:阻止冒泡
  • .prevent:阻止默认事件
  • .capture:添加事件侦听器时使用事件捕获模式
  • .self:只当事件在该元素本身(比如不是子元素)触发时触发回调
  • .once:事件只触发一次

示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .inner {
            height: 150px;
            background-color: darkcyan;
        }

        .outer {
            padding: 40px;
            background-color: red;
        }
    </style>
</head>

<body>
    <div id="app">
        <!-- 阻止向外层元素冒泡 -->
        <!-- <div @click="divhandle" class="inner">
            <input type="button" @click.stop="btnhandle" value="按钮">
        </div> -->

        <!-- 阻止默认行为 -->
        <!-- <a href="https://www.baidu.com" @click.prevent="linkClick">百度</a> -->

        <!--实现捕获触发事件的机制 -->
        <!-- <div @click.capture="divhandle" class="inner">
            <input type="button" @click="btnhandle" value="按钮">
        </div> -->

        <!-- .self 只有点击自己才会触发 -->
        <!-- <div @click.self="divhandle" class="inner">
            <input type="button" @click="btnhandle" value="按钮">
        </div> -->

        <!-- .once 只触发一次, 事件修饰符可以嵌套,第一次点击会阻止 a 标签跳转,第二次点击就会跳转-->
        <!-- <a href="https://www.baidu.com" @click.prevent.once="linkClick">百度</a> -->

        <!-- .stop 与 .self 的区别 -->
        <div class="outer" @click="div2handle">
            <div @click.self="divhandle" class="inner">
                <!-- <input type="button" @click.stop="btnhandle" value="按钮"> -->
                <input type="button" @click="btnhandle" value="按钮">

            </div>
        </div>
    </div>

    <script src="./lib/vue-2.4.0.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {},
            methods: {
                divhandle() {
                    console.log('div handle 触发')
                },

                btnhandle() {
                    console.log('btn handle 触发')
                },

                linkClick() {
                    console.log('跳转链接!')
                },

                div2handle() {
                    console.log('外层 div');
                },
            }
        })
    </script>
</body>

</html>

概念

  • 冒泡:当点击以上 div 中的按钮时,同时也会触发 div 的事件,即同时会输出 divinput 的值,从里向外冒泡
  • 捕获:从外向里

.stop.self 的区别:

  • .self:只会阻止自己身上冒泡行为的触发,并不会真正阻止冒泡的行为。
  • .stop:会阻止事件向其外层冒泡的行为

v-model 和数据双向绑定

v-bind 只能进行单向数据绑定,v-model 可以实现表单元素和 Model 中数据的双向数据绑定。常见的表单的空间元素:input、select、textarea 等。

所谓的双向数据绑定即修改表单空间元素的值会更改 Vue 实例的值,更改 Vue 实例的值,相应地表单空间元素的值也会发生改变。

示例一:

<div id="app">
    <input type="text" v-model="msg">
    <h4>{{ msg }}</h4>
</div>

<script src="./lib/vue-2.4.0.js"></script>
<script>

    var vm = new Vue({
        el: '#app',
        data: {
            msg: '123'
        },
        methods: {

        }
    })
</script>

示例二:简易计算器

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>

    <div id="app">
        <input type="text" v-model="n1">
        <select v-model="opt">
            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>
        </select>
        <input type="text" v-model="n2">
        <input type="button" value="=" @click="calc">
        <input type="text" v-model="result">
    </div>

    <script src="./lib/vue-2.4.0.js"></script>
    <script>

        var vm = new Vue({
            el: '#app',
            data: {
                n1: 0,
                n2: 0,
                opt: '+',
                result: 0
            },
            methods: {
                calc() {
                    switch (this.opt) {
                        case '+':
                            this.result = parseInt(this.n1) + parseInt(this.n2);
                            break;
                        case '-':
                            this.result = parseInt(this.n1) - parseInt(this.n2);
                            break;
                        case '*':
                            this.result = parseInt(this.n1) * parseInt(this.n2);
                            break;
                        case '/':
                            this.result = parseInt(this.n1) / parseInt(this.n2);
                            break;
                    }
                }
            }
        })
    </script>
</body>

</html>

v-bind 修改样式

class 样式

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .red {
            color: red;
        }

        .thin {
            font-weight: 200;
        }
    </style>
</head>

<body>
    <div id="app">
        <!-- 传递一个数组 -->
        <!-- <p :class="['red', 'thin']">Vue 中 css 样式</p> -->

        <!-- 三元表达式,flag 为 true 应用 thin 样式 -->
        <!-- <p :class="['red', flag?'thin':'']">Vue 中 css 样式</p> -->

        <!-- 使用对象替换三元表达式,提高代码可读性 -->
        <!-- <p :class="['red', {'thin': flag}]">Vue 中 css 样式</p> -->

        <!-- 直接使用对象 -->
        <p :class="classObj">Vue 中 css 样式</p>

    </div>
    <script src="./lib/vue-2.4.0.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                flag: false,
                classObj: {red: true, thin: false}
            }
        })
    </script>
</body>

</html>
  • 传递一个数组
  • 三元表达式,不够灵活,不推荐使用
  • 直接使用对象形式,键需要单引号扩起来
  • v-bind:引用对象方法,放在 Vue 实例 data 属性中

内联样式

<body>
    <div id="app">
        <!-- 直接在元素上通过 `:style` 的形式,书写样式对象 -->
        <!-- 若样式中间有横杠 -,则必须用单引号包裹 -->
        <!-- <p :style="{color: 'red', 'font-size': '40px'}">Vue 中 css 样式</p> -->

        <!-- data 中定义样式,再 :style 中引用对象 -->
        <!-- <p :style="styleObj1">Vue 中 css 样式</p> -->

        <!-- 通过数组绑定多个样式 -->
        <p :style="[ styleObj1, styleObj2 ]">Vue 中 css 样式</p>


    </div>
    <script src="./lib/vue-2.4.0.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                styleObj1: { color: 'red', 'font-weight': 200 },
                styleObj2: { 'font-style': 'italic' }
            }
        })
    </script>
</body>

Tips:若样式中间有横杠 -,则必须用单引号包裹 ,如 font-size

v-for 和 key 属性

v-for 循环

循环普通数组

格式:item in 数组,若要获取索引,在 item 后面指定即可,索引从 0 开始。

 <div id="app">
    <!-- <li v-for="item in list">{{ item }}</li> -->
    <li v-for="(item, i) in list">索引:{{ i }},值: {{ item }}</li>
</div>

<script src="./lib/vue-2.4.0.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            list: [1, 2, 3]
        } 
    })    
</script>

循环对象数组

<div id="app">
    <li v-for="(item, i) in list">ID:{{ item.id }}, Name: {{ item.name }}, 索引:{{ i }}</li>
</div>

<script src="./lib/vue-2.4.0.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            list: [
            { id: 1, name: 'zs1' },
            { id: 2, name: 'zs2' },
            { id: 3, name: 'zs3' },
            { id: 4, name: 'zs4' }
            ]
        } 
    })    
</script>

循环对象

<div id="app">
    <li v-for="(val, key, i) in user">值: {{ val }}, 键: {{ key }}, 索引: {{ i }}</li>
</div>

<script src="./lib/vue-2.4.0.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            user: {
                id: 1,
                name: '托尼·屎大颗',
                gender: '男'
            }
        },
    })    
</script>

循环数字

<div id="app">
    <li v-for="count in 10">{{ count }}</li>
</div>

<script src="./lib/vue-2.4.0.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {},
    })    
</script>

Tips: 循环数字从 1 开始,而非 0


v-for 的 key 属性

2.2.0+ 的版本里,当在组件中使用 v-for 时,key 现在是必须的

  • v-for 循环的时候,key 属性只能使用 number 获取 string
  • key 在使用的时候,必须使用 v-bind 属性绑定的形式,指定 key 的值
  • 在组件中,使用 v-for 循环的时候,或者在一些特殊情况中,如果 v-for 有问题,必须 在使用 v-for 的同时,指定唯一的字符串/数字 类型 :key

示例:

以下示例动态向数组对象 list 中添加对象,勾选其中一项,当向后添加 push 时,不会更改所勾选的选项。

而当向前添加 unshift 时,则会更改所勾选的选项,这时就需要指定 key 属性,属性值且必须是 numberstring

<div id="app">
    ID: <input type="text" v-model='id'>
    NAME: <input type="text" v-model="name">
    <input type="button" value="添加" @click="add">

    <!-- 指定 key 属性 -->
    <!-- <p v-for="item in list"> -->
    <p v-for="item in list" :key="item.id">
        <input type="checkbox">{{ item.id }} -- {{ item.name }}
    </p>
</div>

<script src="./lib/vue-2.4.0.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            id: '',
            name: '',
            list: [
                { id: 1, name: '李斯' },
                { id: 2, name: '嬴政' },
                { id: 3, name: '赵高' },
                { id: 4, name: '韩非' },
                { id: 5, name: '荀子' }
            ]
        },
        methods: {
            add() {
                // this.list.push({id: this.id, name: this.name});
                this.list.unshift({id: this.id, name: this.name})
            }
        }

    })    
</script>

v-if 和 v-show

v-if 和 v-show 都是根据条件展示元素,但是两者还是有些差别。

  • v-if:每次都会重新删除或创建元素,有较高的切换性能消耗
  • v-show:每次不会重新进行 DOM 的删除和创建操作,只是切换了元素的 display:none 样式,有较高的初始渲染消耗
  • 如果元素涉及到频繁的切换,最后不要使用 v-if,而是推荐使用 v-show
  • 如果元素可能永远也不会被显示出来被用户看到,则推荐使用 v-if
 <div id="app">
    <input type="button" value="按钮" @click="toggle"> 

    <h3 v-show="flag">v-if 控制的元素</h3>
    <h3 v-show="flag">v-show 控制的元素</h3>
</div>

<script src="./lib/vue-2.4.0.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            flag: false
        },
        methods: {
            toggle() {
                this.flag=!this.flag
            }
        }

    })    
</script>

MVC 和 MVVM 的关系图解

总结

  • v-bind:绑定属性、包括 css 样式,简写::
  • v-model:表单空间元素,双向数据绑定,简写:@
  • v-for:循环数组、对象、数组对象,2.2+ 版本需注意 key 属性,属性值类似为 numberstring
  • v-ifv-show:都是根据条件显示元素,但是在渲染时还是有区别的
  • 绑定 css 样式两种方式:v-bind:classv-bind:style
  • vm 实例:el 指定要控制的区域,data:挂载数据,对象类型,methods:挂载方法/事件,对象类型
  • 事件修饰符:.stop、 .prevent、.capture、.self、.once
posted @ 2020-09-03 22:28  Hubery_Jun  阅读(249)  评论(0编辑  收藏  举报