Vue.js 内置指令

        Vue.js 的指令是带有特殊前缀 “v-“ 的 HTML 特性。它绑定一个表达式,并将一些特性应用到 DOM 上。

一、基本指令

1.1 v-cloak

        v-cloak 不需要表达式,它会在 Vue 实例结束编译时从绑定的 HTML 元素上移除,经常和 CSS 的 display: none ;配合使用:


    <div id="app" v-cloak>
        {{ message }}
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                message: '这是一段文本'
            }
        })
    </script>

        这时虽然已经加了指令 v-cloak ,但其实并没有起到任何作用,当网速较慢、Vue.js 文件还没有加载完时,在页面上会显示 {{ message }} 的字样,直到 Vue 创建实例、编译模板时,DOM 才会被替换,所以这个过程屏幕是有闪动的。只要加一句 CSS 就可以解决这个问题了:


    [v-cloak] {
        display: none;
    }

        在一般情况下,v-cloak 是一个解决初始化慢导致页面闪动的最佳实践,对于简单的项目很实用,但是在具有工程化的项目里,比如在项目的 HTML 机构只有一个空的 div 元素,剩余的内容都是由路由去挂载不同组件完成的,所以不再需要 v-cloak 。

1.2 v-once

        v-once 也是一个不需要表达式的指令,作用是定义它的元素或组件只渲染一次,包括元素或组件的所有子节点。首次渲染后,不再随数据的变化重新渲染,将被视为静态内容,例如:

<div id="app">
    <span v-once>{{ message }}</span>
    <div v-once>
        <span>{{ message }}</span>
    </div>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            message: '这是一段文本'
        }
    })
</script>

        v-once 在业务中很少使用,但当需要进一步优化性能时,可能会用到。

二、条件渲染指令

2.1 v-if,v-else-if,v-else

        与 JavaScript 的条件语句 if、else、else if 类似,Vue.js 的条件指令可以根据表达式的值在 DOM 中渲染或销毁元素/组件,例如:

<div id="app">
    <p v-if="status === 1">当status为1时显示该行</p>
    <p v-else-if="status === 2">当status为2时显示该行</p>
    <p v-else>否则显示该行</p>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            status: 1
        }
    })
</script>

        v-else-if 要紧跟 v-if,v-else 要紧跟 v-else-if 或 v-if ,表达式的值为真时,当前元素/组件及所有子节点将被渲染,为假时被移除。如果一次判断的是多个元素,可以在 Vue.js 内置的<template>元素上使用条件指令,最终渲染的结果不会包含该元素,例如:

<div id="app">
    <template v-if="status ==== 1">
        <p>这是一段文本</p>
        <p>这是一段文本</p>
        <p>这是一段文本</p>
    </template>
</div>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            status: 1
        }
    })
</script>

        Vue 在渲染元素时,出于效率考虑,会尽可能地复用已有的元素而非重新渲染,比如下面的示例:

   <div id="app">
        <template v-if="type === 'name'">
            <label>用户名:</label>
            <input placeholder="输入用户名"》
        </template>
        <template v-else>
            <label>邮箱:</label>
            <input placeholder="输入邮箱"》
        </template>
        <button @click="handleToggleClick">切换输入类型</button>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                type: 'name'
            },
            nethods: {
                handleToggleClick: function() {
                    this.type = this.type === 'name' ? 'mail' : 'name';
                }
            }
        })
    </script>

        这样键入内容后,点击切换按钮,虽然 DOM 变了,但是之前在输入框键入的内容并没有改变,只是替换了 placeholder 的内容,说明 <inpout> 元素被复用了。

        如果不希望这样复用,可以使用 Vue.js 提供的 key 属性,它可以让你自己决定是否要复用元素,key 的值必须唯一的,例如:

 <div id="app">
        <template v-if="type === 'name'">
            <label>用户名:</label>
            <input placeholder="输入用户名" key="name-input">
        </template>
        <template v-else>
            <label>邮箱:</label>
            <input placeholder="输入邮箱" key="mail-input">
        </template>
        <button @click="handleToggleClick">输入类型切换</button>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                type: 'name'
            },
            methods: {
                handleToggleClick: function() {
                    this.type = this.type === 'name' ? 'mail' : 'name';
                }
            }
        })
    </script>

2.2 v-show

        v-show (v-show 不能在<template>上使用)的用法与 v-if 基本一致,只不过 v-show 是改变元素的 CSS 属性 display 。当 v-show 表达式的值为 false 时,元素会隐藏,查看 DOM 结构会看到元素上加载了内联样式 display: none;,例如:

    <div id="app">
        <p v-show="status === 0">当 status 为 0 时显示该行</p>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                status: 1
            }
        })
    </script>

        渲染后的结果为:

<p style="dispaly: none;">当 status 为 1 时显示该行</p>

2.3 v-if 与 v-show 的选择

        v-if 和 v-show 具有类似的功能,不过 v-if 才是真正的条件渲染,它会根据表达式适当地销毁或重建元素及绑定的事件或子组件。若表达式初始值为 false ,则一开始元素/组件并不会渲染,只有当条件第一次变为真时才开始编译。

        而 v-show 只是简单的 CSS 属性切换,无论条件真与否,都会被编译。相比之下,v-if 更适合条件不经常改变的场景,因为它切换开销相对较大,而 v-show 适用于频繁切换条件。

三、列表渲染指令 v-for

3.1 基本用法

        当需要一个数组遍历或枚举一个对象循环显示时,就会用到列表渲染指令 v-for 。它的表达式需要结合 in 来使用,类似 item in items 的形式,例如:

<div id="app">
    <ul>
        <li v-for="book in books">{{ book.name }}</li>
    </ul>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            books: [
                { name: '《Oracle 从删库到跑路》'},
                { name: '《MySql 从删库到跑路》' },
                { name: '《JavaScript 高级程序设计》' }
            ]
        }
    })
</script>

        在表达式中,books 是数据,book 是当前数组元素的别名,循环出的每个 <li> 内的元素都可以访问到对应的当前数据 book 。列表渲染也支持用 of 来代替 in 作为分割符,它更接近 JavaScript 迭代器的语法:

<li v-for="book of books">{{ book.name }}</li>

        v-for 的表达式支持一个可选参数作为当前项的索引,例如:

<div id="app">
    <ul>
        <li v-for="book in books">{{ index }} - {{ book.name }}</li>
    </ul>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            books: [
                { name: '《Oracle 从删库到跑路》'},
                { name: '《MySql 从删库到跑路》' },
                { name: '《JavaScript 高级程序设计》' }
            ]
        }
    })
</script>

        分割符 in 前的语句使用括号,第二项就是 books 当前项的索引 (在 Vue.js 1.x 的版本,这里的 index 也可以由内置的 $index 代替,不过,在 2.x 版本里取消了该用法)。

        与 v-if 一样,v-for 也可以用在内置标签 <template> 上,将多个元素进行渲染:

<div id="app">
    <ul>
        <template v-for="book in books">
            <li>书名:{{ book.name }}</li>
            <li>作者:{{ book.author }}</li>
        </template>
    </ul>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            books: [
                {
                    name: '《Oracle 从入门到跑路》',
                    author: 'Mart'
                },
                {
                    name: '《MySql 从入门到跑路》',
                    author: '尹成'
                },
                {
                    name: '《JavaScript 高级程序设计》',
                    author: 'Nicholas C.Zakas'
                }
            ]
        }
    })
</script>

        除数组外,对象的属性也是可以遍历的,例如:

<div id="app">
    <span v-for="value in user">{{ value }}</span>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            user: {
                name: '王麻子',
                gender: '男',
                age: 28
            }
        }
    })
</script>

        渲染后的结果为:

<span>王麻子</span><span>男</span><span>28</span>

        遍历对象属性时,有两个可选参数,分别是键名和索引:

<div id="app">
    <ul>
        <li v-for="(value, key, index) in user" >
            {{ index }} - {{ key }} : {{ value }}
        </li>
    </ul>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            user: {
                name: '王麻子',
                gender: '男',
                age: 28
            }
        }
    })
</script>

        v-for 还可以迭代整数:

<div id="app">
    <span v-for="n in 100">{{ n }}</span>
</div>
<script>
    var app = new Vue({
        el: '#app'
    })
</script>

3.2 数组更新

        Vue 的核心是数据与视图的双向绑定,当我们修改数组时,Vue 会检测到数据变化,所以用 v-for 渲染的视图也会立即更新。Vue 包含了一组观察数组变异的方法,使用它们改变数组也会触发视图更新:

        ·    push()

        ·    pop()

        ·    shift()

        ·    unshift()

        ·    splice()

        ·    sort()

        ·    reverse()

        例如,将之前的示例的数据 books 添加一项:

app.books.push({
    name: '《CSS揭秘》',
    author: '[希] Lea Verou'
});

        使用上述方法会改变被这些方法调用的原始数组,有些方法不会改变原数组,例如:

        ·    filter()

        ·    concat()

        ·    slice()

        它们返回的是一个新数组,在使用这些非变异方法时,可以用新数组来替换原数组,还是之前展示示例,找出含有 JavaScript 关键词的书目,例如:

        

<div id="app">
    <ul>
        <template v-for="book in books">
            <li>书名:{{ book.name }}</li>
            <li>作者:{{ book.author }}</li>
        </template>
    </ul>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            books: [
                {
                    name: '《Oracle 从入门到跑路》',
                    author: 'Mart'
                },
                {
                    name: '《MySql 从入门到跑路》',
                    author: '尹成'
                },
                {
                    name: '《JavaScript 高级程序设计》',
                    author: 'Nicholas C.Zakas'
                }
            ]
        }
    });

    app.books = app.books.filter(function (item) {
        return item.name.match(/JavaScript/);
    });
</script>

        渲染的结果中,只显示了书名中含有 JavaScript 的选项。

        Vue 在检测到数组变化时,并不是直接重新渲染整个列表,而是最大化地复用 DOM 元素。替换的数组中,含有相同元素的项不会被重新渲染,因此可以大胆地用新数组来替换旧数组,不用担心性能问题。

        需要注意的是,以下变动的数组中,Vue 是不能检测到的,也不会触发视图更新:

        ·    通过索引直接设置项,比如 app.books[2]={...} 。

        ·    修改数组长度,比如 app.books.length = 1 。

        解决第一个问题可以用两种方法实现同样的效果,第一种是使用 Vue 内置的 set 方法:

Vue.set(app.books, 3, {
    name: '《CSS 揭秘》',
    author: '[希] Lea Verou'
});

        如果是在 webpack 中使用组件化的方式,默认是没有导入 Vue 的,这是可以使用 $set ,例如:

this.$set(app.books, 3, {
    name: '《CSS 揭秘》',
    author: '[希] Lea Verou'
})

        这里的 this 指向的就是当前组件实例,即 app 。在非 webpack 模式下也可以用 $set 方法,例如 app.$set(...) 。另一种方法:

app.books.splice(3, 1, {
    name: '《CSS 揭秘》',
    author: '[希] Lea Verou'
})

        第二个问题也可以直接用 splice 来解决:

app.books.splice(1);

3.3 过滤与排序

        当你不想改变原数组,想通过一个数组的副本来做过滤或排序的显示时,可以使用计算属性来返回过滤或排序后的数组,例如:

<div id="app">
    <ul>
        <template v-for="book in filterBooks">
            <li>书名:{{ book.name }}</li>
            <li>作者:{{ book.author }}</li>
        </template>
    </ul>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            books: [
                {
                    name: '《Oracle 从入门到跑路》',
                    author: 'Mart'
                },
                {
                    name: '《MySql 从入门到跑路》',
                    author: '尹成'
                },
                {
                    name: '《JavaScript 高级程序设计》',
                    author: 'Nicholas C.Zakas'
                }
            ]
        },
        computed: {
            filterBooks: function () {
                return this.books.filter(function (book){
                    return book.name.match(/JavaScript/);
                });
            }
        }
    })
</script>

        上例是把书名中包含 JavaScript 关键词的数据过滤出来,计算属性 filterBooks 依赖 books,但是不会修改 books 。实现排序也是类似的,比如:

            sortedBooks: function () {
                return this.books.sort(function (a, b){
                    return a.name.length < b.name.length;
                });
            }

        在 Vue.js 2.x 中废弃了 1.x 中内置的 limitBy,filterBy 和 orderBy 过滤器,统一改用计算属性来实现。

四、方法与事件

4.1 基本用法

        Vue 事件处理的概念 v-on ,在事件绑定上,类似原生 JavaScript 的 onclick 等写法,也是 HTML 上进行监听的。比如,监听一个按钮的点击事件,设置一个计数器,每次点击都加 1 :

<div id="app">
    点击计数:{{ counter }}
    <button @click="counter++">+ 1</button>
</div>
<script>
    new Vew({
        el: '#app',
        data: {
            counter: 0
        }
    })
</script>

        @click 的表达式可以直接使用 JavaScript 语句,也可以是一个在 Vue 实例中 methods 选项内的函数名,比如对上例进行扩展,再增加一个按钮,点击一次,计数器加100 ;

<div id="app">
    点击计数:{{ counter }}
    <button @click="handleAdd()">+ 1</button>
    <button @click="handleAdd(100)">+ 100</button>
</div>
<script>
    new Vew({
        el: '#app',
        data: {
            counter: 0
        },
        methods: {
            handleAdd: function (count) {
                count = count || 1;
                // this 指向当前 Vue 实例 app
                this.counter += count;
            }
        }
    })
</script>

        在 methods 中定义了我们需要的方法供 @click 调用,需要注意的是,@click 调用的方法名后可以不跟括号“()”。此时,如果该方法有参数,默认会将原生对象 event 传入。      

        这种在 HTML 元素上监听事件的设计看似将 DOM 与 JavaScript 紧耦合,违背分离的的原理,实则刚好相反。因为通过HTML 就可以知道调用的是哪个方法,将逻辑与 DOM 解耦,便于维护。最重要的是,当 ViewModel 销毁时,所有的事件处理器都会自动删除,无须自己清理。

        Vue 提供了一个特殊变量 $event , 用于访问原生 DOM 事件,比如,可以阻止链接打开:

<div id="app">
    <a href="https://www.baidu.com" @click="handleClick('禁止打开', $event)">打开链接</a>
</div>
<script>
    var app = new Vue({
        el: '#app',
        methods: {
            handleClick: function (message, event) {
                event.preventDefault();
                window.alert(message);
            }
        }
    })
</script>

4.2 修饰符

        上述使用的 event.preventDefault() 也可以用 Vue 事件的修饰符来实现,在 @绑定的事件后加小圆点” . “,再跟一个后缀来使用修饰符。Vue 支持以下修饰符:

        ·    .stop

        ·    .prevent

        ·    .capture

        ·    .self

        ·    .once

        具体用法如下:

<!-- 阻止单击事件冒泡  -->
<a @click.stop="handle"></a>
<!-- 提交事件不再重载页面 -->
<form @submit.prevent="handle"></form>
<!-- 修饰符可以串联 -->
<a @click.stop.prevent="handle"></a>
<!-- 只有修饰符 -->
<form @submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<div @click.capture="handle">...</div>
<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
<div @click.self="handle">...</div>
<!-- 只触发一次,组件同样适用 -->
<div @click.once="handle">...</div>

        在表单元素上监听键盘事件时,还可以使用按键修饰符,比如按下具体某个键时才调用方法:

<!-- 只有在 keyCode 是 32 时调用 vm.submit() -->
<input @keyup.32="submit">
<!-- 也可以自己配置具体按键 -->
Vue.config.keyCodes.f1 = 112;       // 全局定义后,就可以使用 @keyup.f1

        除了具体的某个 keyCode 外,Vue 还提供了一些快捷名称,以下是全部的别名:

        ·    .enter

        ·    .tab

        ·    .delate (捕获 ”删除“ 和 ”退格“ 键)

        ·    .esc

        ·    .space

        ·    .up

        ·    .down

        ·    .left

        ·    .right

        这些按键修饰符也可以组合使用,或和鼠标一起配合使用:

        ·    .ctrl

        ·    .alt

        ·    .shift

        ·    .meta (Mac 下是 Command 键,Windows 下是窗口键)

        例如:

<!-- Shift + S -->
<input @keyup.shift.83="handleSave">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do someting</div>

 

转载于:https://my.oschina.net/u/3375733/blog/2877823

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值