为了账号安全,请及时绑定邮箱和手机立即绑定

Vue.js的点点滴滴(三)

https://img1.sycdn.imooc.com//5cdea54300015f9906000287.jpg

Vue.js指令总结:

指令 (Directives) 是带有 v- 前缀的特殊特性。指令特性的值预期是单个 JavaScript 表达式;

指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。

Vue指令总结如下:

1. v-if

如果,用于有条件性地渲染一块内容,这块内容只会在指令的表达式返回truthy值的时候被渲染;

比如:<div v-if="show">hello world</div>


v-else

与v-if配套使用,使用v-else指令来表示v-if的“else块”,它必须紧跟在带v-if或者v-else-if的元素的后面,否则它将不会被识别。

比如:

<div v-if="Math.random() > 0.5">Now you see me</div>

<div v-else>Now you don't</div>


v-else-if

充当v-if的“else-if块”,可以联系使用,它也必须紧跟在带v-if或者v-else-if的元素之后。

比如:

<div v-if="type === 'A'">A</div>

<div v-else-if="type === 'B'">B</div>

<div v-else-if="type === 'C'">C</div>

<div v-else>Not A/B/C</div>

实例代码1:


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue条件渲染</title>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./vue.js"></script>
</head>
<body>
<div id="app">
<div v-if="count > 0">
count 大于0, 当前count的值是:{{count}}
</div>
<div v-else-if="count < 0 && count > -5">
count 介于0和-5之间
</div>
<div v-else>
count的值是:{{count}}
</div>
<br>
<div v-show="count == -1">show: {{count}}</div>
{{msg}}
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
           msg: "Hello Vue.js",
           count: 10
}
})
</script>
</body>
</html>

实例代码2:


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>条件/列表渲染</title>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./vue.js"></script>
</head>
<body>
<div id="app">
<div v-for="item in list">{{item}}</div>
<hr color="red">
<div v-for="item1 in userList" v-bind:class="['active', 'add', 'more', {'another':item1.age < 30}]">   
{{item1.name}} -- {{item1.age}}
</div>
<hr color="red">
<div v-for="item2 in userList" v-bind:class="{'active': true}">
<div v-if="item2.age > 30">
<div v-if="item2.sex == '男'">
{{item2.name}}, 你老了,你个老男人
</div>
<div v-else-if="item2.sex == '女'">
{{item2.name}},你老了,你个老阿姨
</div>
</div>
<div v-else>
{{item2.name}},{{item2.age}}岁,好年轻
</div>
</div>
<hr color="red">
<div v-for="item3 in userList">
<div v-show="item3.age < 30" v-bind:style="style">
{{item3.name}}-{{item3.age}}-{{item3.sex}}
</div>
</div>
</div>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
           list: [1,2,3,4,5,6,7,8,9],
           userList: [{
           name: "刘豆豆",
           age: 23,
           sex: "男"
           },{
           name: "小三",
           age: 18,
           sex: "女"
           },{
           name: "老王",
           age: 40,
           sex: "男"
           },{
           name: "花花",
           age: 35,
           sex: "女"
           }],
           style: {
           color: 'red',
           textShadow: '0 0 5px green'
           }
}
})
</script>
</body>
</html>


2. v-show

用于根据条件展示元素的内容,带有v-show的元素始终会被渲染并保留在DOM中,

v-show只是简单地切换元素的CSS属性display,其属性值为none||block;

v-show不支持<template>元素,也不支持v-else.

比如:<h1 v-show="ok">Hello!</h1>


v-if 与 v-show的区别:

v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。

v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

实例代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue - v-show</title>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./vue.js"></script>
</head>
<body>
<div id="app">
<div v-show="count == -1">show1: {{count}}</div>
<div v-show="count >= 5">show2: {{count}}  {{msg}}</div>
<div v-if="count == 1">{{msg}}</div>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
           msg: "Hello Vue.js",
           count: 10
}
})
</script>
</body>
</html>


3. v-bind

绑定属性,用于响应式地更新HTML特性;

比如:<div v-bind:title="title">Hello World</div>

v-bind:class  绑定HTML Class,用于动态地切换class;

比如:<div v-bind:class="{ active: isActive }"></div>

v-bind:style  绑定内联样式,用于引入CSS样式渲染内容;CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用单引号括起来) 来命名

比如:<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

实例代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue-绑定class与样式</title>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./vue.js"></script>
</head>
<body>
<div id="app">
<!-- v-bind:class 绑定HTML class-->
<div v-bind:class="[activeClass, errorClass]">兴百姓苦</div>
<!-- v-bind:style 绑定CSS样式 -->
<div v-bind:style="{color: activeColor, fontSize: fontSize + 'px'}">亡百姓苦</div>
</div>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
activeClass: 'active',
errorClass: 'text-danger',
activeColor: 'red',
fontSize: 30
}
})
</script>
</body>
</html>


4. v-for

用于循环列表,添加 :key 提升渲染效率/性能, 要求每一项循环的key 不一样, 也可用 :key="index", 

如果对列表进行频繁的变更, 比如排序时, 使用 index 就不适合了

比如:<li v-for="(item index) of list" :key="item">{{item}}</li>

v-for=“item of list”,v-for表示循环list,依次输出item ,:key可以提升遍历效率,但key 值不能相同;key值相同时,用index做区别;

通常情况下,不推荐同时使用v-if和v-for。当同时使用它们时,v-for 具有比 v-if 更高的优先级。


v-for 指令根据一组数组的选项列表进行渲染。v-for 指令需要使用 item in items 形式的特殊语法,items 是源数据数组并且 item 是数组元素迭代的别名。

实例代码1:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue指令—— v-if,v-show,v-for</title>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./vue.js"></script>
</head>
<body>
<div id="root">
<div style="color: red;font-size: 30px;" v-if="show">hello world</div>
<br>
<div style="color: green;font-size: 30px;" v-if="show">hello world</div>
<button style="width: 80px; height: 30px;" v-on:click="handleClick">toggle</button>
<br>
<ul>
<li v-for="item of list">{{item}}</li>
</ul>
<ul>
<!--  v-for=“item of list”,v-for表示循环list,依次输出item ,:key可以提升遍历效率,但key 值不能相同;key值相同时,用index做区别-->
<li v-for="item of list" :key="item">#{{item}}</li>
</ul>
<ul>
<li v-for="(item, index) of list" :key="index">&{{item}}</li>
</ul>
</div>
<script type="text/javascript">
new Vue({
el: "#root",
data: {
           show: true,
           list: [1, 2, 3, 4]
},
methods: {
           handleClick: function(){
            this.show= !this.show;
           }
}
})
</script>
</body>
</html>

实例代码2:


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue —— v-for</title>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./vue.js"></script>
<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
</head>
<body>
<div id="app">
<ul>
<!-- 用 v-for 指令根据一组数组的选项列表进行渲染。v-for 指令需要使用 item in items 形式的特殊语法,items 是源数据数组并且 item 是数组元素迭代的别名。 -->
<li v-for="item in items" v-bind:style="{color: activeColor, fontSize: fontSize + 'px', textAlign: textAlign}">
{{item.message}}
    </li>
</ul>
</div>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
items: [
{message: '寒蝉凄切,对长亭晚,骤雨初歇。都门帐饮无绪,留恋处,兰舟催发。'},
{message: '执手相看泪眼,竟无语凝噎。念去去,千里烟波,暮霭沉沉楚天阔。'},
{message: '多情自古伤离别,更那堪,冷落清秋节!今宵酒醒何处?杨柳岸,晓风残月。'},
{message: '此去经年,应是良辰好景虚设。便纵有千种风情,更与何人说?'}
],
activeColor: 'blue',
fontSize: 30,
textAlign: 'center'
}
})
</script>
</body>
</html>



5. v-text

会直接输出html语句,会对模板数据进行转译

比如:<h1 style="color:blue;" v-text="content"></h1>


6. v-html

不会输出html语句,不会对模板数据进行转译

比如:<h1 style="color:green;" v-html="content"></h1>

实例代码:

<!DOCTYPE html>
<html>
<head>
<title>Vue入门</title>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./vue.js"></script>
</head>
<body>
<!--
v-text: 会进行转译
v-html: 不会进行转译
v-on: 用于绑定事件,可以简写为 @
-->
<div id="root">
<h1 style="color:red;">{{msg}}--{{number}}</h1>
<h1 style="color:blue;" v-text="number"></h1>
<h1 style="color:green;" v-html="number"></h1>
<div v-text="content"></div>
<br>
<div v-html="content"></div>
<div v-on:click="handleClick">{{msg}}</div>
</div>
<script type="text/javascript">
new Vue({
el: "#root",
data: {   /*数据项*/
msg: "Hello World",
number: 123,
content: "<h1 style='color:red;'>Hello World</h1>"
},
methods: {
handleClick : function(){   //事件方法
this.content="world"
}
}
})
</script>
</body>
</html>


7. v-model

 双向数据绑定,数据与页面的显示会同时变化;

比如:<input type="text" v-model="content">

使用v-model指令在表单 <input>、<textarea> 及 <select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。

它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。

v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值而总是将 Vue 实例的数据作为数据来源。

你应该通过 JavaScript 在组件的 data 选项中声明其初始值。

实例代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue-监听器</title>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./vue.js"></script>
</head>
<body>
<div id="app">
<input v-model="str1" />
<br>
<input v-model="str2" />
<br>
<input v-model="str3" />
<br>
    {{ fullStr }}
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#app",
data: {
str1: '天国虽美',
str2: '没有了你',
str3: '万杯觥筹只不过是提醒寂寞罢了',
fullStr: '天国虽美,没有了你,万杯觥筹只不过是提醒寂寞罢了'
},
watch: {
str1: function(val){
this.fullStr = val + ',' + this.str2 + ',' + this.str3
},
str2: function(val){
this.fullStr = this.str1 + ',' + val + ',' + this.str3
},
str3: function(val){
this.fullStr = this.str1 + ',' + this.str2 + ',' + val
}
}
})
</script>
</body>
</html>

v-model 在内部使用不同的属性为不同的输入元素并抛出不同的事件:

text 和 textarea 元素使用 value 属性和 input 事件;

checkbox 和 radio 使用 checked 属性和 change 事件;

select 字段将 value 作为 prop 并将 change 作为事件。


在文本区域插值 (<textarea>{{text}}</textarea>) 并不会生效,应用 v-model 来代替。

如果 v-model 表达式的初始值未能匹配任何选项,<select> 元素将被渲染为“未选中”状态。

对于单选按钮,复选框及选择框的选项,v-model 绑定的值通常是静态字符串 (对于复选框也可以是布尔值)


v-model数据绑定修饰符:

(1) .lazy : 在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 。

你可以添加 lazy 修饰符,从而转变为使用 change 事件进行同步。

比如:

<!-- 在“change”时而非“input”时更新 -->

<input v-model.lazy="msg" >


(2) .number : 给v-model添加.number修饰符,将用户的输入值自动转化为数值类型

比如: <input v-model.number="age" type="number">


(3) .trim : 给v-model添加.trim修饰符,可以自动过滤用户输入的首位空白字符。

比如:<input v-model.trim="msg">

实例代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>v-model用法</title>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./vue.js"></script>
</head>
<body>
<div id="app">
<!-- v-model绑定文本值 -->
<input v-model="username" placeholder="请输入用户名">
<p>您的用户名为: {{username}}</p>
    <br>
    <!-- v-model绑定多行文本值 -->
    <textarea v-model="message" placeholder="请输入您的座右铭"></textarea>
    <span>您的座右铭:</span><br>
    <p style="white-space: pre-wrap;">{{message}}</p>
    <br>
    <!-- v-model绑定单个复选框,绑定到布尔值 -->
    <input type="checkbox" id="checkbox" v-model="checked">
    <label for="checkbox">{{checked}}</label>
    <br>
    <!-- v-model绑定多个复选框,绑定到同一个数组 -->
    <p>请选择你的爱好:</p>
    <input type="checkbox" id="music" value="音乐" v-model="checkedNames">
    <label for="music">音乐</label>
    <input type="checkbox" id="movie" value="电影" v-model="checkedNames">
    <label for="movie">电影</label>
    <input type="checkbox" id="swimming" value="游泳" v-model="checkedNames">
    <label for="swimming">游泳</label>
    <input type="checkbox" id="travel" value="旅行" v-model="checkedNames">
    <label for="travel">旅行</label>
    <br>
    <span>您的爱好是: {{checkedNames}}</span>
    <br>
    <!-- v-model绑定单选按钮 -->
    <p>请选择您的性别:</p>
    <input type="radio" id="male" value="男" v-model="sex">
    <label for="male">男</label>
    <input type="radio" id="female" value="女" v-model="sex">
    <label for="female">女</label>
    <br>
    <span>您的性别是: {{sex}}</span>
    <br>
    <!-- v-model绑定单选选择框 -->
    <p>请选择您的出生地:</p>
    <select v-model="country">
    <option disabled="disabled" value="">请选择</option>
    <option>中国</option>
    <option>美国</option>
    <option>俄罗斯</option>
    <option>日本</option>
    <option>法国</option>
    <option>英国</option>
    </select>
    <br>
    <span>您的出生地是: {{country}}</span>
    <br>
    <!-- v-model绑定多项选择框,绑定到一个数组 -->
     <p>请选择您最喜欢的城市:</p>
    <select v-model="citys" multiple style="width: 100px;">
    <option>北京</option>
    <option>上海</option>
    <option>深圳</option>
    <option>纽约</option>
    <option>东京</option>
    <option>柏林</option>
    </select>
    <br>
    <span>您最喜欢的城市是: {{citys}}</span>
    <br>
    <!-- v-model绑定选择框,并用v-for渲染动态选项 -->
    <p>看作者学诗词:</p>
    <select v-model="poetryDemo">
    <option v-for="poetry in poetries" v-bind:value="poetry.value">
    {{poetry.text}}
    </option>
    </select>
    <span>诗词: {{poetryDemo}}</span>
    <br>
    <br>
    <!-- 当选中时,`picked` 为字符串 "a" -->
<input type="radio" v-model="picked" value="abc">
<!-- `toggle` 为 true 或 false -->
<input type="checkbox" v-model="toggle">
<!-- 当选中第一个选项时,`selected` 为字符串 "abc" -->
<select v-model="selectStr">
   <option value="abc">ABC</option>
</select>
<br><br>
<!-- v-model绑定复选框
        // 当选中时
toggle1 === 'yes'
// 当没有选中时
toggle1 === 'no'
-->
<input type="checkbox" v-model="toggle1" true-value="yes" false-value="no">
    <br><br>
    <!-- v-model绑定单选按钮 当选中时,pick === abc -->
    <input type="radio" v-model="pick" v-bind:value="abc">
    <br><br>
    <!-- v-model绑定选择框的选项 
     当选中时,typeof num => 'object'
                     num.number => 12345
    -->
    <select v-model="num">
    <!--内联对象字面量-->
    <option v-bind:value="{number:12345}">12345</option>
    </select>
    <!-- v-model使用修饰符 -->
    <p>一句话证明自己</p>
    <input v-model.lazy="msg1"><br>
    <span>你说的是:{{msg1}}</span>
    <br>
    <p>请输入您的年龄:</p>
    <input type="number" v-model.number="age"><br>
    <span> 您的年龄是:{{age}}</span>
    <br>
    <p>请输入一段文本信息:</p>
    <input v-model.trim="msg2"><br>
    <span>文本信息: {{msg2}}</span>
</div>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
username: '',
message: '',
checked: true,
checkedNames: [],
sex: '',
country: '',
citys: [],
poetryDemo: '岑夫子,丹丘生,将进酒,杯莫停。',
poetries: [
                {text: '李白', value: '岑夫子,丹丘生,将进酒,杯莫停。'},
                {text: '苏轼', value: '不思量。自难忘。千里孤坟,无处话凄凉。'},
                {text: '李煜', value: '剪不断,理还乱,是离愁,别是一般滋味在心头。'},
                {text: '佚名', value: '不信抬头看,苍天绕过谁'}
],
picked: '',
toggle: true,
selectStr: '',
toggle1: '',
pick: '',
num: '',
msg1: '',
age: '',
msg2: ''
}
})
</script>
</body>
</html>

8. v-on

绑定事件,用于监听DOM事件,在触发的时候运行一些JavaScript代码;简化写法:@

比如:<button v-on:click="handleClick">toggle</button>

上面的代码等价于:<button @click="handleClick">toggle</button>

Vue.js 为 v-on 提供了事件修饰符,按键修饰符,系统修饰键,鼠标按钮修饰符等。

实例代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue - v-on</title>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./vue.js"></script>
</head>
<body>
<!-- v-on:监听事件-->
<div id="example">
<button v-on:click="counter += 1">加1计数器</button>
<p>点击次数:{{counter}}</p>
</div>
<script type="text/javascript">
new Vue({
el: "#example",
data: {
counter: 0
}
})
</script>
</body>
</html>

修饰符是由点开头的指令后缀来表示的。

(1)事件修饰符如下:

.stop

.prevent

.capture

.self

.once

.passive

.once

.passive


用法及作用如下:

<!-- 阻止单击事件继续传播 -->

<a v-on:click.stop="doThis"></a>


<!-- 提交事件不再重载页面 -->

<form v-on:submit.prevent="onSubmit"></form>


<!-- 修饰符可以串联 -->

<a v-on:click.stop.prevent="doThat"></a>


<!-- 只有修饰符 -->

<form v-on:submit.prevent></form>


<!-- 添加事件监听器时使用事件捕获模式 -->

<!-- 即元素自身触发的事件先在此处理,然后才交由内部元素进行处理 -->

<div v-on:click.capture="doThis">...</div>


<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->

<!-- 即事件不是从内部元素触发的 -->

<div v-on:click.self="doThat">...</div>


<!-- 点击事件将只会触发一次 -->

<a v-on:click.once="doThis"></a>

.once 修饰符还能被用到自定义的组件事件上。


Vue 还对应 addEventListener 中的 passive 选项提供了 .passive 修饰符。

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->

<!-- 而不会等待 `onScroll` 完成  -->

<!-- 这其中包含 `event.preventDefault()` 的情况 -->

<div v-on:scroll.passive="onScroll">...</div>

这个 .passive 修饰符尤其能够提升移动端的性能。


使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。

因此,用 v-on:click.prevent.self 会阻止所有的点击,

而 v-on:click.self.prevent 只会阻止对元素自身的点击。


事件修饰符.passive 和 .prevent 不能同时使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。

请记住,.passive 会告诉浏览器你不想阻止事件的默认行为。


(2)按键修饰符

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

比如:

<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->

<input v-on:keyup.enter="submit">

你可以直接将 KeyboardEvent.key 暴露的任意有效按键名转换为 kebab-case 来作为修饰符。


<input v-on:keyup.page-down="onPageDown">

在上述示例中,处理函数只会在 $event.key 等于 PageDown 时被调用。


按键码KeyCode的事件用法虽然已被废弃,但是在Vue中使用KeyCode特性也是可以的,为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名,如下:

.enter

.tab

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

.esc

.space

.up

.down

.left

.right


另外我们可以通过全局config.keyCodes对象自定义按键修饰符别名,如下:

// 可以使用 `v-on:keyup.f1`

Vue.config.keyCodes.f1 = 112


(3)系统修饰键

Vue为我们提供了如下系统修饰键,来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。

.ctrl

.alt

.shift

.meta

.exact


用法如下:

<!-- Alt + C -->

<input @keyup.alt.67="clear">


<!-- Ctrl + Click -->

<div @click.ctrl="doSomething">Do something</div>


.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。

<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->

<button @click.ctrl="onClick">A</button>


<!-- 有且只有 Ctrl 被按下的时候才触发 -->

<button @click.ctrl.exact="onCtrlClick">A</button>


<!-- 没有任何系统修饰符被按下的时候才触发 -->

<button @click.exact="onClick">A</button>


请注意修饰键与常规按键不同,在和 keyup 事件一起用时,事件触发时修饰键必须处于按下状态。

换句话说,只有在按住 ctrl 的情况下释放其它按键,才能触发 keyup.ctrl。而单单释放 ctrl 也不会触发事件。

如果你想要这样的行为,请为 ctrl 换用 keyCode:keyup.17。


(4)鼠标按钮修饰符

鼠标按钮修饰符限制处理函数仅响应特定的鼠标按钮,具体如下:

.left

.right

.middle

实例代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue</title>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./vue.js"></script>
</head>
<body>
<div id="app">
<input v-model="newTodo" v-on:keyup.enter="addTodo">
<ul>
<li v-for="todo in todos">
<span>{{todo.text}}</span>
<button v-on:click="removeTodo($index)">X</button>
</li>
</ul>
</div>
<script type="text/javascript">
new Vue({
el: "#app",
        data: {
        newTodo: '',
        todos: [
               {text: 'Add some todos' }
        ]
        },
        methods: {
        addTodo: function(){
        var text = this.newTodo.trim()
        if(text){
        this.todos.push({text: text})
        this.newTodo = ''
        }
        },
        removeTodo: function(index){
        this.todos.splice(index, 1)
        }
        }
})
</script>
</body>
</html>


9.自定义指令

在 Vue2.0 中,代码复用和抽象的主要形式是组件。有时候,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。

(1)自定义全局指令,语法如下:

Vue.directive('指令名', {

//钩子函数

})

比如:

// 注册一个全局自定义指令 `v-focus`

Vue.directive('focus', {

  // 当被绑定的元素插入到 DOM 中时……

  inserted: function (el) {

    // 聚焦元素

    el.focus()

  }

})


(2)自定义局部指令

在new Vue()实例内部,定义如下:

directives: {

指令名: {

   //指令的定义

}

}

比如:

directives: {

  focus: {

    // 指令的定义

    inserted: function (el) {

      el.focus()

    }

  }

}


在自定义指令的时候,需要用到指令钩子函数。具体可选的钩子函数如下:

(1)bind: 只调用一次,用于进行一次性的初始化设置,当指令第一次绑定到元素时调用。

(2)inserted: 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

(3)update: 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。

(4)componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

(5)unbind:只调用一次,指令与元素解绑时调用。


指令钩子函数的参数:

(1)el:指令所绑定的元素,可以用来直接操作 DOM 。

(2)binding:一个对象,包含以下属性:

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 }。

(3)vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。

(4)oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

实例代码1:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue自定义全局指令</title>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./vue.js"></script>
</head>
<body>
<div id="app" v-demo:foo.a.b="message">
</div>
<script type="text/javascript">
//自定义全局指令v-demo
Vue.directive('demo', {
//钩子函数
bind: function(el, binding, vnode){
var s = JSON.stringify
el.innerHTML = 
   'name: ' + s(binding.name) + '<br>' + 
   'value: ' + s(binding.value) + '<br>' + 
   'expression: ' + s(binding.expression) + '<br>' + 
   'arg: ' + s(binding.arg) + '<br>' + 
   'modifiers: ' + s(binding.modifiers) + '<br>' + 
   'vnode keys: ' + Object.keys(vnode).join(', ') 
}
})
new Vue({
el: "#app",
data: {
message: "一个人的寂寞两个人的错"
}
})
</script>
</body>
</html>

实例代码2:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue-自定义全局指令</title>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./vue.js"></script>
</head>
<body>
<div id="app">
<p v-tack:left="[dynamicleft]">
曾经有一份美味的鸡腿,放在我面前,我没有好好珍惜,等别人吃完了,我才后悔莫及。如果再来一份,别人一定抢不过我。
</p>
<p v-tack:top="[dynamictop]">爱别离,怨长久,求不得, 放不下</p>
</div>
<script type="text/javascript">
//自定义全局指令 v-tack
Vue.directive('tack', {
//钩子函数
  bind(el, binding, vnode) {
    el.style.position = 'fixed';
    el.style.color = 'red';
    el.style.fontSize = '25px';
    el.style.boxShadow = '5px 10px 5px #00ff00';
    el.style.border = '4px solid #a1a1a1';
    const s = (binding.arg == 'left' ? 'left' : 'top');
    el.style[s] = binding.value + 'px';
  }
})
new Vue({
el: "#app",
data() {
           return {
             dynamicleft: 1200,
             dynamictop: 500
           }
}
})
</script>
</body>
</html>

实例代码3:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>vue-自定义局部指令</title>
<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="./vue.js"></script>
</head>
<body>
<div id="app">
<div v-users="userList">{{userList}}</div>
    
    <br><br>
<div v-for="us in userList">
<div v-users="us">{{us.name}}</div>
</div>
    <br><br>
<div v-demo="userList"></div>
</div>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
userList: [{
name: "刘豆豆",
age: 22
},{
name: "小三",
age: 18
}]
},
//自定义局部指令
directives: {
users: {
                 bind(el){
                 el.style.color = 'red';
                 el.style.fontSize = '25px';
                 }
},
demo: {
bind: function(el, binding){
var s = JSON.stringify
el.style.color = 'green';
el.style.border = "2px solid #00ff00";
el.innerHTML = 
   'name: ' + s(binding.name) + '<br>' + 
   'value: ' + s(binding.value) + '<br>'
}
}
}
})
</script>
</body>
</html>

更多关于Vue.js的点点滴滴未完待续,相关实例代码后面会开放,请多多支持我!

点击查看更多内容
2人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
1.5万
获赞与收藏
8507

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消