0
0
Lập trình
Hưng Nguyễn Xuân 1
Hưng Nguyễn Xuân 1xuanhungptithcm

Hướng Dẫn Xây Dựng Trình Soạn Thảo Văn Bản RichText Chuyên Nghiệp Với TipTap và React Kèm Tính Năng Mentions

Đăng vào 1 tháng trước

• 6 phút đọc

Chủ đề:

Development

Giới thiệu

Bạn đang tìm kiếm một giải pháp để phát triển một trình soạn thảo RichText tích hợp trong ứng dụng React của mình? TipTap là một thư viện tuyệt vời, dễ dàng tùy chỉnh và mạnh mẽ, giúp bạn xây dựng trình soạn thảo văn bản hoàn hảo. Bài viết này sẽ hướng dẫn bạn từng bước để tích hợp TipTap, thêm tính năng mentions, và khắc phục một số vấn đề thường gặp trong quá trình phát triển.

Bước 1: Cài Đặt Các Thư Viện Cần Thiết

Trước tiên, bạn cần cài đặt các thư viện cần thiết cho TipTap:

bash Copy
npm install @tiptap/react @tiptap/starter-kit @tiptap/extension-mention

Bước 2: Tạo Trình Soạn Thảo RichText Cơ Bản

Chúng ta sẽ bắt đầu bằng cách tạo một thành phần RichTextEditor. Dưới đây là một ví dụ đơn giản để thực hiện điều này:

javascript Copy
import { useEditor, EditorContent } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';

export const RichTextEditor = ({ content, onChange }) => {
  const editor = useEditor({
    extensions: [StarterKit],
    content: content,
    onUpdate: ({ editor }) => {
      onChange(editor.getHTML());
    },
  });
  return <EditorContent editor={editor} />;
};

Bước 3: Thêm Tính Năng Mention

Tính năng mentions giúp tăng cường sự tương tác của người dùng. Để thêm tính năng này, chúng ta sẽ cài đặt và cấu hình Mention extension từ @tiptap/extension-mention.

javascript Copy
import Mention from '@tiptap/extension-mention';

export const RichTextEditor = ({ content, onChange, mentions }) => {
  const editor = useEditor({
    extensions: [
      StarterKit,
      Mention.configure({
        HTMLAttributes: { class: 'mention' },
        suggestion: {
          items: ({ query }) =>
            mentions.filter(item => item.display.toLowerCase().includes(query.toLowerCase())).slice(0, 5),
          render: () => {
            let component;
            let popup;
            return {
              onStart: (props) => {
                popup = document.createElement('div');
                popup.className = 'mention-popup';
                document.body.appendChild(popup);
                component = {
                  updateProps: () => {
                    popup.innerHTML = `
                      <div class="items">
                        ${props.items.map(item => `
                          <button class="item ${item.selected ? 'is-selected' : ''}">${item.display}</button>
                        `).join('')}  
                      </div>
                    `;
                  },
                  destroy: () => popup.remove(),
                };
                popup.addEventListener('click', (e) => {
                  const button = e.target.closest('button');
                  if (button) {
                    const index = Array.from(popup.querySelectorAll('.item')).indexOf(button);
                    props.command({ id: props.items[index].id, label: props.items[index].display });
                  }
                });
                component.updateProps();
              },
              onExit: () => component?.destroy(),
            };
          },
        },
      }),
    ],
    content,
    onUpdate: ({ editor }) => onChange(editor.getHTML()),
  });
  return <EditorContent editor={editor} />;
};

Bước 4: Định Dạng Popup Cho Tính Năng Mention

Để tăng cường khả năng sử dụng và tính trực quan của mentions, bạn có thể thêm các kiểu sau:

css Copy
.mention-popup {
  background: white;
  border-radius: 8px;
  box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.1);
  padding: 8px;
  position: absolute;
  z-index: 1000;
}
.mention-popup .items {
  display: flex;
  flex-direction: column;
}
.mention-popup .item {
  padding: 8px;
  cursor: pointer;
  border-radius: 4px;
}
.mention-popup .item:hover,
.mention-popup .item.is-selected {
  background: #f0f0f0;
}

Bước 5: Khắc Phục Một Số Vấn Đề Thường Gặp

1. Vấn Đề Với Con Trỏ Nhảy

Đối với vấn đề con trỏ nhảy khi gõ, hãy giữ nguyên vị trí con trỏ bằng cách cập nhật nội dung như sau:

javascript Copy
const editor = useEditor({
  extensions: [StarterKit],
  content,
  onUpdate: ({ editor }) => {
    const selection = editor.state.selection;
    onChange(editor.getHTML());
    editor.commands.setTextSelection(selection);
  },
});

2. Thiếu Hiện Placeholder

Nếu placeholder không hiển thị, hãy sử dụng tiện ích mở rộng Placeholder:

javascript Copy
import Placeholder from '@tiptap/extension-placeholder';
const editor = useEditor({
  extensions: [
    StarterKit,
    Placeholder.configure({ placeholder: 'Hãy nhập nội dung ở đây...' }),
  ],
});

3. Danh Sách Gợi Ý Mention Không Hiển Thị

Kiểm tra lại phương thức suggestion.items để đảm bảo lọc và trả về danh sách hợp lệ.

Bước 6: Tích Hợp Vào Ứng Dụng Của Bạn

Cuối cùng, để tích hợp trình soạn thảo vào ứng dụng, bạn có thể sử dụng RichTextEditor trong một form. Ví dụ:

javascript Copy
import React from 'react';

const NotificationForm = ({ mentions, onSubmit }) => {
  const [content, setContent] = React.useState('');
  return (
    <form onSubmit={() => onSubmit(content)}>
      <RichTextEditor content={content} onChange={setContent} mentions={mentions} />
      <button type="submit">Gửi</button>
    </form>
  );
};

Kết Luận

Với TipTap, việc xây dựng một trình soạn thảo RichText chuyên nghiệp và thân thiện với người dùng thật sự đơn giản và nhanh chóng. Tính năng mentions không chỉ tăng cường khả năng tương tác mà còn làm cho ứng dụng của bạn trở nên sinh động và hấp dẫn hơn. Để có thêm thông tin chi tiết, hãy truy cập vào trang web chính thức của TipTap.
source: viblo

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào