likes
comments
collection
share

为什么没有早点让我知道“就地编辑”?!

作者站长头像
站长
· 阅读数 26

一、前言

为什么没有早点让我知道“就地编辑”?!

原来就地编辑是这样实现的。回想之前写修改功能都是跳转到其他页面来操作,还得多写一个页面也是真的心酸🥲。 今天就来把这B站常考面试题拿下吧!

为什么没有早点让我知道“就地编辑”?!

二、问题剖析

1、文本与输入间的切换

为什么没有早点让我知道“就地编辑”?!

为什么没有早点让我知道“就地编辑”?!

大家应该都很熟悉,当我们鼠标悬浮在个性签名处,就会显示边框,点击就会进入输入状态。 平时文本状态,显示签名,mouseover,进入编辑状态,显示编辑框。

2、点击别处保存

为什么没有早点让我知道“就地编辑”?!

输入了个性签名后,点击输入框外的任意位置就可以直接保存了。也就是退出编辑状态 自动保存,切换到文本状态

三、localStorage

修改的内容该以怎样的形式存放在哪里呢?在实现逻辑之前,我们先来认识一下一个HTML5 引入的一个 Web 存储 API,localStorage。它允许在用户的浏览器上存储数据,而且即使在浏览器关闭后,这些数据依然会被保存。

通过简单的 JavaScript API 进行操作,如 setItem(key, value) 用于存储数据,getItem(key) 用于获取数据,以及 removeItem(key) 和 clear() 分别用于删除单个项或清除所有存储的数据。

四、代码实现

了解了所需要做的事情后,就可以开始敲我们的代码了。 封装思想必须要学会,融会贯通到每一次的编程中。创建一个类,那就单独放到一个文件中,原本JS是没有类这个概念的,它是原型式的面向对象的编程,用首字母大写的方式来默认为一个类。

1、做好JSDoc注释

/**
 * @function 就地编辑   // 简要描述函数的功能
 * @param { ele } container 挂载点   // 用于说明函数的参数
 * @author 牛马先生   // 标注代码的作者信息,有助于追溯和版权管理
 * @date 2024/06/25   // 记录代码的创建或修改日期,为了版本控制和历史追踪
 */

做好这样的注释块是十分重要的,相比于敲代码本身,甚至于更应该看重这些个细节。这样的注释有助于其他开发者理解该段代码的目的、如何使用、由谁编写及何时编写,从而提高团队协作效率,减少沟通成本,同时也有助于维护人员在未来进行代码审查或修改时能够快速理解代码逻辑。毕竟谁也不愿意看到一堆又一堆的代码而没有注释,需要自己从头看到尾来理清思路。

2、类定义

function EditInPlace(container, value = '这个家伙很懒,什么都没有留下') {
   
    this.container = container
    this.value = value
    // console.log(this.value);
    // 将动态地创建文本和编辑input地dom 封装,代码好管理
    this.createElement()
    this.attachEvents()
}
EditInPlace.prototype = {
    // 就地编辑需要的动态DOM
    createElement: function() {
        
    },
    // 文本状态
    converToText: function() {
       
    },
    // 编辑状态
    converToEdit: function() {
        t
    },
    // 事件监听
    attachEvents: function() {
        
    },
    save: function() {
       
    }
}

构造函数 (EditInPlace) : 接受两个参数,分别是container(挂载点DOM元素),以及可选的默认值value。构造函数初始化这些属性,并调用createElementattachEvents方法来构建界面和绑定事件。

value的默认值是es6引入的一种重要特性,当用户什么都没有输入时,构造器的参数使用默认值,使得我们的用户体验更好。

原型方法: 通过扩展EditInPlace.prototype来添加实例共享的方法,包括createElementconverToTextconverToEditattachEventssave

3、功能实现

(1) 创建DOM元素: 在createElement方法中,为编辑功能创建必要的DOM结构,包括静态文本显示(span)、输入框(input type="text"), 保存和取消按钮(input type="button"), 并将它们附加到指定的容器中。

createElement: function() {
    // DOM树
    // 创建一个div
    this.editElement = document.createElement('div')
    // 加一个子元素
    this.container.appendChild(this.editElement)

    // signature 文本值
    this.staticElement = document.createElement('span')
    this.staticElement.innerHTML = this.value
    this.editElement.appendChild(this.staticElement)

    // input
    this.filedElement = document.createElement('input')
    this.filedElement.type = 'text'
    this.filedElement.value = this.value
    this.editElement.appendChild(this.filedElement)

    // 确认按钮
    this.saveButton = document.createElement('input')
    this.saveButton.type = 'button'
    this.saveButton.value = '保存'
    this.editElement.appendChild(this.saveButton)

    // 取消按钮
    this.cancelButton = document.createElement('input')
    this.cancelButton.type = 'button'
    this.cancelButton.value = '取消'
    this.editElement.appendChild(this.cancelButton)

    // 初始文本状态
    this.converToText()
},

(2) 状态切换:

🥇 converToText: 将界面从编辑模式切换回文本显示模式,隐藏输入框和按钮,显示静态文本。

🥈 converToEdit: 反之,将界面切换到编辑模式,隐藏静态文本,显示输入框和按钮。

// 文本状态
converToText: function() {
    this.filedElement.style.display = 'none'
    this.staticElement.style.display = 'inline'
    this.saveButton.style.display = 'none'
    this.cancelButton.style.display = 'none'
},
// 编辑状态
converToEdit: function() {
    this.staticElement.style.display = 'none'
    this.filedElement.style.display = 'inline'
    this.saveButton.style.display = 'inline'
    this.cancelButton.style.display = 'inline'
},

(3) 事件处理:

🥇 点击静态文本: 通过委托给staticElement的点击事件,触发编辑模式。

🥈 保存操作: 绑定到saveButton的点击事件,保存输入框中的值到value属性,并更新静态文本显示,同时调用localStorage.setItem持久化数据到浏览器的本地存储中,最后回到文本显示模式。

🥉 取消操作: 绑定到cancelButton的点击事件,简单地取消编辑,恢复到文本显示模式,不保存任何更改。

attachEvents: function() {
    // 暂存this
    let that = this
    this.staticElement.addEventListener('click', function() {
        // this 丢失了
        that.converToEdit()
    })
    this.saveButton.addEventListener('click', () => {
        this.save()
    })
    this.cancelButton.addEventListener('click', () => {
        this.converToText()
    })
},
save: function() {
    this.value = this.filedElement.value
    this.staticElement.innerHTML = this.value
    this.converToText()
    // html5 localStorage
    localStorage.setItem(this.storageKey, this.value)
}

仔细看就会发现,添加事件的时候,回调函数有的使用的是箭头函数,有的则是正常函数。你会认为两种有什么差异呢?

五、优化与结果

因为既然是为了复用代码而进行的封装,那就得进行到底。就地编辑除了修改个性签名,还可以用在很多地方的吧,比如编辑个人籍贯什么的,所以就需要再加一个参数表示编辑的到底是什么。

function EditInPlace(storageKey, container, value = '这个家伙很懒,什么都没有留下') {
    this.storageKey = storageKey
    this.container = container
    this.value = value
    // console.log(this.value);
    // 将动态地创建文本和编辑input地dom 封装,代码好管理
    this.createElement()
    this.attachEvents()
}

最后在html中new一个实例来看看结果怎么样。

<script src="./edit_in_place.js"></script>
<script>
    const STORAGEKEY = 'signature'
    const signature = localStorage.getItem('STORAGEKEY') || "这个家伙很懒,什么都没有留下"
    new EditInPlace(STORAGEKEY, document.getElementById('signature'), signature)
</script>

为什么没有早点让我知道“就地编辑”?!

六、结语

今天带大家一起认识了JS的本地存储localStorage,以及如何实现就地编辑。希望看完会有收获,一起加油!✌️

转载自:https://juejin.cn/post/7384801669509742602
评论
请登录