
2.2.3 计算属性的setter
计算属性在默认情况下仅能通过计算属性函数得出结果。当开发者尝试修改一个计算属性时,会收到一个运行时警告提示。我们来看如图2-10所示的页面效果。

图2-10 页面效果
现有3个需求,具体如下。
①姓名由“姓-名”组成,姓名的初始显示为“A-B”。
②当改变姓或名时,姓名能自动同步变化。
③姓和名能实时与姓名同步。
下面对数据进行分析和设计。可以将“姓”和“名”设计为2个data数据,我们可以利用v-model实现双向数据绑定,但因为“姓名”是由“姓”和“名”动态确定的,所以我们可以将“姓名”设计为计算属性,同样用v-model绑定到input标签上。具体实现代码如下。


在上面的代码中,我们在data对象中定义了firstName和lastName两个计算属性,在computed配置中定义了计算属性fullName,并通过v-model将其绑定到对应的input标签上。初始显示实现了需求①中“姓名”的显示要求,如图2-11所示;当修改“姓”或“名”的内容时,“姓名”也会自动同步变化,这样也实现了需求②中“姓名”同步变化的要求,如图2-12所示。

图2-11 初始显示

图2-12 数据同步改变
那么问题来了,当我们在输入框(input)中改变“姓名”的内容时,v-model会自动将输入值赋给计算属性fullName,Vue框架会抛出警告提示,如图2-13所示。

图2-13 抛出警告提示
警告提示表示写操作失败,因为计算属性fullName是只读的,也就是只能计算返回一个值。那么应该如何设置计算属性值呢?答案是:可以通过同时提供getter和setter的计算属性来实现。下面修改一下计算属性fullName的实现,代码如下。

此时的计算属性fullName是一个对象,包含get方法(常称为getter)和set方法(常称为setter)。前面写的计算属性函数的功能等同于get方法,当它在初始化时会执行一次,并且任意依赖数据发生变化时会再次执行,也就实现了“姓名”的初始动态显示与修改“姓”或“名”的内容时会同步更新显示的功能。而set方法则是在修改fullName属性值后,会自动执行。也就是说,当修改“姓名”的内容时,计算属性的set方法就会自动执行,在set方法中接收fullName指定的最新值,并分隔出两个值的数组分别去更新firstName和lastName,这样就实现了需求③中的要求。