模板语法概述
Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层组件实例的数据。所有 Vue.js 的模板都是合法的 HTML,所以能被遵循规范的浏览器和 HTML 解析器解析。
在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应性系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。
如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,你也可以不用模板,直接写渲染 (render) 函数,使用可选的 JSX 语法。
插值
文本(插值表达式)
数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:
<span>Message: {{ msg }}</span>
Mustache 标签将会被替代为对应组件实例中 msg property 的值。无论何时,绑定的组件实例上 msg property 发生了改变,插值处的内容都会更新。
原始 HTML
双大括号不会解析HTML 代码。为了输出真正的 HTML,你需要使用v-html 指令。
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
......
rawHtml: '<span style="color: red">This should be red.</span>'
注意: 在你的站点上动态渲染任意的 HTML 是非常危险的,因为它很容易导致 XSS 攻击。请只对可信内容使用 HTML 插值,绝不要将用户提供的内容作为插值。
Attribute
(Attribute : 元素标签的属性)
(property : 元素对象的属性)
ustache 语法不能在 HTML attribute 中使用,然而,可以使用 v-bind 指令:
<div v-bind:id="dynamicId"></div>
如果绑定的值是 null 或 undefined,那么该 attribute 将不会被包含在渲染的元素上。
对于布尔 attribute (它们只要存在就意味着值为 true),v-bind 工作起来略有不同,在这个例子中:
<button v-bind:disabled="isButtonDisabled">按钮</button>
如果 isButtonDisabled 的值是 truthy,那么 disabled attribute 将被包含在内。如果该值是一个空字符串,它也会被包括在内,与 <button disabled=""> 保持一致。对于其他错误的值,该 attribute 将被省略。
使用 JavaScript 表达式
对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>
指令
指令本质就是自定义属性
指令 (Directives) 是带有 v- 前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式 (v-for 是例外情况,稍后我们再讨论)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
数据绑定指令
v-text
为了: 填充纯文本
对比:
- 和插值表达式{{}} :
v-text会覆盖元素中原本的内容,插值表达式{{ }}只会替换自己的这个占位符,不会把整个元素内容替换。
- 和v-html :
v-text和{{}}表达式渲染数据,不解析标签。
v-html不仅可以渲染数据,而且可以解析标签。
示例:
<span v-text="msg"></span>
<!-- 等价于 -->
<span>{{msg}}</span>
v-html
为了 : 填充HTML片段,解析标签。
缺点 : 存在安全问题。在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用 v-html,永不用在用户提交的内容上。本网站内部数据可以用,来自第三方的数据不可用。
示例 :
HTML:
<div v-html="html"></div>
v-pre
为了 : 显示原始信息,跳过编译过程。
示例 :
HTML:
<span v-pre>{{ this will not be compiled }}</span>
显示 ==> {{ this will not be compiled }}
双向数据绑定
v-model
限制 : 表单 <input>、<textarea> 及 <select> 元素上
特点 :
v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
- text 和 textarea 元素使用 value property 和 input 事件;
- checkbox 和 radio 使用 checked property 和 change 事件;
- select 字段将 value 作为 prop 并将 change 作为事件。
注意 :
对于需要使用输入法 (如中文、日文、韩文等) 的语言,你会发现 v-model 不会在输入法组织文字过程中得到更新。如果你也想响应这些更新,请使用 input 事件监听器和 value 绑定,而不是使用 v-model。
示例 :
<input v-model="message"/>
MVVM设计思想
Vue.js通过MVVM实现双向数据绑定。
换个地仔细说说==>Vue学习笔记 - MVVM模型和MVC模型
事件绑定
v-on
缩写:@
用在普通元素上时,只能监听原生 DOM 事件。用在自定义元素组件上时,也可以监听子组件触发的自定义事件。
1.0.11+ 在监听自定义事件时,内联语句可以访问一个 $arguments 属性,它是一个数组,包含传给子组件的 $emit 回调的参数。
基本使用
示例:
HTML:
<div id='app'>
<div>{{num}}</div>
<div>
<button v-on:click='num++'>按钮1</button>
<!-- @后面没有冒号! -->
<button @click='num++'>按钮2</button>
<button @click='handle'>按钮3</button>
<button @click='handle()'>按钮3</button>
</div>
</div>
JS:
var vm = new Vue({
el: '#app',
data() {
return {
num: 0
}
},
methods: {
handle: function(){
console.log(this === vm);//true 这里的this就是Vue实例对象
this.num++;
}
}
})
参数传递方式
HTML:
<div id='app'>
<div>{{num}}</div>
<div>
<!-- 要想传递事件对象,参数必须放到最后一个,而且名字必须是 $event -->
<button @click='handle1(123, 456, $event)'>按钮1</button>
<button @click='handle2'>按钮2</button>
</div>
</div>
js:
handle1: function(p1, p2, event){//此处的 event 是形参,不是固定的
this.num++;
console.log(p1, p2, event.target);//通过event拿到触发事件的对象target },
handle2: function(event){//不传参时默认传递了$event
this.num++;
console.log(event.target);
},
总结:
- 如果事件直接绑定函数名称(不带括号的),那么默认会传递事件对象作为函数事件的第一个参数
- 如果事件绑定函数调用(带括号的),那么事件对象必须作为最后一个参数显式传递,并且事件对象的名称必须是
$event
修饰符
1、 .stop 阻止冒泡
调用 event.stopPropagation()
<!-- 停止冒泡 -->
<button @click.stop="doThis"></button>
2、 .prevent 阻止默认行为
调用 event.preventDefault()
<!-- 阻止默认行为 -->
<button @click.prevent="doThis"></button>
<!-- 阻止默认行为,没有表达式 -->
<form @submit.prevent></form>
修饰符可以串联写:
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat">
3、 .capture 添加事件侦听器时使用 capture 模式
<div v-on:click.capture="doThis">...</div>
4、 .self 只当事件是从侦听器绑定的元素本身触发时才触发回调
5、 .{keyCode | keyAlias} 只在指定按键上触发回调
<!-- 键修饰符,键别名 -->
<input @keyup.enter="onEnter">
<!-- 键修饰符,键代码 -->
<input @keyup.13="onEnter">
属性绑定
v-bind
缩写::
HTML:
<div id='app'>
<a :href='url'>baidu</a>
</div>
VUE:
data() {
return {
url: 'http://www.baidu.com'
}
},
样式绑定
class绑定
CSS:
.active {
border: 1px solid red;
width: 100px;
height: 100px;
}
.error {
background: orange;
}
.base {
font-size: 25px;
}
.text {
color: purple;
}
HTML:
<div id='app'>
<!-- 不影响默认class -->
<div class='base' :class='objClasses'>obj样式,推荐</div>
<div :class='arrClasses'>arr样式,不推荐</div>
<div :class='[activeClass, errorClass, {text: isTest}]'>
对象数组可以一起用,不推荐</div>
</div>
VUE:
data() {
return {
activeClass: 'active',
errorClass: 'error',
isTest: true,
arrClasses: [
'active',
'error'
],
objClasses: {
active: true,
error: true
}
}
},
style绑定
HTML:
<div id='app'>
<div :style='objStyles'>对象</div>
<div :style='[objStyles, overrideStyles]'>数组</div>
<button @click='handle'>切换样式</button>
</div>
VUE:
data() {
return {
objStyles: {
border: '1px solid blue',
width: '200px',
height: '200px'
},
overrideStyles: {
border: '5px solid orange',
backgroundColor: 'blue'
}
}
},
methods: {
handle: function(){
this.objStyles.height = '400px'
}
},
条件渲染
v-if、v-else-if、v-else
v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。
<h1 v-if="awesome">Vue is awesome!</h1>
推荐在 <template> 元素使用 v-if 条件渲染分组:
因为 v-if 是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个 <template> 元素当做不可见的包裹元素,并在上面使用 v-if。最终的渲染结果将不包含 <template> 元素。
一起使用的还有 v-else-if、v-else
用key管理可复用元素
例如,用户在不同的登录方式之间切换:
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address">
</template>
上面的代码中切换 loginType 将不会清除用户已经输入的内容。因为两个模板使用了相同的元素,<input> 不会被替换掉——仅仅是替换了它的 placeholder。
所以如果在输入框输入了文本,然后切换,发现输入框的文字仍然存在。
如果不需要复用元素,可以在元素添加具有唯一值的 key attribute 即可:
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input"> </template>
注意,<label> 元素仍然会被高效地复用,因为它们没有添加 key attribute
v-show
注意:
v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS property display
v-show 与 v-if 区别
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if 是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
不推荐同时使用 v-if 和 v-for,v-for 具有比 v-if 更高的优先级
循环遍历
遍历数组
<li :key='index' v-for='(item, index) in fruits'>{{item + '---' +index}}</li>
key: 帮助Vue区分不同的元素,从而提高性能。
遍历对象
<li v-for='(key, value) in objs'>{{key + "---" + value}}</li>
数据响应式
如何理解 :
- HTML中的响应式 : 屏幕尺寸变化导致样式变化。
- 数据的响应式 : 数据变化导致页面内容的变化。
数据绑定 : 数据填充到页签中。
v-once
为了 :只编译一次,显示内容后不再具有响应式。如果显示的内容不需要更改,可以使用v-once,可以提高性能。
示例 :
<div v-once>{{info}}</div>
其他指令
v-cloak
为了: 解决 插值表达式存在的闪动问题
原理: 先隐藏,替换好值后再显示
这个指令保持在元素上直到关联组件实例结束编译。和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到组件实例准备完毕。
示例:
css:
[v-cloak] {
display: none;
}
HTML:
<div v-cloak>
{{ message }}
</div>
<div> 不会显示,直到编译结束.
未完待续(不完整&&修饰符)。。。