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. 组件初始化阶段
- 变量声明
- 首先声明了
editingRows
、selectOptions
等变量。editingRows
被初始化为一个空数组ref([])
。selectOptions
最初也被初始化为一个空数组ref([])
,虽然有一段被注释掉的测试数据定义。
- 首先声明了
props
定义- 接着使用
defineProps
定义了组件的props
,包括disabled
、countries
、selectOptions
和visible
。这些props
定义了组件从父组件接收数据的接口。
- 接着使用
emit
定义- 通过
defineEmits
定义了一个名为update:selectOptions
的事件,用于向父组件发送数据更新通知。
- 通过
2. 挂载阶段(onMounted
)
- 当组件挂载(
onMounted
生命周期钩子被触发)时,执行以下操作:- 打印
props.selectOptions
的值,这是为了查看从父组件接收到的selectOptions
的值。 - 将父组件传入的
selectOptions
的值赋给子组件的selectOptions
变量(selectOptions.value = props.selectOptions
)。这一步是为了在子组件中使用父组件传入的数据。
- 打印
3. 方法定义阶段
- 定义了多个方法,如
onRowEditSave
、getStatusLabel
、formatCurrency
、deleteRecord
和addNewRecord
。这些方法分别用于处理行编辑保存、获取状态标签、格式化货币、删除记录和添加新记录等操作。 - 在
onRowEditSave
方法中,当行编辑保存时,会更新selectOptions
数组中的对应元素。 - 在
deleteRecord
方法中,根据传入的id
值删除selectOptions
数组中的元素,并相应地更新editingRows
数组。 - 在
addNewRecord
方法中,会增加最大id
值,创建一个新的记录并添加到selectOptions
数组中。
4. 监听阶段(watch
)
- 使用
watch
监听selectOptions
的变化。当selectOptions
的值发生变化时([newSelectOptions]
),会打印新的selectOptions
值,并且通过emit
发出update:selectOptions
事件,将新的selectOptions
值发送给父组件。
二、执行顺序的原因
1. 遵循Vue组件的生命周期
- 在Vue组件中,组件的创建和挂载有其特定的生命周期顺序。首先进行变量声明、
props
和emit
的定义,这是组件的基本结构设置。然后在挂载阶段(onMounted
)执行一些初始化操作,如获取和处理从父组件传入的数据,这符合在组件准备好后再处理数据的逻辑。
2. 数据驱动的设计原则
- 方法的定义在数据初始化之后,这样在方法中可以使用已经初始化好的数据(如
selectOptions
)。例如,onRowEditSave
方法需要操作selectOptions
数组,所以要在selectOptions
被正确初始化(在onMounted
中从父组件获取值)之后定义该方法才有意义。
3. 响应式数据处理
- 最后设置
watch
监听selectOptions
的变化。这是为了实现响应式数据更新,当selectOptions
发生变化时,可以及时通知父组件(通过emit
),并且可以在子组件内部进行一些相关的操作(如打印新值)。这符合Vue的响应式原理,保证数据的一致性和组件之间的通信。
3.解决获取最大值的问题:已解决
1.再组件初始化的时候就把父组件传进来的值赋给子组件的数组
果然ok