一个js小组件,了解js面向对象编程

一个EditInPlace小组件,了解js面向对象编程

什么叫面向对象呢?

面向对象(Object-Oriented,简称OO)是一种编程思想或范式,它将程序中的数据和对数据的操作封装成对象。对象是程序中的实体,可以是现实世界中的物体或概念。面向对象编程的基本思想是通过创建对象来模拟现实世界中的实体,使程序更容易理解、设计和维护。

关键概念包括:

  1. 对象(Object): 对象是一个具体实例,具有特定的属性和方法。例如,一辆车可以是一个对象,它具有属性(颜色、型号)和方法(启动、停止)。
  2. 类(Class): 类是对象的模板或蓝图,定义了对象的结构和行为。一个类可以包含多个对象。使用类可以创建具有相似属性和方法的多个对象。
  3. 封装(Encapsulation): 封装是将对象的状态(属性)和行为(方法)包装在一起,形成一个独立的单元。这样可以隐藏对象的内部实现细节,只暴露必要的接口。
  4. 继承(Inheritance): 继承允许一个类(子类)继承另一个类(父类)的属性和方法。这样可以实现代码的重用,子类可以拥有父类的特性,并可以添加或修改自己的特性。
  5. 多态(Polymorphism): 多态性允许同一个方法在不同的对象中有不同的行为。子类可以覆盖(override)父类的方法,实现自己的特定行为。

面向对象编程的优势在于它提供了一种更加模块化、可维护和可扩展的方式来组织代码。通过将代码组织成对象,可以更好地反映现实世界中的关系和交互。这种编程思想有助于降低复杂性,提高代码的可读性和可维护性,同时促进代码的重用。简单一点来说我可以将很多功能分开来写,然后让对象具有我功能函数里面具有的属性和方法。

一个组件了解js面向对象

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>EditInPlace</title>
</head>
<body>
    <div id="app"></div>
    <script src="./editor.js"></script>
    <script>

        // #app 挂载点  DOM面向对象的封装
        //业务代码
        new EditInPlace(
           'ep1' ,
            document.getElementById('app'),
            'this is value'
            
        )
    </script>
</body>
</html>

在html中,我们new了一个EditInPlace的对象,我们知道,对象能使用js里面的属性和方法,那么那些属性和方法写在哪里呢。那就体现了编程的另一个素养,叫做模块化,另写一个js文件。提高代码的可读性和复用性。

js 复制代码
/**
 * @func EditInPlace组件
 * @param {string} id 元素id 
 * @param {dom} parent 挂载点 
 * @param {string} value 初始值
 * @author ls
 * @date   2023/12/4
 */
function EditInPlace(id, parent, value) {
    this.id = id;
    this.parentElement = parent || document.body;
    this.value = value || 'default value';
    this.createElement(this.id);
    this.attachEvents(); 
}

EditInPlace.prototype = {
    // 创建组件的DOM,并挂载到挂载点上
    createElement: function(id) {
        // console.log(this, '---')
        // 动态创建dom 当前对象的containerElement属性
        // DOM 树, 
        this.containerElement = document.createElement('div');
        // span节点的创建
        this.staticElement = document.createElement('span');
        this.staticElement.innerText = this.value;
        this.containerElement.appendChild(this.staticElement)
        
        //输入框的创建 
        this.fieldElement = document.createElement('input');
        this.fieldElement.type = 'text';
        this.fieldElement.value = this.value;
        this.containerElement.appendChild(this.fieldElement)

        // 保存按钮 
        this.saveButton = document.createElement('input');
        this.saveButton.type = 'button';
        this.saveButton.className = 'save';
        this.saveButton.value = 'Save'
        this.containerElement.appendChild(this.saveButton);

        // 取消按钮
        this.cancelButton = document.createElement('input');
        this.cancelButton.type = 'button';
        this.cancelButton.className = 'cancel';
        this.cancelButton.value = 'Cancel'
        this.containerElement.appendChild(this.cancelButton);

        this.parentElement.appendChild(this.containerElement);
        this.convertToText();
    },
    // 切换到文本状态
    convertToText: function() {
        this.fieldElement.style.display = 'none';
        this.saveButton.style.display = 'none';
        this.cancelButton.style.display = 'none';
        this.staticElement.style.display = 'inline';
    },
    attachEvents: function() {
        // console.log(this)
        // let that = this; // 对象实例保存下来了
        const fn = this.convertToEditable.bind(this)
        this.staticElement.addEventListener('click', fn)
        this.cancelButton.addEventListener('click',this.convertToText.bind(this))
        this.saveButton.addEventListener(
            'click',
            this.save.bind(this)
        )
        // fn();
    },
    convertToEditable: function() {
        // console.log(this, this.cancelButton)
        this.fieldElement.style.display = 'inline';
        this.saveButton.style.display = 'inline';
        this.cancelButton.style.display = 'inline';
        this.staticElement.style.display = 'none';
    },
    save:function(){
        let value=this.fieldElement.value;
        this.value=value;
        this.staticElement.innerText=value;
        this.convertToText();
    }
}

代码分析

1.构造函数

js 复制代码
function EditInPlace(id, parent, value) {
  this.id = id;
    this.parentElement = parent || document.body;
    this.value = value || 'default value';
    this.createElement(this.id);
    this.attachEvents(); 
}

这个函数是 EditInPlace 组件的构造函数。 它接受三个参数:id(元素的 ID)、parent(组件挂载的父 DOM 元素),以及 value(组件的//初始值)。

构造函数初始化了一些属性,比如 idparentElement(如果未提供则默认为 document.body),以及 value(如果未提供则默认为 'default value')。

2.createElement 方法:

js 复制代码
createElement: function(id) {
    // ...
}
  • 这个方法用于创建组件的 DOM 元素,并将它们附加到指定的父元素上。
  • 它创建了一个包含 spanstaticElement)、inputfieldElement)、'Save' 按钮(saveButton)、'Cancel' 按钮(cancelButton)的 divcontainerElement)。

3.convertToText 方法:

js 复制代码
convertToText: function() {
    // ...
}
  • 这个方法隐藏了输入框和按钮,仅显示静态文本,使其变为不可编辑状态

4.attachEvents 方法:

js 复制代码
attachEvents: function() { // .
  • 这个方法给静态元素(点击事件)、取消按钮(点击事件)和保存按钮(点击事件)添加了事件监听器。
  • 点击静态元素触发 convertToEditable 方法,点击取消按钮触发 convertToText 方法。

5.convertToEditable 方法:

js 复制代码
convertToEditable: function() {
    // ...
}

这个方法隐藏了静态文本,显示了输入框和按钮,允许用户编辑内容。

6.save 方法:

js 复制代码
save: function() { // ... }

这个方法保存了编辑后的值,更新了静态文本,然后通过 convertToText 方法将组件转换回不可编辑状态。

注意

  • 一定要有this指针,this会指向实例对象,所以我们要引用对象里面的内容就必须要有this指针。
  • 方法一定要写在构造函数的原型上,因为实例对象的隐式原型会指向构造函数的显示原型,我们的实例对象需要构造函数的属性和方法必须隐式继承

以上的内容都在《你不知道的javascript》一书中,当然我原来的文章当中也有写,有想了解的宝子们可以去看一下,深刻了解以下原型和this的指向。

实现的效果

点击save保存之后,原先编辑的文字就会保存下来,取代原来的this is value,显示在页面上,点击cancel现在编辑的则不保存,任然显示原先保存de。

小插曲

  • "力量只有在面对强大的对手时才能得到提升。"
  • "不要认为你已经足够强大,否则你就会败给那些比你更强大的人。"
  • "这个世界并不是理所当然地属于任何人的,只有强者才能在这个世界上生存下去。"
相关推荐
万叶学编程1 小时前
Day02-JavaScript-Vue
前端·javascript·vue.js
前端李易安3 小时前
Web常见的攻击方式及防御方法
前端
PythonFun3 小时前
Python技巧:如何避免数据输入类型错误
前端·python
知否技术3 小时前
为什么nodejs成为后端开发者的新宠?
前端·后端·node.js
hakesashou3 小时前
python交互式命令时如何清除
java·前端·python
天涯学馆3 小时前
Next.js与NextAuth:身份验证实践
前端·javascript·next.js
HEX9CF4 小时前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
ConardLi4 小时前
Chrome:新的滚动捕捉事件助你实现更丝滑的动画效果!
前端·javascript·浏览器
ConardLi4 小时前
安全赋值运算符,新的 JavaScript 提案让你告别 trycatch !
前端·javascript