预期的行为是用户能够单独设置所有三个元素的样式。
工作原理:
- 当每个元素被点击时,它被存储在selected.elements
- 单击“粗体/斜体”时,它存储在 selected.settings 中
- 单击“应用”后,DOM 将使用“选定”对象中的元素和设置进行更新,并清除选定元素。
重现步骤:
- 点击“elementOne”
- 选择“粗体”
- 点击“应用”
- 点击“elementTwo”
- 选择“斜体”
- 点击“应用”
预期: elementOne 为粗体; elementTwo 是斜体
实际:都是斜体
在第 5 步,model.elementOne.settings 被更新,即使没有调用函数来执行此操作。
const selected = {
elements: [],
settings: {}
}
const model = {
elementOne: {
slug: 'elementOne',
settings: {}
},
elementTwo: {
slug: 'elementTwo',
settings: {}
},
elementThree: {
slug: 'elementThree',
settings: {}
}
}
const elementContainer = document.getElementById('elementContainer')
const buttonContainer = document.getElementById('buttonContainer')
const fontStyleContainer = document.getElementById('fontStyleButtonContainer')
const setupEventListeners = _ => {
elementContainer.addEventListener('click', e => {
// add the selected element to selected.elements
selected.elements.push(e.target.id)
})
fontStyleContainer.addEventListener('click', e => {
// add the selected font style to the selected.settings
for (let i = 0; i < selected.elements.length; i++) {
if (e.target.hasAttribute('data-bold')) {
selected.settings.fontStyle = 'bold'
} else if (e.target.hasAttribute('data-italic')) {
selected.settings.fontStyle = 'italic'
}
}
})
buttonContainer.addEventListener('click', e => {
// update the model for each selected element using the selected settings
for (let i = 0; i < selected.elements.length; i++) {
model[selected.elements[i]].settings = selected.settings
}
// update the DOM based on the new model
updateDOMFromModel()
// reset the selected elements & settings
selected.elements.length = 0
})
}
const updateDOMFromModel = _ => {
// update the DOM based on the new model
for (const el in model) {
if (model.hasOwnProperty(el)) {
const element = model[el]
const elementDOM = document.getElementById(element.slug)
switch (element.settings.fontStyle) {
case 'bold':
elementDOM.style = 'font-weight: 800;'
break
case 'italic':
elementDOM.style = 'font-style: italic;'
break
default:
}
}
}
}
setupEventListeners()
<body>
<div id="elementContainer" style="cursor: pointer;">
<p>1. Select an element to style</p>
<ul>
<li id="elementOne">elementOne</li>
<li id="elementTwo">elementTwo</li>
<li id="elementThree">elementThree</li>
</ul>
</div>
<div id="fontStyleButtonContainer" style="cursor: pointer;">
<p>2. Select a font style</p>
<div id="fontStyleButton" data-bold>Bold</div>
<div id="fontStyleButton" data-italic>Italic</div>
</div>
<div id="buttonContainer" style="cursor: pointer;">
<p>3. Apply changes</p>
<button id="btnApply">Apply</button>
</div>
</body>
最佳答案
通过在 selected.settings
中始终使用相同的对象,您可以将模型元素的设置绑定(bind)在它们之间,因为它们最终指向同一事物。
在这里,我只是为 selected.settings
重新设置了一个新对象,它起作用了! ( checkin fontStyleContainer
点击监听器)
当心你是否使用值或引用 ;)
const selected = {
elements: [],
settings: {}
}
const model = {
elementOne: {
slug: 'elementOne',
settings: {}
},
elementTwo: {
slug: 'elementTwo',
settings: {}
},
elementThree: {
slug: 'elementThree',
settings: {}
}
}
const elementContainer = document.getElementById('elementContainer')
const buttonContainer = document.getElementById('buttonContainer')
const fontStyleContainer = document.getElementById('fontStyleButtonContainer')
const setupEventListeners = _ => {
elementContainer.addEventListener('click', e => {
// add the selected element to selected.elements
selected.elements.push(e.target.id)
})
fontStyleContainer.addEventListener('click', e => {
// add the selected font style to the selected.settings
for (let i = 0; i < selected.elements.length; i++) {
if (e.target.hasAttribute('data-bold')) {
// Each time a new object!
selected.settings = {fontStyle: 'bold'}
} else if (e.target.hasAttribute('data-italic')) {
// Each time a new object!
selected.settings = {fontStyle: 'italic'}
}
}
})
buttonContainer.addEventListener('click', e => {
// update the model for each selected element using the selected settings
for (let i = 0; i < selected.elements.length; i++) {
model[selected.elements[i]].settings = selected.settings
}
// update the DOM based on the new model
updateDOMFromModel()
// reset the selected elements & settings
selected.elements.length = 0
})
}
const updateDOMFromModel = _ => {
// update the DOM based on the new model
for (const el in model) {
if (model.hasOwnProperty(el)) {
const element = model[el]
const elementDOM = document.getElementById(element.slug)
switch (element.settings.fontStyle) {
case 'bold':
elementDOM.style = 'font-weight: 800;'
break
case 'italic':
elementDOM.style = 'font-style: italic;'
break
default:
}
}
}
}
setupEventListeners()
<body>
<div id="elementContainer" style="cursor: pointer;">
<p>1. Select an element to style</p>
<ul>
<li id="elementOne">elementOne</li>
<li id="elementTwo">elementTwo</li>
<li id="elementThree">elementThree</li>
</ul>
</div>
<div id="fontStyleButtonContainer" style="cursor: pointer;">
<p>2. Select a font style</p>
<div id="fontStyleButton" data-bold>Bold</div>
<div id="fontStyleButton" data-italic>Italic</div>
</div>
<div id="buttonContainer" style="cursor: pointer;">
<p>3. Apply changes</p>
<button id="btnApply">Apply</button>
</div>
</body>
关于javascript - 对象神秘更新而没有调用更新函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49788385/