组件中setup的代码执行的顺序(组件的初始化先于组件的挂载方法)

 1.在子组件中使用props值

1.父组件 传入初始值

 

2.子组件接收初始值

 

 

3.在子组件页面挂载时打印,发现父组件的值其实传进来了, 但是没用上

4.修改后

2.代码执行的顺序

<script setup long="ts">
import {ref, onMounted, watch} from 'vue';



  const editingRows = ref([]);


  // 定义测试数据
  // const selectOptions = ref([
  //   {id:1, option_name: '限选值1', desc: 'dfsdfdf'},
  //   {id:2, option_name: '限选值1', desc: 'dfsdfdf'},
  //   {id:3, option_name: '限选值1', desc: 'dfsdfdf'},
  //   {id:4, option_name: '限选值1', desc: 'dfsdfdf'},
  //   {id:5, option_name: '限选值1', desc: 'dfsdfdf'},
  //   {id:6, option_name: '待填写', desc: '描述'},
  // ]);

  const selectOptions=ref([]);
  const props = defineProps({
    // 可以添加自定义的props,例如是否禁用组件等
    disabled: {
      type: Boolean,
      default: false
    },
    countries:{
      type: Array,

      required: true
    },
    selectOptions:{
      type: Array,

    },
    visible:{
      type: Boolean,
      default: false

    }

  });

  const emit = defineEmits(['update:selectOptions']);




  // 初始化editingRows,每个元素是一个包含行索引和编辑状态的对象
  onMounted(() => {

    // 假设这里有获取初始数据的逻辑,这里简化为一个空数组初始化
    console.log(props.selectOptions);
    // 讲父组件的selectOptions的值复制给子组件
   selectOptions.value=props.selectOptions;

  });

  const onRowEditSave = (event) => {
  let { newData, index } = event;

    selectOptions.value[index] = newData;
};

  const getStatusLabel = (status) => {
  switch (status) {
  case 'INSTOCK':
  return 'success';
  case 'LOWSTOCK':
  return 'warn';
  case 'OUTOFSTOCK':
  return 'danger';
  default:
  return null;
}
};

  const formatCurrency = (value) => {
  return new Intl.NumberFormat('en - US', { style: 'currency', currency: 'USD' }).format(value);
};
  // 编辑一行后保存数据
  // const onRowEditSave = (event) => {
  //   const { newData, index } = event;
  //   debugger
  //   const rowIndex = editingRows.value.findIndex((item) => item.index === index);
  //
  //   if (rowIndex!== - 1) {
  //     selectOptions.value[index] = newData;
  //     editingRows.value[rowIndex].isEditing = false;
  //   }
  // };

  // 删除记录的方法
  const deleteRecord = (id) => {
    const newSelectOptions = selectOptions.value.filter(option => option.id!== id);
    selectOptions.value = newSelectOptions;
    // 同时更新editingRows,移除对应的编辑状态对象
    const newEditingRows = editingRows.value.filter(row => {
      const dataIndex = selectOptions.value.findIndex(option => option.id === row.index);
      return dataIndex!== - 1;
    });
    editingRows.value = newEditingRows;
  }


// 初始化最大id值
const maxId = ref(selectOptions.value.length > 0? Math.max(...selectOptions.value.map(option => option.id)) : 0);
console.log(maxId);



  // 添加一行数据
  const addNewRecord = () => {
    // 自增最大id值
    maxId.value++;

    // 创建新记录并分配自增后的id值
    const newRecord = {id: maxId.value, option_name: '待填写', desc: '描述'};

    const newSelectOptions = selectOptions.value.slice();
    newSelectOptions.push(newRecord);
    selectOptions.value = newSelectOptions;

    // const newRowIndex = newSelectOptions.length - 1;
    // editingRows.value.push({index: newRowIndex, isEditing: false});

    console.log(selectOptions.value);
    console.log(editingRows.value);
  };

  //监听

  watch([selectOptions], ([newSelectOptions]) => {
    console.log(newSelectOptions,'sdfsdfsdf');
    emit('update:selectOptions', selectOptions);
  }, { deep: true });
</script>

1.为什么会想到查这个代码的执行顺序呢

2.按照上面这个初始化的数组最大id是0,而不是父组传进来的最大id,和预想不符

原因就在于组件的初始化先于挂载执行。。。。

一、执行顺序分析

1. 组件初始化阶段

  • 变量声明
    • 首先声明了editingRowsselectOptions等变量。editingRows被初始化为一个空数组ref([])selectOptions最初也被初始化为一个空数组ref([]),虽然有一段被注释掉的测试数据定义。
  • props定义
    • 接着使用defineProps定义了组件的props,包括disabledcountriesselectOptionsvisible。这些props定义了组件从父组件接收数据的接口。
  • emit定义
    • 通过defineEmits定义了一个名为update:selectOptions的事件,用于向父组件发送数据更新通知。

2. 挂载阶段(onMounted

  • 当组件挂载(onMounted生命周期钩子被触发)时,执行以下操作:
    • 打印props.selectOptions的值,这是为了查看从父组件接收到的selectOptions的值。
    • 将父组件传入的selectOptions的值赋给子组件的selectOptions变量(selectOptions.value = props.selectOptions)。这一步是为了在子组件中使用父组件传入的数据。

3. 方法定义阶段

  • 定义了多个方法,如onRowEditSavegetStatusLabelformatCurrencydeleteRecordaddNewRecord。这些方法分别用于处理行编辑保存、获取状态标签、格式化货币、删除记录和添加新记录等操作。
  • onRowEditSave方法中,当行编辑保存时,会更新selectOptions数组中的对应元素。
  • deleteRecord方法中,根据传入的id值删除selectOptions数组中的元素,并相应地更新editingRows数组。
  • addNewRecord方法中,会增加最大id值,创建一个新的记录并添加到selectOptions数组中。

4. 监听阶段(watch

  • 使用watch监听selectOptions的变化。当selectOptions的值发生变化时([newSelectOptions]),会打印新的selectOptions值,并且通过emit发出update:selectOptions事件,将新的selectOptions值发送给父组件。

二、执行顺序的原因

1. 遵循Vue组件的生命周期

  • 在Vue组件中,组件的创建和挂载有其特定的生命周期顺序。首先进行变量声明、propsemit的定义,这是组件的基本结构设置。然后在挂载阶段(onMounted)执行一些初始化操作,如获取和处理从父组件传入的数据,这符合在组件准备好后再处理数据的逻辑。

2. 数据驱动的设计原则

  • 方法的定义在数据初始化之后,这样在方法中可以使用已经初始化好的数据(如selectOptions)。例如,onRowEditSave方法需要操作selectOptions数组,所以要在selectOptions被正确初始化(在onMounted中从父组件获取值)之后定义该方法才有意义。

3. 响应式数据处理

  • 最后设置watch监听selectOptions的变化。这是为了实现响应式数据更新,当selectOptions发生变化时,可以及时通知父组件(通过emit),并且可以在子组件内部进行一些相关的操作(如打印新值)。这符合Vue的响应式原理,保证数据的一致性和组件之间的通信。

3.解决获取最大值的问题:已解决

1.再组件初始化的时候就把父组件传进来的值赋给子组件的数组

果然ok

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值