Vue中的理论在实际开发过程中的遇见

1. 只有在初始化 Vue实例前声明的属性才具有响应式能力,后来添加的属性不具备。

场景: 子组件是一个创建/编辑公用的配置页面,当在父组件中点击编辑时,需要将已有的配置数据传递到子组件中展示,当直接对子组件 data属性中的 对象变量 进行赋值时,少添加了一个属性,以致子组件中对该属性变更,页面都没有反应。

<!-- 子组件 template -->
<Form ref="configForm" :model="newConfig" :rules="ruleValidate" :label-width="150">
  <Row :gutter="5" v-for="(item, index) in newConfig.dataList" :key="'o-' + index">
    <iCol span="10">
      <FormItem :label="$t('sms.common.dataList')" :prop="'dataList.' + index + '.id'" :rules="validate.id">
      	<!-- 遍历出来的每个 <select>中的备选项 即 options,都是 allOptions剔除其他 <select>已被选择的项之后剩下的,即可被当前 <select>选择的备选项 -->
      	<!-- change事件中实时计算每个 <select>的备选项 -->
        <Select v-model="item.id" @on-change="changeData">
          <Option v-for="o in item.options" :value="o.id" :key="`o-${o.id}`">{{ o.name }}</Option>
        </Select>
      </FormItem>
    </iCol>
  </Row>
</Form>
// 子组件 data数据
data () {
  return {
    newConfig: {
      allOptions: [],
      // 空数据结构
      // 渲染到页面上是一个 <select> 列表,每个 <select> 中的备选项,即 options都是 allOptions剔除其他 <select>已被选择的项之后剩下的可被当前 <select>选择的备选项
      dataList: [
        {
          id: '',
          name: '',
          options: []
        }
      ]
    }
  }
}
// 父组件 调用方法
edit(row) {
	// 显示子组件
	this.sonShowFlag = true;
	// 对子组件 data中的变量赋值
	this.$nextTick(() => {
		this.$refs.son.newConfig = {
			// 原先是这样写的,如果有数据就把数据直接赋值给子组件的这个对象变量,如果没有就赋一个空的对象结构,而 options这个属性是自行添加方便实时计算的,row.dataList中并没有这个属性,导致子组件根据已有数据计算出各个 <select>的 options后,页面并没有渲染出 各个 <select>的备选项,下拉框仍然是空的
			itemList: row.dataList.length > 0 ? row.dataList : [
				{
					id: '',
					name: '',
					options: []
				}
			],
			// 修正后,为 row.dataList中的每一项添加一个空的 options属性
			itemList: row.dataList.length > 0 ? row.dataList.map(item => ({...item, options: []})) : [
				{
					id: '',
					name: '',
					options: []
				}
			]
		};
	})
},

2. Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。如果需要强制替换元素/组件而不是重复使用它,可以为各个元素/组件分配一个唯一的 key。

场景: Form表单中,结构相同的 <FormItem>根据 v-if 条件切换展示,切换后原先条件下的 <FormItem>的校验报错信息仍然显示在页面上。

<template>
	<Form ref="configForm" :model="config" :rules="ruleValidate" :label-width="150">
		<FormItem label="选择条件" prop="condition">
			<Select v-model="config.condition">
				<Option v-for="o in conditionOptions" :value="o.id" :key="`o-${o.id}`">{{ o.name }}</Option>
			</Select>
		</FormItem>
		<!-- 如果不加 key的话,条件1的情况下,“选择设备”的 FormItem 报错而不纠正的情况下直接切换成条件2,根据 Vue的渲染原则,这个 FormItem的 dom会被“选择A端设备”所复用,原先的报错信息因为没有被纠正而保留在页面上  -->
		<FormItem label="选择设备" prop="deviceIds" v-if="config.condition == 1" key="device">
			<CheckboxGroup v-model="config.deviceIds">
				<Checkbox v-for="o in deviceList" :label="o.id" :key="`o-${o.id}`">{{ o.name }}</Checkbox>
			</CheckboxGroup>
		</FormItem>
		<FormItem label="选择A端设备" prop="deviceAIds" v-if="config.condition == 2" key="deviceA">
			<CheckboxGroup v-model="config.deviceAIds">
				<Checkbox v-for="o in deviceAList" :label="o.id" :key="`o-${o.id}`">{{ o.name }}</Checkbox>
			</CheckboxGroup>
		</FormItem>
		<FormItem label="选择B端设备" prop="deviceBIds" v-if="config.condition == 2" key="deviceB">
			<CheckboxGroup v-model="config.deviceBIds">
				<Checkbox v-for="o in deviceBList" :label="o.id" :key="`o-${o.id}`">{{ o.name }}</Checkbox>
			</CheckboxGroup>
		</FormItem>
	</Form>
</template>
computed: {
	ruleValidate() {
		return {
			condition : [
				{ type: 'number', required: true, message: '请选择条件', trigger: 'change' }
			],
			deviceIds: [
				{ type: 'array', required: true, message: '请选择设备', trigger: 'change' }
			],
			deviceAIds: [
				{ type: 'array', required: true, message: '请选择A端设备', trigger: 'change' }
			],
			deviceBIds: [
				{ type: 'array', required: true, message: '请选择B端设备', trigger: 'change' }
			]
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值