EditlnPlace就地编辑:Dom编程 (Form表单优化) VS React 编程

153 阅读6分钟

随着AI技术发展,参差不齐的图文出现,用户体验显得更加重要。本文将通过一个具体的例子——编辑和查看模式的切换,对比传统DOM编程和React编程的不同实现方式,并且用Form对Dom编程进行优化,并探讨如何优化用户体验。

EditInPlace 就地编程

就地编辑(EditInPlace)是一种用户界面设计模式,允许用户直接在页面上修改内容,而无需跳转到单独的编辑页面或打开新的窗口。举个bilibili的栗子 image.png

1. 传统DOM编程实现

传统的DOM编程直接操作DOM元素,通过JavaScript来实现页面的动态效果。先上代码:

传统dom设计思路

  • DOM节点获取: 使用document.getElementById获取页面上的DOM节点。
  • 状态切换convertToTextconvertToEdit函数分别用于切换到文本状态和编辑状态。
  • 事件监听: 通过addEventListener为按钮和文本内容添加点击事件,实现状态的切换和内容的更新。
<!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 id="ep1">
      <span id="content">男德学院一等奖学金获得者</span>
      <input type="text" id="input" value="男德学院一等奖学金获得者">
      <input type="button" id="save" value="Save">
      <input type="button" id="cancel" value="Cancel">
    </div>
  </div>
  <script>
    // 获取DOM节点
    const content = document.getElementById('content');
    const input = document.getElementById('input');
    const save = document.getElementById('save');
    const cancel = document.getElementById('cancel');

    // 文本状态
    function convertToText() {
      input.style.display = 'none'; // 隐藏输入框
      save.style.display = 'none';  // 隐藏保存按钮
      cancel.style.display = 'none'; // 隐藏取消按钮
      content.style.display = 'inline'; // 显示文字
    }

    // 编辑状态
    function convertToEdit() {
      input.style.display = 'inline'; // 显示输入框
      save.style.display = 'inline';  // 显示保存按钮
      cancel.style.display = 'inline'; // 显示取消按钮
      content.style.display = 'none'; // 隐藏文字
    }

    // 初始化为文本状态
    convertToText();

    // 点击内容切换到编辑状态
    content.addEventListener('click', () => {
      convertToEdit();
      input.value = content.innerText; // 输入框的值等于文本内容
    });

    // 点击保存按钮,保存编辑内容
    save.addEventListener('click', () => {
      content.innerText = input.value;
      convertToText();
    });

    // 点击取消按钮,恢复到文本状态
    cancel.addEventListener('click', () => {
      convertToText();
    });
  </script>
</body>
</html>

先用dom进行简单事件实现:点击“save”和“cancel”进行事件处理。“save”按钮,点击对编辑好的内容进行保存,“cancel”取消编辑,保留原来状态。

image.png

2. 使用React编程

React是一种用于构建用户界面的JavaScript库,它通过虚拟DOM和组件化的方式简化了UI的开发。React的状态管理和生命周期方法使得管理复杂界面变得更加容易。

react设计思路:

  • 状态管理: 使用useState钩子管理一个状态数组items,每个项目包含idcontentmode属性。
  • 模式切换switchToViewModeswitchToEditMode函数用于切换项目的模式。
  • 内容更改handleContentChange函数用于处理文本内容的更改。
  • 条件渲染: 根据项目的mode属性,条件渲染编辑模式或查看模式。
// 导入useState 钩子,用于声明状态变量,让组件保留信息2(比如下面的列表内容content,模式mode)
import React, { useState } from 'react';
// 定义组件APP
function App() {
// 状态变量 items ,存储多个列表项,每个item 有唯一id ,初始状态为view
  const [items, setItems] = useState([
    { id: 1, content: '第一条内容', mode: 'view' },
    { id: 2, content: '第二条内容', mode: 'view' },
    { id: 3, content: '第三条内容', mode: 'view' }
  ]);
// 切换到查看模式 ,设置mode 为view
  const switchToViewMode = (id) => {
    setItems(items.map(item =>
      item.id === id ? { ...item, mode: 'view' } : item
    ));
  };

  const switchToEditMode = (id) => {
  // 更新setItems ,变量items数组,
    setItems(items.map(item =>
      item.id === id ? { ...item, mode: 'edit' } : item
    ));
  };
// 处理列表内容变化,编辑状态触发这个函数。负责更新content属性,并且通过setItems更新
// content 用户在textarea 里面输入的新内容
  const handleContentChange = (id, content) => {
  // items 从useState 钩子 获取 包含多个列表数组
    setItems(items.map(item =>
    // item.id === id: 检查当前遍历到的列表项的 id 是否与传入的 id 相等
      item.id === id ? { ...item, content } : item
    ));
  };
// 渲染列表
  return (
    <div>
      <ul>
        {items.map(item => (
         // 遍历获取 单个列表id
          <li key={item.id}>
            {item.mode === 'edit' ? (
              <div>
              // 多行文本编辑
                <textarea
                  value={item.content}
                  // onChange 事件处理器输入框输入内容调用编辑函数
                  onChange={(e) => handleContentChange(item.id, e.target.value)}
                />
                // 查看模式按钮
                <button onClick={() => switchToViewMode(item.id)}>查看模式</button>
              </div>
            ) : (
              <div>
                <p>{item.content}</p>
                <button onClick={() => switchToEditMode(item.id)}>编辑模式</button>
              </div>
            )}
          </li>
        ))}
      </ul>
    </div>
  );
}

export default App;

对于return 回来的渲染列表

  • 如果mode为edit,则显示一个textarea输入框和一个“查看模式”按钮。用户可以在输入框中编辑内容,点击按钮后切换回查看模式。
  • 如果mode为view,则显示一段文本和一个“编辑模式”按钮。点击按钮后切换到编辑模式。

值得回味,分析下面代码:

const handleContentChange = (id, content) => { 
    setItems(items.map(item => 
    item.id === id ? { ...item, content } : item 
    )); 
};
  • item.id === id: 检查当前遍历到的列表项的 id 是否与传入的 id 相等。
  • 如果相等,则创建一个新的对象 { ...item, content }:
  • { ...item } 表示将当前列表项的所有属性复制到新对象中。
  • content 表示将新输入的内容覆盖原来的 content 属性。
  • 如果不相等,则直接返回当前的 item 对象,不做任何修改。

3.用户体验优化

为了进一步优化用户体验,我们可以添加一些提示信息和动画效果,使用户操作更加直观和友好。Form表单

(1)传统DOM编程中的用户体验优化
<body>
  <div id="app">
  </div>
  <script src="./editInPlace.js"></script>
  <script>
  // 流程代码, 走向面向对象封装
  new EditInPlace(
    'ep1', 
    document.getElementById('app')
  );
  new EditInPlace(
    'ep2', 
    document.getElementById('app'),
    '好嗨哟'
  );
  </script>
</body>

image.png

代码分析:

  • 动画效果: 使用CSS动画为元素添加淡入效果,使用户操作更加平滑。
  • 封装类: 使用面向对象的方式封装编辑功能,提高代码的可维护性和复用性。
  • 事件监听: 为静态文本、保存按钮和取消按钮添加点击事件,实现模式的切换和内容的更新。 使用封装一个类进行类似登入等,进行编辑和查看事件的切换。

(2) prototype关联封装类

prototype 是一个对象,运行向构造方法添加属性和方法,这样通过这个构造函数创建的所有实例都共享属性和方法,很大程度节省空间,,所有实例都可以访问。 createElement 是document 对象内置方法。“挂载”,可以说是元素添加到父元素,也就是添加得到dom树

function EditInPlace(id, parent, value) {
  this.id = id; // 跨函数共享属性
  this.parent = parent || document.body;
  this.value = value || '这个家伙很懒,什么都没有留下';
  this.createElement(this.id);
}
EditInPlace.prototype.createElement = function(id) {
  // console.log(id);
  // 创建容器元素 div,挂载 id
  // <div id="ep1"></div>
  this.containerElement = document.createElement('div');
  this.containerElement.id = id;
  // 将 containerElement 元素添加到 parent 元素中,使其成为 parent 的子元素,方便在页面上显示和布局管理
  this.parent.appendChild(this.containerElement); 

  this.staticElement = document.createElement('span');
  this.staticElement.innerText = this.value; // 静态文本等于 value
  // 将静态文本 span 添加到 id 为 ep1 的 div 中
  this.containerElement.appendChild(this.staticElement); 
}

结论

无论是传统DOM编程还是React编程,都能实现编辑和查看模式的切换功能。然而,React通过虚拟DOM和组件化的方式,使得状态管理和界面更新更加简洁和高效。同时,通过添加动画效果和提示信息,可以显著提升用户的操作体验。

在实际开发中,还是要根据项目的需求和技术栈选择合适的开发方式,以实现最佳的用户体验。这样才能体现你的开发水平。

点赞.webp