点击文本块切换textarea仅首次生效,后续无响应技术求助
问题原因分析
- 事件绑定失效:你一开始用
$("p, h1").click()直接给页面加载时存在的<p>和<h1>绑定点击事件,但当调用replaceWith()把这些元素换成<textarea>后,原元素会被从DOM树中移除;虽然end()函数又把它们插回去,但此时原元素上的点击事件已经丢失了——直接绑定在元素上的事件,会随着元素脱离DOM而失效,所以后续点击自然没反应。 - nodeName识别问题:第一次点击后元素变成了
<textarea>,此时点击的是textarea而非原标签;而你初始的$("*").click()也是直接绑定,重新插回的<p>/<h1>没有这个事件监听,所以控制台不会输出它们的nodeName。
解决代码
修改后的JavaScript代码
// 用事件委托绑定点击事件,父元素body会监听所有子元素中匹配p/h1的点击 $('body').on('click', 'p, h1', function() { const $currentBlock = $(this); startEdit($currentBlock); }); function startEdit($block) { // 保存原元素的关键信息 const originalText = $block.text(); const originalClass = $block.attr('class'); const originalId = $block.attr('id'); const originalTag = $block.prop('tagName'); const blockWidth = $block.css('width'); const blockHeight = $block.css('height'); // 创建textarea元素 const $textarea = $('<textarea>', { 'class': originalClass, 'val': originalText, 'style': `width: ${blockWidth}; height: ${blockHeight};`, // 存储原元素的标签名和id,方便恢复 'data-original-tag': originalTag, 'data-original-id': originalId }); // 回车触发失焦 $textarea.keydown(function(event) { if (event.key === 'Enter') { $(this).blur(); } }); // 失焦时恢复原标签 $textarea.blur(function() { finishEdit($(this)); }); // 替换元素并聚焦 $block.replaceWith($textarea); $textarea.focus(); $textarea[0].selectionStart = originalText.length; } function finishEdit($textarea) { const newContent = $textarea.val(); // 取出存储的原元素信息 const originalTag = $textarea.data('original-tag').toLowerCase(); const originalClass = $textarea.attr('class'); const originalId = $textarea.data('original-id'); // 创建原标签元素 const $originalBlock = $(`<${originalTag}>`, { 'class': originalClass, 'text': newContent }); // 恢复原id if (originalId) { $originalBlock.attr('id', originalId); } // 替换回原元素 $textarea.replaceWith($originalBlock); } // 用事件委托监听所有元素的点击,确保动态插入的元素也能触发 $('body').on('click', '*', function() { console.log($(this).prop('nodeName')); });
HTML代码(无需修改,保持原结构即可)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script> <body> <H1 class="Header" id="view">Lorem ipsum dolor sit.</H1> <p class="text" id="gert">Lorem ipsum dolor sit amet consectetur adipisicing elit. Quibusdam voluptas doloribus impedit voluptatem nisi! Beatae nulla deleniti fugiat id quibusdam laudantium, tempora ut, consequatur odio quis atque saepe nam sequi.</p> <p class="text" id="ger">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ex voluptate repellat aperiam harum. Veritatis repellendus voluptatibus voluptatem veniam eum provident! Alias perferendis quaerat nostrum? Inventore aliquid consequuntur quo laboriosam consequatur?</p> <script src="../logic.js"></script> </body>
关键改进点
- 事件委托:把事件绑定到父元素(这里用
body),通过监听子元素的点击事件,不管元素被替换多少次,只要匹配<p>/<h1>选择器,就能触发点击逻辑。 - 存储原元素信息:通过
data-*属性保存原标签名、id等信息,确保恢复元素时能完全还原原结构。 - 避免全局变量:把元素对象作为参数传递给函数,减少全局变量带来的潜在冲突。
内容的提问来源于stack exchange,提问作者Vlaqikk
相关产品推荐
相关产品推荐

