Polymer JS触发on-change事件时预选中表单值不生效问题
问题根因
这个问题是Polymer响应式机制和dom-repeat渲染规则共同导致的,核心有3个问题:
- 直接修改了原
serviceTypeItems数组中的对象属性,没有做值重置逻辑,切换业务类型时旧值会残留,同时直接修改源数据会产生全局副作用 - 没有使用Polymer提供的响应式API通知属性变化,内部状态更新后视图监听不到变更
- dom-repeat默认按对象引用判断是否需要重新渲染,你返回的数组内是原有对象引用,就算属性改了也不会触发重渲染
修复方案
步骤1:给dom-repeat添加key属性
让dom-repeat按业务唯一标识serviceTypeId比对条目,而不是按对象引用,触发属性变更后的重渲染:
<template is="dom-repeat" items="{{_selectedServiceType(_contract.serviceTypeIds, serviceTypeItems, _contract.businessTypeId)}}" as="_serviceTypeDetails" key="serviceTypeId"> <!-- 原有内容保持不变 --> </template>
步骤2:修改_selectedServiceType计算函数逻辑
修改点包括:不直接修改源数据对象、增加属性重置逻辑、调用Polymer响应式API通知变更:
_selectedServiceType(val1, val2, val3) { var returnItems = []; if (val1 != undefined) { // 统一处理选中的服务类型ID const selectedIds = val1 === '-1' ? val2.map(item => String(item.serviceTypeId)) : String(val1).split(','); for (let i = 0; i < val2.length; i++) { const currentSt = val2[i]; if (selectedIds.includes(String(currentSt.serviceTypeId))) { // 浅拷贝原对象,不修改源数据 const stCopy = Object.assign({}, currentSt); // 按业务类型赋值,同时处理不同类型的属性重置,避免旧值残留 if (val3 === "2") { // 商业类 stCopy.sitesStartDateAligned = true; stCopy.noOfSites = undefined; stCopy.pricingMethodId = undefined; } else if (val3 === "1") { // 住宅类 stCopy.noOfSites = 1; stCopy.pricingMethodId = 2; stCopy.sitesStartDateAligned = false; } // 迭代ID规则优先级最高 if (this._contract?.iterationId === '2' || this._contract?.iterationId === '3') { stCopy.pricingMethodId = 1; } returnItems.push(stCopy); } } } // 用Polymer的set方法赋值,触发响应式更新 this.set('_contract.serviceTypeDetails', returnItems); // 通知数组下所有子属性变更,强制dom-repeat刷新 this.notifyPath('_contract.serviceTypeDetails.*'); return returnItems; }
步骤3:补全_refreshFields事件逻辑(可选)
如果切换业务类型时计算函数没有自动触发,可以在绑定的change事件中手动触发重新计算:
_refreshFields() { this._selectedServiceType( this._contract.serviceTypeIds, this.serviceTypeItems, this._contract.businessTypeId ); }
内容的提问来源于stack exchange,提问作者Fighithebird
相关产品推荐
相关产品推荐

