考虑一个场景:在两个输入框中分别输入姓和名,下方显示出全名
插值语法实现
<!-- 准备好一个容器--> <div id="root"> 姓:<input type="text" v-model="firstName"> <br/><br/> 名:<input type="text" v-model="lastName"> <br/><br/> 全名:{{firstName}}-{{lastName}} </div>
new Vue({ el:'#root', data:{ firstName:'张', lastName:'三' } })
通过v-model
实现实现属性和输入的双向绑定,使用插值语法{{firstName}}-{{lastName}}
实现全名的拼接显示
优化方向
- Vue官方推荐:组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法
- 复杂表达式会让模板变得不那么声明式。我们应该尽量描述应该显示什么,而非如何计算那个值。而且计算属性和方法使得代码可以复用
methods实现
<div id="root"> 姓:<input type="text" v-model="firstName"> <br/><br/> 名:<input type="text" v-model="lastName"> <br/><br/> 全名:{{fullName()}} <!--测试函数调用次数--> <br>全名:{{fullName()}} <br>全名:{{fullName()}} </div>
new Vue({ el:'#root', data:{ firstName:'张', lastName:'三' }, methods: { fullName(){ console.log('调用了fullName()函数~') return this.firstName + '-' + this.lastName } }, })
通过v-model
实现实现属性和输入的双向绑定,使用方法fullname()
实现全名的拼接显示
从图中可以看到fullname()
每次读取时都会执行一次。当数据发生改变时fullname()
会被重新调用。
优化方向:
- 可否让
fullname()
在第一次调用后形成缓存,后续仅在属性值发生修改时才再次调用
计算属性实现
- 定义:通过已有属性计算得来的属性
- 原理:底层借助了
Objcet.defineproperty
方法提供的getter
和setter
get()
函数什么时候执行?
- 初次读取时会执行一次。
- 当依赖的数据发生改变时会被再次调用。
- 优势:与
methods
实现相比,内部有缓存机制(复用),效率更高,调试方便。 - 备注:
- 计算属性最终会出现在vm上,直接读取使用即可。
- 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
<div id="root"> 姓:<input type="text" v-model="firstName"> <br/><br/> 名:<input type="text" v-model="lastName"> <br/><br/> 全名:{{fullName}} <!--测试函数调用次数--> <br>全名:{{fullName}} <br>全名:{{fullName}} </div>
new Vue({ el:'#root', data:{ firstName:'张', lastName:'三', }, computed:{ fullName:{ get(){ console.log('get()被调用了') return this.firstName + '-' + this.lastName //此处的this是vm }, set(value){ console.log('set',value) const arr = value.split('-') this.firstName = arr[0] this.lastName = arr[1] } } } })
若计算属性只读,则可以简写计算属性:
new Vue({ el:'#root', data:{ firstName:'张', lastName:'三', }, computed:{ fullName(){ console.log('get()被调用了') return this.firstName + '-' + this.lastName //此处的this是vm }, } })
通过v-model
实现实现属性和输入的双向绑定,使用计算属性fullname
实现全名的拼接显示
从图中可以看到get()
只在初次读取时会执行一次,后续会使用缓存实现复用。当依赖的数据发生改变时会被再次调用。