计算属性
在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示
模板中书写表达式
<template id="template">
<h2>{{ `${user.firstName} ---- ${user.lastName}` }}</h2>
<h2>{{ `${user.firstName} ---- ${user.lastName}` }}</h2>
<h2>{{ `${user.firstName} ---- ${user.lastName}` }}</h2>
</template>
<script>
Vue.createApp({
template: '#template',
data() {
return {
user: {
firstName: 'Klaus',
lastName: 'Wang'
}
}
}
}).mount('#app')
</script>
缺点:
-
模板中存在大量的复杂逻辑,不便于维护(模板中表达式的初衷是用于简单的计算)
-
当有多次一样的逻辑时,存在重复的代码
-
多次使用的时候,很多运算也需要多次执行,没有缓存;
methods中的实现
<template id="template">
<h2>{{ getFullname() }}</h2>
<h2>{{ getFullname() }}</h2>
<h2>{{ getFullname() }}</h2>
</template>
<script>
Vue.createApp({
template: '#template',
data() {
return {
user: {
firstName: 'Klaus',
lastName: 'Wang'
}
}
},
methods: {
getFullname() {
return `${this.user.firstName} ---- ${this.user.lastName}`
}
}
}).mount('#app')
</script>
缺点:
- 我们仅仅只是想要在界面上展示对应的值,但是变成了多次的方法调用
- 多次使用方法的时候,没有缓存,也需要多次计算
computed
<template id="template">
<h2>{{ fullName }}</h2>
<h2>{{ fullName }}</h2>
<h2>{{ fullName }}</h2>
</template>
<script>
Vue.createApp({
template: '#template',
data() {
return {
user: {
firstName: 'Klaus',
lastName: 'Wang'
}
}
},
computed: {
fullName() {
return `${this.user.firstName} ---- ${this.user.lastName}`
}
}
}).mount('#app')
</script>
计算属性 VS Methods
<template id="template">
<h2>{{ fullName }}</h2>
<h2>{{ fullName }}</h2>
<h2>{{ fullName }}</h2>
<h2>{{ getFullname() }}</h2>
<h2>{{ getFullname() }}</h2>
<h2>{{ getFullname() }}</h2>
</template>
<script>
Vue.createApp({
template: '#template',
data() {
return {
user: {
firstName: 'Klaus',
lastName: 'Wang'
}
}
},
computed: {
fullName() {
return `${this.user.firstName} ---- ${this.user.lastName}`
}
},
methods: {
getFullname() {
return `${this.user.firstName} ---- ${this.user.lastName}`
}
}
}).mount('#app')
</script>
计算属性本质上是一个对象
完整写法
computed: {
fullName: {
set() {
return `${this.user.firstName} ---- ${this.user.lastName}`
},
get(v) {
const names = v.split(' --- ')
this.firstName = names[0].trim()
this.lastName = names[1].trim()
}
}
}
methods: {
// 写成方法的时候,其实是计算属性的语法糖,即只实现了get方法,而没有实现set方法
getFullname() {
return `${this.user.firstName} ---- ${this.user.lastName}`
}
}
watch
开发中我们在data返回的对象中定义了数据,这个数据通过插值语法等方式绑定到template中
当数据变化时,template会自动进行更新来显示最新的数据
但是在某些情况下,我们希望在代码逻辑中监听某个数据的变化,并实现相应的处理逻辑
,
这个时候就需要用侦听器watch来完成
watch: {
// 参数1: 新值 参数2: 修改之前的旧值
fullName(newV, oldV) {
console.log(newV, oldV)
}
}
配置选项
watch: {
fullName: {
// 深度监听,默认vue对于复杂数据类型只会对引用地址进行监听
// 所以当一个对象的属性发生改变的时候,是没有办法被监听到的
// 如果需要被监听到,就必须使用深度监听
deep: true,
// 监听器的执行是在渲染完毕以后,对应值发生改变的时候
// 如果我们希望初次渲染的时候,即刻执行,可以设置immediate为true
// 此时侦听器就会在初次渲染的时候被执行(也就意味着oldV的值是undefined)
immediate: true,
handler(newV, oldV) {
console.log(newV, oldV)
}
}
}
其它写法
字符串形式
watch: {
// 即将handler函数抽离到methods中进行定义
fullName: 'handleWatch'
},
methods: {
handleWatch(newV, oldV) {
console.log(newV, oldV)
}
}
数组写法
watch: {
fullName: [
'handlefullNameChange',
// vue会自动遍历数组中的值并执行,所以这里的函数可以是一个匿名函数
function(newV, oldV) {
console.log(newV, oldV)
},
{
immediate: true,
handler(newV, oldV) {
console.log('immediate', newV, oldV)
}
}
]
},
监听属性
watch: {
'user.name'(newV, oldV) {
console.log('immediate', newV, oldV)
}
}
但是vue是无法监听数组对象成员的变化的
// 下面这种写法是错误的, 值会发生改变,但是并不会触发监听操作
watch: {
'user[0].name'(newV, oldV) {
console.log('immediate', newV, oldV)
}
}
深度监听对象
Vue.createApp({
template: '#template',
data() {
return {
users: [
{name:'Klaus'},
{name:'Steven'},
{name:'James'}
]
}
},
watch: {
users: {
deep: true,
handler(newV, oldV) {
// 在引用数据类型的监听中 oldV是没有任何的意义的,
// 对于引用数据类型中的旧值和新值, 仅仅只是引用地址上的赋值,并没有做浅拷贝或深拷贝
console.log(newV === oldV) // => true
}
}
},
methods: {
handleClick() {
this.users[0].name = 'Alex'
}
}
}).mount('#app')
$set
created() {
// $watch 的设置方式和在watch option中的设置 效果是一致的
// 这里第二个handler函数可以是箭头函数,因为外层作用域是created函数,其内部this就是当前组件data的proxy对象
this.$watch('fullName', (newV, oldV) => console.log(newV, oldV), {
immediate: true,
deep: true
})
}
Tips: vue3已经移除了侦听器,可以使用计算属性,方法(定义在组件中的局部方法或定义在app.config.globalProperies的全局方法)替代
// 使用计算属性替换过滤器,来为价格前面加上¥
filterBooks() {
return this.books.map(item => {
// 为了避免需要展示的数据污染旧的实际进行逻辑判断的数据,
// 需要对这些复杂类型数据进行浅拷贝
const newItem = Object.assign({}, item);
newItem.price = "¥" + item.price;
return newItem;
})
}
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!