个人工作中自己给自己挖的坑,埋坑记录
1. 响应式对象与v-model
如果双向绑定的数据是一个对象,仅仅改变对象里的某个属性,就会发现值改变了,但是页面上显示的内容没有变化
代码如下,我要实现一个月份快速切换的组件(MonthPicker),双向绑定的数据是一个moment对象,快速切换年月后使用moment对象的方法加减年月。
<template>
<div>
<a-button
type="link"
size="small"
@click="quickChangeDate(-1, 'year')">
<DoubleLeftOutlined />
</a-button>
<a-button
type="link"
size="small"
@click="quickChangeDate(-1, 'month')">
<LeftOutlined />
</a-button>
<a-month-picker
v-model:value="date"
@change="onMonthChange"
/>
<a-button
type="link"
size="small"
@click="quickChangeDate(1, 'month')">
<RightOutlined />
</a-button>
<a-button
type="link"
size="small"
@click="quickChangeDate(1, 'year')">
<DoubleRightOutlined />
</a-button>
</div>
</template>
<script setup>
import moment from 'moment';
import {
RightOutlined,
DoubleRightOutlined,
DoubleLeftOutlined,
LeftOutlined
} from "@ant-design/icons-vue";
import { computed, watchEffect, ref } from "vue";
const props = defineProps({
modelValue: {
type: [Object, String],
default: undefined
}
});
const emits = defineEmits(["update:modelValue", "change"]);
// 日历时间
const date = ref(moment())
watchEffect(() => {
if (!props.modelValue) {
date.value = undefined;
} else {
if (!props.modelValue.isSame(date.value, "month")) {
date.value = props.modelValue.clone();
}
}
});
function quickChangeDate(operator, type) {
if (operator > 0) {
date.value.add(operator, type).clone();
} else {
date.value.subtract(Math.abs(operator), type).clone();
}
onMonthChange();
}
function onMonthChange() {
if (props.modelValue && props.modelValue.isSame(date.value, "month")) {
return;
}
const value = date.value.clone();
emits("update:modelValue", value);
emits("change", value);
}
// init();
</script>
<template>
<MonthPicker v-model="month"/>
<span>{{month.format('YYYY-MM')}}</span>
</template>
<script setup>
const month = ref()
</script>
真实的实现效果是<span>{{month.format('YYYY-MM')}}</span>
快捷键切换后月份有变化,但是a-month-picker展示的月份一直是初始化时的月份,快速切换后无变化。于是我把代码做了如下修改,a-month-picker展示的月份,也会跟着快速切换变化。
// 原来的
function quickChangeDate(operator, type) {
if (operator > 0) {
date.value.add(operator, type).clone();
} else {
date.value.subtract(Math.abs(operator), type).clone();
}
onMonthChange();
}
// 现在的
function quickChangeDate(operator, type) {
if (operator > 0) {
// 这里直接把日期的值更换为新的moment对象,就好了
date.value = date.value.add(operator, type).clone();
} else {
date.value = date.value.subtract(Math.abs(operator), type).clone();
}
onMonthChange();
}
使用心得:v-model的数据是不可变数据。既传递的是引用数据类型时,每次触发更新时都应该传递一个新的数据,不要修改原来的数据后传递旧的数据。
1. reactive 转换ref
使用toRefs转换为ref数据(refData)以后,再给reactive数据新增属性,refData就会缺少属性。具体如下
// reactive数据
const reactiveData = reactive({ a: 0, b: '', c: undefined })
// 转换为ref的数据
const refData = toRefs(re)
// 修改 reactiveData
reactiveData .d = 123
// 获取refDate.d
refData.d // undefined
reactiveData .d // 123
上述问题解释如下:把toRefs理解为快照,里面转换的是当前时刻reactiveData 拥有的属性,所以往后时刻给reactiveData增加属性,上一次的快照是没有的。
使用心得:写composition函数时,如果把reactive对象使用toRefs返回时,最好是在reactive申明的时候就把所有的属性确立好,暂时不能确定值的用undefined赋值