目录
计算属性:computed声明一个计算属性reversedMessage
侦听属性:watch有一些数据需要随着其它数据变动而变动时使用
计算属性的 setter,计算属性默认只有 getter,需要时可以提供一个 setter
侦听器:当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
1、模板语法
v-bind:绑定HTML 特性,<h2 v-bind:title="title"></h2>。布尔特性:<button v-bind:disabled="isButtonDisabled">Button</button>,如果
isButtonDisabled
的值是null
、undefined
或false
,则disabled
特性甚至不会被包含在渲染出来的<button>
元素中。
v-if:条件,如:<p v-if="bool">是否显示</p>
v-for:循环数据,如:<p v-for="arr in arrs">{{ arr.attr }}</p>
v-on:事件,如:<button v-on:click="function">点击</button>
v-model:实现表单输入和应用状态之间的双向绑定,如:<p>{{ message }}</p> <input v-model="message">
v-once:一次性的插值,当数据改变时内容不会更新,如: <span v-once>这个将不会改变: {{ msg }}</span>
v-html:输出html,如:<span v-html="rawHtml"></span>---- rawHtml='<span style="color: red">This should be red.</span>'
使用 JavaScript 表达式,每个绑定都只能包含单个表达式:如:{{ number + 1 }},{{ ok ? 'YES' : 'NO' }},{{ message.split('').reverse().join('') }},<div v-bind:id="'list-' + id"></div>
动态参数:<a v-bind:[attributeName]="url"> ... </a>。attributeName 会被作为一个 JavaScript 表达式进行动态求值
<a v-on:[eventName]="doSomething"> ... </a>。当
eventName
的值为"focus"
时,v-on:[eventName]
将等价于v-on:focus
。异常情况下值为
null。
这个特殊的null
值可以被显性地用于移除绑定。任何其它非字符串类型的值都将会触发一个警告。
修饰符:修饰符 (modifier) 是以半角句号
.
指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent
修饰符告诉v-on
指令对于触发的事件调用event.preventDefault()
:<form v-on:submit.prevent="onSubmit">...</form>
缩写:
v-bind 缩写:v-bind:href="" -> :href=""
v-on 缩写:v-on:click="doSomething" -> @click="doSomething"
2、计算属性和侦听器
计算属性:computed声明一个计算属性reversedMessage
<div id="example"> <p>Original message: "{{ message }}"</p> <p>Computed reversed message: "{{ reversedMessage }}"</p> </div>
var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { // 计算属性的 getter reversedMessage: function () { // `this` 指向 vm 实例 return this.message.split('').reverse().join('') } } })
结果:
Original message: "Hello"
Computed reversed message: "olleH"
像绑定普通属性一样在模板中绑定计算属性。Vue 知道
vm.reversedMessage
依赖于vm.message
,因此当vm.message
发生改变时,所有依赖vm.reversedMessage
的绑定也会更新。方法:methods
<p>Reversed message: "{{ reversedMessage() }}"</p>
// 在组件中 methods: { reversedMessage: function () { return this.message.split('').reverse().join('') } }
计算属性与方法的区别:计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要
message
还没有发生改变,多次访问reversedMessage
计算属性会立即返回之前的计算结果,而不必再次执行函数。计算属性缓存的好处:假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。
侦听属性:watch有一些数据需要随着其它数据变动而变动时使用
<div id="demo">{{ fullName }}</div>
var vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' }, watch: { firstName: function (val) { this.fullName = val + ' ' + this.lastName }, lastName: function (val) { this.fullName = this.firstName + ' ' + val } } })
将它与计算属性的版本进行比较:
var vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar' }, computed: { fullName: function () { return this.firstName + ' ' + this.lastName } } })
计算属性的 setter,计算属性默认只有 getter,需要时可以提供一个 setter
// ... computed: { fullName: { // getter get: function () { return this.firstName + ' ' + this.lastName }, // setter set: function (newValue) { var names = newValue.split(' ') this.firstName = names[0] this.lastName = names[names.length - 1] } } } // ...
现在再运行
vm.fullName = 'John Doe'
时,setter 会被调用,vm.firstName
和vm.lastName
也会相应地被更新。侦听器:当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
<div id="watch-example"> <p> Ask a yes/no question: <input v-model="question"> </p> <p>{{ answer }}</p> </div>
<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 --> <!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 --> <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script> <script> var watchExampleVM = new Vue({ el: '#watch-example', data: { question: '', answer: 'I cannot give you an answer until you ask a question!' }, watch: { // 如果 `question` 发生改变,这个函数就会运行 question: function (newQuestion, oldQuestion) { this.answer = 'Waiting for you to stop typing...' this.debouncedGetAnswer() } }, created: function () { // created 生命周期钩子,在实例创建完成后被立即调用。 // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。 // 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率 // AJAX 请求直到用户输入完毕才会发出。想要了解更多关于 // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识, // 请参考:https://lodash.com/docs#debounce this.debouncedGetAnswer = _.debounce(this.getAnswer, 500) }, methods: { getAnswer: function () { if (this.question.indexOf('?') === -1) { this.answer = 'Questions usually contain a question mark. ;-)' return } this.answer = 'Thinking...' var vm = this axios.get('https://yesno.wtf/api') .then(function (response) { vm.answer = _.capitalize(response.data.answer) }) .catch(function (error) { vm.answer = 'Error! Could not reach the API. ' + error }) } } }) </script>
在这个示例中,使用
watch
选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
3、Class 与 Style 绑定
绑定 HTML Class
v-bind:class,如:<div v-bind:class="{ active: isActive }"></div>,class显示与否将取决于isActive是 truthy (指的是在 布尔值 上下文中转换后的值为真的值) 时才添加
activeClass
。可与普通class属性共存。如:<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }" ></div>,当isActive为true时,渲染为class="static active"
class绑定对象
<div v-bind:class="classObject"></div>
data: { classObject: { active: true, 'text-danger': false } }
class绑定一个返回对象的计算属性
<div v-bind:class="classObject"></div>
data: { isActive: true, error: null }, computed: { classObject: function () { return { active: this.isActive && !this.error, 'text-danger': this.error && this.error.type === 'fatal' } } }
class绑定数组
<div v-bind:class="[activeClass, errorClass]"></div>
data: { activeClass: 'active', errorClass: 'text-danger' }
渲染为:<div class="active text-danger"></div>
class使用三元表达式:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
数组中嵌套对象语法
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
组件上绑定
// 声明组件 Vue.component('my-component', { template: '<p class="foo bar">Hi</p>' })
<my-component class="baz boo"></my-component>
HTML 将被渲染为:<p class="foo bar baz boo">Hi</p>
数据绑定class也适用
<my-component v-bind:class="{ active: isActive }"></my-component>
当isActive为truthy时,HTML将被渲染为:<p class="foo bar active">Hi</p>
style绑定内联样式
v-bind:style
的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: { activeColor: 'red', fontSize: 30 }
style绑定对象,还可使用返回对象的计算属性
<div v-bind:style="styleObject"></div>
data: { styleObject: { color: 'red', fontSize: '13px' } }
style绑定数组,可以将多个样式对象应用到同一个元素上
<div v-bind:style="[baseStyles, overridingStyles]"></div>
style自动添加前缀:当 v-bind:style 使用需要添加浏览器引擎前缀的 CSS 属性时,如 transform,Vue.js 会自动侦测并添加相应的前缀。
style多重值:提供一个包含多个值的数组,只会渲染数组中最后一个被浏览器支持的值。
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染
display: flex
。
4、条件渲染
v-if:指令用于条件性地渲染一块内容。
v-else:添加一个"else块",v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
v-else-if:充当 v-if 的“else-if 块”,可以连续使用
<h1 v-if="awesome">Vue is awesome!</h1> <h1 v-else>Oh no ?</h1>
因为 v-if 是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个 <template> 元素当做不可见的包裹元素,并在上面使用 v-if。最终的渲染结果将不包含 <template> 元素。
<template v-if="ok"> <h1>Title</h1> <p>Paragraph 1</p> <p>Paragraph 2</p> </template>
<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>
用 key 管理可复用的元素
Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做除了使 Vue 变得非常快之外,还有其它一些好处。例如,如果你允许用户在不同的登录方式之间切换:
<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
属性即可<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
属性。v-show:用于根据条件展示元素
<h1 v-show="ok">Hello!</h1>
注意,
v-show
不支持<template>
元素,也不支持v-else
。v-if 和 v-show 区别
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。相比之下,
v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换一般来说,
v-if
有更高的切换开销,而v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show
较好;如果在运行时条件很少改变,则使用v-if
较好。注意:不推荐同时使用
v-if
和v-for
。