事件处理和事件修饰符
使用方法
- 事件绑定指令:
v-on:方法名
,方法定义在vue的methods
对象中 - 事件传参:
@click="aaa('')"
注意点:
- methods中配置的函数不可使用箭头函数
event.target.innerText
能拿到标签的值,但是调用不加()
,或者使用($event)
常用修饰符
阻止默认事件
// js中的阻止默认事件
e.preventDefault()
// vue
@click.prevent="showMessge"
阻止事件冒泡
// js中的阻止事件冒泡
e.stopPropagation()
// vue
@click.stop="showMessge"
// 阻止冒泡、默认事件连用
@click.stop.prevent="showMessge"
只触发一次事件
事件在当前页面只触发一次,之后便被移除,不再触发
@click.once="showMessge"
键盘事件
使用@keyup
监听按键抬起事件,如果只使用@keyup
表示监听所有按键抬起事件,而使用@keyup.xxx
表示xxx
键抬起时才触发对应的方法
<input @keyup="keyCheck" type="text" placeholder="实时更新">
<input @keyup.enter="keyCheck" type="text" placeholder="回车更新">
计算属性
定义
在Vue.js中,计算属性(computed properties)是基于它们的依赖进行缓存的响应式属性。计算属性主要用于当一个属性依赖于其他属性值,并且需要进行一些运算时。使用计算属性可以避免在模板中放入过多的逻辑,使得模板更加简洁和易于维护。
写法
计算属性的定义通常在Vue实例的computed
选项中进行,如下所示:
new Vue({
el: '#app',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: {
get: function (){
return this.firstName + ' ' + this.lastName
},
set: function (newValue){
var names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[names.length - 1];
}
}
}
})
;
在这个例子中,fullName
是一个计算属性,它依赖于data
中的firstName
和lastName
。当firstName
或lastName
发生变化时,fullName
会自动更新。在模板中,你可以像访问数据属性一样访问计算属性:
<div id="app">
<p>Full name: {{ fullName }}</p>
</div>
如果fullName
中的值有修改,那么set
方法会将fullName
重新进行拆分,并赋值给data
中相应的对象。
如果对于计算属性只有读的需求,那么可以将以上代码改写为:
new Vue({
el: '#app',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function() {
return this.firstName + ' ' + this.lastName;
}
}
});
计算属性的特性包括:
- 缓存:计算属性是基于它们的响应式依赖进行缓存的。只有当它的依赖项发生改变时,计算属性才会重新计算。这意味着,只要依赖项没有发生变化,多次访问计算属性将立即返回之前的计算结果,而不需要再次执行函数。
- 响应式:计算属性内部跟踪了哪些数据被访问,从而知道何时需要重新计算。如果计算属性依赖的数据发生变化,它将重新计算并触发相应的DOM更新。
- Getter 和 Setter:计算属性默认只有getter函数,但是你也可以提供一个setter函数,当你尝试对计算属性赋值时,setter函数将被调用。
原理
Vue.js 的计算属性实现原理涉及到几个核心概念:响应式系统、依赖追踪、以及惰性求值。下面是计算属性背后的实现细节:
- 响应式系统:
Vue.js 使用 Object.defineProperty(在 Vue 2.x 中)或 Proxy(在 Vue 3.x 中)来使对象成为响应式。这意味着当你访问或修改一个对象的属性时,Vue.js 能够检测到这个变化。 - 依赖追踪:
当计算属性的 getter 函数被执行时,Vue 会记录所有被访问的响应式属性作为这个计算属性的依赖。这是通过一个全局的依赖目标(通常是一个 watcher 实例)来实现的,它在计算属性的函数执行过程中收集依赖。 - 惰性求值:
计算属性的值会被缓存,Vue.js 会为每个计算属性创建一个 watcher 实例。只有在依赖项发生变化时,这个缓存值才会失效。在下一次访问计算属性时,如果依赖项没有发生变化,Vue.js 会返回缓存的值而不是重新计算。 - 依赖变更通知:
当计算属性的依赖项发生变化时,依赖项的 setter 会通知其相关的 watcher。如果这个 watcher 对应的是一个计算属性,它会标记为脏(dirty),表示其缓存的值已经失效。 - 重新计算:
当你下一次访问这个计算属性时,如果它被标记为脏,Vue.js 将重新运行它的 getter 函数来计算新的值,并更新缓存。 - Getter 和 Setter:
Vue.js 允许你为计算属性指定 getter 和 setter 函数。getter 负责计算和返回值,而 setter 在你尝试设置计算属性的值时被调用,允许你自定义如何响应这个变化。
在 Vue 3.x 中,响应式系统从 Object.defineProperty 升级到了使用 Proxy,这提供了更好的性能和更多的语言特性支持,但基本原理保持不变。
这个系统的设计使得 Vue.js 的计算属性非常高效。只有在必要时才重新计算值,并且确保了数据的一致性和组件的性能。
监视属性
定义和用法
在Vue.js中,监视属性(watchers)是一种特别的功能,允许你监听组件状态中的数据变化。当你需要在数据变化时执行异步操作或昂贵的操作时,监视属性非常有用。你可以使用watch
选项在Vue组件中定义监视属性。
下面是一个基本的例子来说明如何在Vue组件中使用监视属性:
<template>
<div>
<p>输入你的名字:</p>
<input v-model="name" placeholder="输入名字">
</div>
</template>
<script>
export default {
data() {
return {
name: ''
};
},
watch: {
// 当name变化时,这个函数就会被调用
name(newValue, oldValue) {
console.log(`名字从 ${oldValue} 改变成了 ${newValue}`);
}
}
};
</script>
在这个例子中,我们有一个名为name
的数据属性,它通过v-model
指令与输入框绑定。我们还定义了一个监视属性,它会在name
的值发生变化时被触发。在监视属性的函数内部,你可以访问新值(newValue
)和旧值(oldValue
),并执行任何你需要的逻辑。
监视属性也可以监视嵌套的对象属性或数组,使用字符串形式表示路径,例如:
watch: {
'someObject.someProperty'(newValue, oldValue) {
// ...
}
}
深度监视
Vue还提供了一种更先进的监视属性使用方式,你可以提供一个对象而不是一个函数,来包含更多的选项,如下:
watch: {
name: {
handler(newValue, oldValue) {
// 处理name变化的逻辑
},
immediate: true, // 立即以当前的值触发回调
deep: true // 深度观察对象内部的变化
}
}
在这个高级用法中,handler
是实际执行监视逻辑的函数,immediate
选项指定是否在监视开始时立即执行一次(使用当前值),而deep
选项允许你深度观察一个嵌套对象内部的变化。
监视属性和计算属性的异同
特性 | 计算属性 (Computed Properties) | 监视属性 (Watchers) |
---|---|---|
定义 | 基于它们的依赖进行缓存的响应式属性。 | 观察和响应Vue实例上的数据变动的函数。 |
缓存 | 有缓存,只有当依赖发生变化时才会重新计算。 | 无缓存,每次触发数据变更时都会执行。 |
写法 | 在computed 选项中定义为函数,返回计算结果。 | 在watch 选项中定义,键是要观察的表达式,值是回调函数。 |
用途 | 对数据进行转换或组合,方便在模板中直接使用。 | 执行异步操作、复杂逻辑或在数据变化时执行副作用(例如日志记录)。 |
性能 | 由于有缓存,性能较高,适用于重复计算和大量数据处理。 | 由于无缓存,可能在性能上不如计算属性,但适用于响应数据变化进行操作。 |
双向绑定 | 默认只有getter,可以添加setter来实现。 | 不适用于双向绑定,只用于监听数据变化。 |
灵活性 | 主要用于同步操作,计算值通常直接用于模板渲染。 | 更灵活,可以监听任何响应式数据,包括props、计算属性等,并执行任何代码。 |
访问旧值和新值 | 不适用,只关心当前计算值。 | 可以访问变化前后的值,便于比较和执行基于变化的操作。 |
应用场景 | 当需要根据某些数据自动计算新的数据时使用。 | 当需要在数据变化时执行一些额外的操作,如调用API或执行异步任务时使用。 |
通常情况下,如果你需要根据某些数据自动计算出新的数据,并且这些新数据不需要进行复杂的操作或异步处理,那么使用计算属性会更加合适。如果你需要在数据变化时执行更复杂的逻辑,或者需要进行异步操作,那么使用监视属性会更加适合。
动态绑定
class样式的动态绑定
在Vue中,可以使用v-bind:class
(或简写为:class
)指令来动态绑定class样式。这允许你根据数据的变化来切换元素的class。以下是几种常见的动态绑定class的方式:
对象语法:
可以将一个对象传给:class
,对象的键是class的名字,值是一个布尔值,用来决定是否应用该class。<template> <div :class="{ active: isActive, 'text-danger': hasError }"></div> </template> <script> export default { data() { return { isActive: true, hasError: false }; } }; </script>
如果
isActive
是true
,active
类会被添加到元素上;如果hasError
是true
,text-danger
类会被添加。数组语法:
可以传递一个数组给:class
,以应用一个class列表。<template> <div :class="[activeClass, errorClass]"></div> </template> <script> export default { data() { return { activeClass: 'active', errorClass: 'text-danger' }; } }; </script>
这将根据
activeClass
和errorClass
的值动态添加active
和text-danger
类。与普通class属性混用:
可以将:class
与普通的class属性一起使用。Vue会智能地合并它们。<template> <div class="static" :class="{ active: isActive, 'text-danger': hasError }"></div> </template> <script> export default { data() { return { isActive: true, hasError: true }; } }; </script>
这里的
div
将同时拥有static
、active
和text-danger
类(如果isActive
和hasError
都为true
)。在组件上使用:
当使用自定义组件时,你也可以绑定class。<template> <MyComponent :class="{ 'custom-class': isCustom }"></MyComponent> </template> <script> export default { data() { return { isCustom: true }; } }; </script>
如果
isCustom
为true
,custom-class
将被添加到MyComponent
的根元素上。
这些是Vue中动态绑定class样式的基本方法。它们可以根据实际情况和需求灵活使用,从而使得应用的样式更加动态和响应式。
style样式的动态绑定
在Vue中,可以使用v-bind:style
(或简写为:style
)指令来动态绑定内联样式。这允许你根据组件的状态来改变元素的样式属性。以下是几种常见的动态绑定style的方式:
对象语法:
可以将一个对象传给:style
,对象的键是CSS属性名,值是对应的样式值。<template> <div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div> </template> <script> export default { data() { return { activeColor: 'red', fontSize: 20 }; } }; </script>
如果
activeColor
是'red'
,并且fontSize
是20
,那么div
的文字颜色将是红色,字体大小将是20像素。数组语法:
可以传递一个数组给:style
,以应用多个样式对象。<template> <div :style="[baseStyles, overridingStyles]"></div> </template> <script> export default { data() { return { baseStyles: { color: 'blue', fontSize: '12px' }, overridingStyles: { fontSize: '14px' } }; } }; </script>
这将应用
baseStyles
和overridingStyles
中的样式,后者的fontSize
将覆盖前者的fontSize
。自动添加前缀:
当使用需要浏览器前缀的CSS属性时,Vue会自动侦测并添加相应的前缀。<template> <div :style="{ display: '-webkit-box' }"></div> </template>
Vue会根据浏览器自动处理前缀,无需手动添加。
使用变量:
可以在样式对象中使用变量,使得样式更加动态。<template> <div :style="styleObject"></div> </template> <script> export default { computed: { styleObject() { return { color: this.isActive ? 'green' : 'gray', fontWeight: this.isActive ? 'bold' : 'normal' }; } }, data() { return { isActive: true }; } }; </script>
styleObject
计算属性根据isActive
的值动态返回不同的样式对象。绑定内联样式的注意事项:
- CSS属性名可以使用驼峰式或短横线分隔(需要用引号包裹)。
- 如果样式的值是空字符串、null或undefined,该样式将不会被渲染。