Vue.js前端框架系统学习(5)——Vue指令之v-for, v-on, v-bind, v-model
接上一篇文章,这篇文章来整理一下其他的一些vue
指令。先申明一下,关于指令的一些概念都搬运自官网,如果有哪些不理解可以直接上官网进行学习。
列表渲染之v-for
-
Expects:
Array | Object | number | string | Iterable (since 2.6)
-
Usage:
基于源数据多次渲染元素或模板块。此指令之值,必须使用特定语法
alias in expression
,为当前遍历的元素提供别名:<div v-for="item in items"> {{ item.text }} </div>
另外也可以为数组索引指定别名 (或者用于对象的键):
<div v-for="(item, index) in items"></div> <div v-for="(val, key) in object"></div> <div v-for="(val, name, index) in object"></div>
v-for
的默认行为会尝试原地修改元素而不是移动它们。要强制其重新排序元素,你需要用特殊 attributekey
来提供一个排序提示:<div v-for="item in items" :key="item.id"> {{ item.text }} </div>
我们可以用 v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用 item in items
形式的特殊语法,其中 items
是源数据数组,而 item
则是被迭代的数组元素的别名。
//derectives.vue
<template>
<div>
<h1>Derectives</h1>
<ul>
<li v-for="item in items" :key="item.message">
{{item.message}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Derectives',
data () {
return {
items: [
{ message: 'name1' },
{ message: 'name2' }
]
}
}
}
</script>
v-for
还支持一个可选的第二个参数,即当前项的索引index
。
//derectives.vue
<template>
<div>
<h1>Derectives</h1>
<ul>
<li v-for="(item, index ) in items" :key="item.message">
{{ index }}+{{item.message}}+{{item.name}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Derectives',
data () {
return {
items: [
{ message: 'I am good', name: 'Andy' },
{ message: 'I am sad', name: 'Lious' }
]
}
}
}
</script>
可以完成这样的效果。
在刚刚的v-for
中,我使用到了:key
,也就是绑定关键字为message
,会根据message
的结果进行遍历。这个在后面会涉及。
官方给出的建议如是:
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一
key
attribute:<div v-for="item in items" v-bind:key="item.id"> //这边的v-bind可以简化为 : <!-- 内容 --> </div>
建议尽可能在使用
v-for
时提供key
attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。因为它是 Vue 识别节点的一个通用机制,
key
并不仅与v-for
特别关联。后面我们将在指南中看到,它还具有其它用途。
不要使用对象或数组之类的非基本类型值作为 v-for
的 key
。请用字符串或数值类型的值。
关于v-for的其他用法,还请移步Vue.js官网-列表渲染
v-on事件处理
-
缩写:
@
-
预期:
Function | Inline Statement | Object
-
参数:
event
-
修饰符:
.stop
- 调用event.stopPropagation()
。.prevent
- 调用event.preventDefault()
。.capture
- 添加事件侦听器时使用 capture 模式。.self
- 只当事件是从侦听器绑定的元素本身触发时才触发回调。.{keyCode | keyAlias}
- 只当事件是从特定键触发时才触发回调。.native
- 监听组件根元素的原生事件。.once
- 只触发一次回调。.left
- (2.2.0) 只当点击鼠标左键时触发。.right
- (2.2.0) 只当点击鼠标右键时触发。.middle
- (2.2.0) 只当点击鼠标中键时触发。.passive
- (2.3.0) 以{ passive: true }
模式添加侦听器
-
用法:
绑定事件监听器。事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略。
用在普通元素上时,只能监听原生 DOM 事件。用在自定义元素组件上时,也可以监听子组件触发的自定义事件。
在监听原生 DOM 事件时,方法以事件为唯一的参数。如果使用内联语句,语句可以访问一个
$event
property:v-on:click="handle('ok', $event)"
。从
2.4.0
开始,v-on
同样支持不带参数绑定一个事件/监听器键值对的对象。注意当使用对象语法时,是不支持任何修饰器的。
我们来实现一下
//derectives.vue
<template>
<div>
<h1>Derectives</h1>
<button @click="count += 1"> 点此按钮加一</button> //这里我将v-on简写为了@
<p>已经点击了{{count}} 下</p>
</div>
</template>
<script>
export default {
name: 'Derectives',
data () {
return {
count: 0 //初始化count为0
}
}
}
</script>
我们完成的事件即在每一次点击按钮时将count
加一,当然了这是最最简单的一种使用v-on
的方式。
我们需要用到vue中的一个methods
,也就是事件处理方法。
<template>
<div>
<h1>Derectives</h1>
<button @click="say('hello')"> Hello !</button>
<hr>
<button @click="greet">Greet</button>
</div>
</template>
<script>
export default {
name: 'Derectives',
data () {
return {
name: 'Andy'
}
},
//方法合集
methods: {
say: function (message) {
alert(message)
},
greet: function () {
alert('Welcome' + this.name) //this指向当前实例
}
}
}
</script>
我在这里写了两个click
事件,并绑定到了对应的方法。
其中say function 是一个有参的方法,可以接受一个message参数,并通过alert显示。
greet function 是无参的方法,它从当前实例中获取到name的值并拼接字符串后输出。
事件修饰符
在事件处理程序中调用
event.preventDefault()
或event.stopPropagation()
是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
为了解决这个问题,Vue.js 为 v-on
提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。
.stop
.prevent
.capture
.self
.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>
这边仅做搬运,个人觉得已经功能介绍已经很清楚了,可以自行尝试。
v-bind 绑定
-
缩写:
:
-
预期:
any (with argument 含参 ) | Object (without argument 无参 )
-
参数:
attrOrProp (optional)
-
修饰符:
.prop
- 作为一个 DOM property 绑定而不是作为 attribute 绑定。.camel
- (2.1.0+) 将 kebab-case attribute 名转换为 camelCase。(从 2.1.0 开始支持).sync
(2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的v-on
侦听器。
-
用法:
动态地绑定一个或多个 attribute,或一个组件 prop 到表达式。
在绑定
class
或style
attribute 时,支持其它类型的值,如数组或对象。可以通过下面的教程链接查看详情。在绑定 prop 时,prop 必须在子组件中声明。可以用修饰符指定不同的绑定类型。
没有参数时,可以绑定到一个包含键值对的对象。注意此时
class
和style
绑定不支持数组和对象。
我们来具体实现一下:
绑定HTML Class
通过给v-bind:class
传递一个对象,从而动态地切换class
<template>
<div>
<h1>Derectives</h1>
<div :class=" ClassObject "></div> // ClassObject在data中
</div>
</template>
<script>
export default {
name: 'Derectives',
data () {
return {
ClassObject: {
active: true,
error: false
} //这里定义了两个class属性active和error
}
},
}
</script>
这里我将active和error 两个class分别设为true和false.看一下页面渲染效果。
不难发现,只有true的active被加载到class中去了。
其他用法请参照官方文档。
绑定内联样式style
v-bind:style
的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:
<template>
<div>
<h1>Derectives</h1>
<div :style="styleObject">This is the styleObject.</div>
</div>
</template>
<script>
export default {
name: 'Derectives',
data () {
return {
styleObject: {
color: 'red',
fontSize: '30px'
}
}
},
methods: {
}
}
</script>
同样的,:style
可以将多个样式对象应用到同一个元素上。
v-model表单控件的绑定
-
预期:随表单控件类型不同而不同。
-
限制:
<input>
<select>
<textarea>
- components
-
修饰符:
-
用法:
在表单控件或者组件上创建双向绑定。
注意,这种v-model
的绑定形式为双向绑定
你可以用
v-model
指令在表单<input>
、<textarea>
及<select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model
本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
v-model
会忽略所有表单元素的 value
、checked
、selected
attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data
选项中声明初始值。
接下来用HTML中的表单元素做演示:
radio单选框
<template>
<div>
<h1>Derectives</h1>
<div id="radio">
<input type="radio" id='one' value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id='two' value="Two" v-model="picked">
<label for="two">Two</label>
<hr>
选择的为:{{picked}}
</div>
</div>
</template>
<script>
export default {
name: 'Derectives',
data () {
return {
picked: ''
}
}
}
</script>
select下拉菜单
<select v-model="selected">
<option disabled value="">请选择</option>
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
<span>Selected: {{ selected }}</span>
<script>
export default {
name: 'Derectives',
data () {
return {
select: ''
}
}
}
</script>
同样的,我们可以使用之前学到的v-for
列表渲染来实现这一功能。将option中的内容写到JS中。
<template>
<div>
<h1>Derectives</h1>
<hr>
<select v-model="selected">
<option v-for="option in options" :key="option.value">
{{option.text}}
</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
</template>
<script>
export default {
name: 'Derectives',
data () {
return {
selected: '',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
}
}
</script>
v-model 修饰符
这三个修饰符还是挺有用的
.lazy
在默认情况下,
v-model
在每次input
事件触发后将输入框的值与数据进行同步 (除了输入法组合文字时)。你可以添加lazy
修饰符,从而转为在change
事件_之后_进行同步:<!-- 在“change”时而非“input”时更新 --> <input v-model.lazy="msg">
.number
如果想自动将用户的输入值转为数值类型,可以给
v-model
添加number
修饰符:<input v-model.number="age" type="number">
这通常很有用,因为即使在
type="number"
时,HTML 输入元素的值也总会返回字符串。如>果这个值无法被parseFloat()
解析,则会返回原始的值。
.trim
如果要自动过滤用户输入的首尾空白字符,可以给
v-model
添加trim
修饰符:<input v-model.trim="msg">
其他用法请参照官方文档。
v-pre
-
不需要表达式
-
用法:
跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
<span v-pre>{{ this will not be compiled }}</span>
很显然,如果正常渲染的话是不会有Mustache标签,v-pre跳过了这一步,原样输出。
v-cloak
-
不需要表达式
-
用法:
这个指令保持在元素上直到关联实例结束编译。和 CSS 规则如
[v-cloak] { display: none }
一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。
<div v-cloak>
{{ message }}
</div>
这部分不会显示,直到编译结束。
v-once
从名字上也可以看出,只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
后面的一些是为了更快的渲染页面所做的优化,现阶段还用不到。
总结:
这篇文章主要完成了对v-for, v-on, v-bind, v-model四个指令的学习。如果有什么问题还请批评指正。