返回 导航

Vue.js

hangge.com

Vue.js - 计算属性的getter和setter方法详解(给计算属性设置值)

作者:hangge | 2026-03-13 08:52
    计算属性是 Vue 最常用的特性之一。它们看起来像属性,但本质上是基于它们的依赖进行缓存的函数。通常我们写的计算属性只有 getter(只读),但在 Vue 中我们也可以为计算属性提供 setter,从而实现“可写的计算属性”。这个非常适合把多个数据源双向绑定为一个逻辑字段(例如表单中的合成字段)或将 UI 变更回写到多个数据源上。

1,基本介绍

Vue.js 内部会根据传递参数类型采用不用的处理方式:
  • 传递的如果是函数,则直接作为 getter 函数处理。
  • 传递的如果是对象,则从中获取 gettersetter 函数,并进行相应处理。

2,只写 getter 的计算属性

(1)最常见计算属性场景就是只写 getter
<template>
    <div class="my-component">
        <p>firstName: {{ firstName }}</p>
        <p>lastName: {{ lastName }}</p>
        <p>fullName: {{ fullName }}</p>
    </div>
</template>
<script>
export default {
    name: 'MyComponent',
    data() {
        return {
            firstName: '张',
            lastName: '三'
        }
    },
    computed: {
        fullName() {
            return this.firstName + this.lastName;
        }
    },
    methods: {
    }
}
</script>

(2)运行结果如下:

3,带 getter 和 setter 的计算属性

(1)下面样例用对象形式定义计算属性,实现从 UI 修改 fullName 并把拆分结果回写到 firstName 和 lastName
<template>
    <div class="my-component">
        <p>firstName: {{ firstName }}</p>
        <p>lastName: {{ lastName }}</p>
        <p>fullName: {{ fullName }}</p>
        <button @click="changeName">修改fullName</button>
    </div>
</template>
<script>
export default {
    name: 'MyComponent',
    data() {
        return {
            firstName: '张',
            lastName: '三'
        }
    },
    computed: {
        fullName: {
            get() {
                return this.firstName + this.lastName;
            },
            set(value) {
                this.firstName = value.charAt(0) || '';
                this.lastName = value.slice(1) || '';
            }
        }
    },
    methods: {
        changeName() {
            this.fullName = '李四'
        }
    }
}
</script>

(2)运行效果如下,默认 firstNamelastName 变量值分别为“张”和“三”。点击按钮后将 fullName 计算属性的值改为“李四”,此时会同步将 firstNamelastName 变量值设置为“李”和“四”

附:带有 setter 方法的计算属性使用场景示例

1,表单中“合成字段”的双向绑定示例

(1)下面是样例有 price(数字)和 unit(字符串)这两个变量,需要一个展示为类似“100 元”的输入框,并且用户可直接编辑。
<template>
    <div class="my-component">
        <p>price:{{ price }}</p>
        <p>unit:{{ unit }}</p>
        <input v-model="priceText" />
    </div>
</template>
<script>
export default {
    name: 'MyComponent',
    data() {
        return { price: 100, unit: '元' }
    },
    computed: {
        priceText: {
            get() {
                return `${this.price} ${this.unit}`;
            },
            set(value) {
                // 假设用户输入 "200 元" 或 "200"
                const num = parseFloat(value);
                if (!isNaN(num)) this.price = num;
                // unit 保持不变或从输入中判断(这里简化处理)
            }
        }
    },
    methods: {
    }
}
</script>
(2)运行效果如下,默认 input 输入框的值为“100 元”。我们可以修改 input 输入框里面金额,会同步更新 price 变量值。

2,在组件中实现 v-model 的“代理”

(1)父组件传入 value,子组件希望在内部用合成字段并回写。下面是子组件 CompositeInput.vue 代码:
<template>
    <div>
        <input v-model="proxy" />
    </div>
</template>
<script>
export default {
    name: 'CompositeInput',
    // v-model 默认使用 prop: value + event: input
    props: {
        value: {
            type: Object,
            required: true,
            // 如 { a: "100", b: "200" }
        }
    },
    computed: {
        proxy: {
            get() {
                // 将父组件传入的对象合成一个字符串
                return `${this.value.a}-${this.value.b}`;
            },
            set(val) {
                // 将用户输入的字符串拆分回对象
                const [a, b] = val.split("-");
                // 通知父组件更新 value(标准 v-model 回写方式)
                this.$emit("input", {
                    a: a || "",
                    b: b || ""
                });
            }
        }
    },
}
</script>

(2)父组件代码如下:
<template>
    <div class="my-component">
        <CompositeInput v-model="formData" />
        <p>a: {{ formData.a }}</p>
        <p>b: {{ formData.b }}</p>
    </div>
</template>
<script>
import CompositeInput from './CompositeInput.vue';
export default {
    name: 'MyView',
    components: {
        CompositeInput
    },
    data() {
        return {
            formData: {
                a: "100",
                b: "200"
            }
        }
    },
    methods: {
    }
}
</script>

(2)运行结果如下,当子组件的 input 输入框内容修改时,会自动更新父组件传入的对象值。
评论

全部评论(0)

回到顶部