vue3响应式数据使用踩坑记录

个人工作中自己给自己挖的坑,埋坑记录

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赋值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值