我正在使用 Lit-HTML(不是 Lit-Element)来构建 html 表单。表格非常简单,它有 2 个下拉菜单:Population 下拉菜单和 Animal 下拉菜单。
动物下拉选项取决于人口下拉列表的选择。请参阅 getAnimalDS() 逻辑。
模型定义和实用函数:
const model = {
Population: null,
Animal: null,
}
const dataSources = {
Populations: [null, "p1", "p2"],
Animals_1: [null, "a1", "a2"],
Animals_2: [null, "a3", "a4", "a5"],
}
function getAnimalDS(population) {
switch (population) {
case 'p1':
return dataSources.Animals_1;
case 'p2':
return dataSources.Animals_2;
default:
return [];
}
}
构建LIT-HTML模板的主要功能:
function buildSection1(model) {
return html`
<div class="mb-3">
<label for="Population" class="form-label">Population</label>
<select id="Population" name="Population" class="form-control"
.value="${model.Population}" @change=${e
=> {
model.Population = e.target.value;
model.Animal = null; // Reset Animal
renderSection1(); // Re-render the form
}}>
${dataSources.Populations.map((item) => html`
<option value="${item}" ?selected="${model.Population === item}">${item}</option>
`)}
</select>
</div>
<div class="mb-3">
<label for="Animal" class="form-label">Animal</label>
<select id="Animal" name="Animal" class="form-control"
.value="${model.Animal}" @change=${e => model.Animal = e.target.value}>
${getAnimalDS(model.Population).map((item) => html`
<option value="${item}" ?selected="${model.Animal === item}">${item}</option>
`)}
</select>
</div>
`;
}
测试:
如果我在 Population 下拉列表中选择一个 population,我会看到 Animal 上的选项正确更改 -> Awesome.
查看问题的步骤:
#1:在 Population 下拉列表中选择选项“p1”,我在 Animal 下拉列表中看到 3 个选项:“”、'a1'、'a2' -- Good
#2:接下来,我在动物下拉列表中选择“a2”(选定索引 = 2)-> 好
#3:现在,在 Population 下拉列表中选择选项“p2”,我在 Animal 下拉列表中看到 4 个选项:“”、'a3'、'a4'、'a5' -> Good
#4:在这一点上,我希望在 Animal 下拉列表中看到“EMPTY”行(选择的索引 = -1),因为在 @change of the Population 上,我确实将 model.Animal 重置为 null。
---- 但是 Animal 下拉菜单显示选项“a4”(选定索引 = 2)
---- 这意味着 LIT-HTML 在步骤 #2 使用先前选择的索引 = 2。
有意见吗?谢谢!
此行为的原因是因为 lit-html 不知道第二个
<select id="Animal">
元素的值已更改,因为 @change
事件处理程序将 model.Animal
更改为 'a2'
但不调用 render()
再次。由于 lit-html 认为该值仍然是null
,因此在重新渲染时不会更新 DOM。
解决方案 1:您可以通过在此处添加
renderSection1()
调用来解决此问题,例如:
html`
...
<select id="Animal" name="Animal" class="form-control"
.value="${model.Animal}"
@change=${e => {
model.Animal = e.target.value;
renderSection1();
}}>
...
</select>`
让 lit-html 知道值已经更新。因此,当第一个下拉列表将值更改回
null
时,它知道它再次不同并更新DOM。
live()
指令使 lit-html 始终根据 DOM 值检查值:
import {live} from 'lit-html/directives/live.js';
html`
...
<select id="Animal" name="Animal" class="form-control"
.value="${live(model.Animal)}" // always compare against DOM
@change=${e => model.Animal = e.target.value}>
...
</select>`