เบ็ดตอบสนองขนาดเล็กเพื่อเปลี่ยนองค์ประกอบให้กลายเป็นพื้นผิวเนื้อหาที่สามารถเรนเดอร์และแก้ไขได้อย่างสมบูรณ์เช่นตัวแก้ไขรหัสโดยใช้ความพึงพอใจ (และเวทมนตร์)
useEditable เป็นตะขอเล็ก ๆ ที่ช่วยให้องค์ประกอบเป็น contenteditable ในขณะที่ยังคงสามารถแสดงผลได้อย่างเต็มที่ เหมาะอย่างยิ่งสำหรับการสร้างโปรแกรมแก้ไขรหัสขนาดเล็กหรือร้อยแก้ว textareas ในเพียง 2kB !
มันมีจุดมุ่งหมายเพื่อให้องค์ประกอบใด ๆ สามารถแก้ไขได้ในขณะที่ยังสามารถแสดงองค์ประกอบการตอบสนองปกติ - ไม่มี innerHTML และต้องจัดการกับการทำงานกับหรือแสดงผลกับ HTML ดิบหรือเริ่มโครงการแก้ไขเต็มตั้งแต่เริ่มต้น
ตรวจสอบการสาธิตเต็มรูปแบบบน codesandbox ด้วย prism-react-renderer !
ติดตั้งก่อน use-editable ก่อนกับ react :
yarn add use-editable
# or
npm install --save use-editable จากนั้นคุณจะสามารถนำเข้า useEditable และส่งผ่านการอ้างอิง HTMLElement และตัวจัดการ onChange
import React , { useState , useRef } from 'react' ;
import { useEditable } from 'use-editable' ;
const RainbowCode = ( ) => {
const [ code , setCode ] = useState ( 'function test() {}nconsole.log("hello");' ) ;
const editorRef = useRef ( null ) ;
useEditable ( editorRef , setCode ) ;
return (
< div className = "App" >
< pre
style = { { whiteSpace : 'pre-wrap' , fontFamily : 'monospace' } }
ref = { editorRef }
>
{ code . split ( / r?n / ) . map ( ( content , i , arr ) => (
< React . Fragment key = { i } >
< span style = { { color : `hsl( ${ ( ( i % 20 ) * 17 ) | 0 } , 80%, 50%)` } } >
{ content }
</ span >
{ i < arr . length - 1 ? 'n' : null }
</ React . Fragment >
) ) }
</ pre >
</ div >
) ;
} ; และเช่นเดียวกับที่เราได้ useEditable จาก editorRef ของเราซึ่งชี้ไปที่องค์ประกอบ <pre> ที่กำลังแสดงผลและไปยัง setCode ซึ่งขับเคลื่อนสถานะของเราที่มีรหัสบางส่วน
ห้องสมุดนี้ได้รับการทดสอบและ ควรทำงานอย่างถูกต้อง โดยใช้:
มีปัญหาที่ทราบกันดีใน IE 11 เนื่องจากวิธีการ MutationObserver ไม่สามารถอ่านโหนดข้อความที่ถูกลบออกผ่านทาง contenteditable
ตามเนื้อผ้ามีสามตัวเลือกเมื่อเลือกพื้นผิวการแก้ไขใน React ทั้งหนึ่งสามารถไปสำหรับโครงการขนาดใหญ่เช่น prosemirror / codemirror หรือที่คล้ายกันซึ่ง div การแก้ไขและการแสดงผล textarea และดังนั้นจึงค่อนข้างมีความเห็นหรือเป็นไปได้ที่จะใช้ความ contenteditable
ทั้งสามตัวเลือกไม่อนุญาตให้มีการปรับแต่งได้มากในแง่ของสิ่งที่ได้รับจริงหรือวางข้อ จำกัด ที่ไม่มีเหตุผลว่าการแสดงและจัดการเนื้อหาของการแก้ไขได้ง่ายเพียงใด
แล้วอะไรที่ทำให้การแสดงผลเป็นองค์ประกอบ contenteditable อย่างหนัก?
โดยทั่วไปแล้วนี่เป็นเรื่องยากเพราะพวกเขาแก้ไข DOM โดยตรง สิ่งนี้ทำให้ไลบรารีการเรนเดอร์ส่วนใหญ่เช่น React และ Preact จะสับสนเนื่องจาก DOM เสมือนจริงของพวกเขาไม่ตรงกับโครงสร้าง DOM จริงอีกต่อไป เพื่อป้องกันไม่ให้ปัญหานี้ use-editable สร้าง MutationObserver ซึ่งเฝ้าดูการเปลี่ยนแปลงทั้งหมดที่เกิดขึ้นกับองค์ประกอบ contenteditable ก่อนที่มันจะรายงานการเปลี่ยนแปลงเหล่านี้เพื่อตอบสนองมันจะย้อนกลับการเปลี่ยนแปลงทั้งหมดไปยัง DOM เพื่อให้ตอบสนองสิ่งที่คาดหวัง
นอกจากนี้ยังรักษาตำแหน่งปัจจุบันของ Caret การเลือกและคืนค่าเมื่อตอบสนองได้อัปเดต DOM เอง นี่เป็นเทคนิคที่ค่อนข้างธรรมดาสำหรับผู้แก้ไข contenteditable แต่การเพิ่ม MutationObserver เป็นสิ่งที่ช่วยให้ use-editable เพื่อให้ห้องสมุดดูอื่นอัปเดตเนื้อหาขององค์ประกอบ
ปัจจุบันเนื้อหาข้อความขององค์ประกอบที่แสดงผลจะต้องตรงกับการป้อนข้อมูลรหัสในที่สุดหรือการใช้งานของคุณจะต้องสามารถแปลงเนื้อหาข้อความที่แสดงผลกลับไปเป็นสิ่งที่คุณใช้เป็นสถานะ นี่คือข้อ จำกัด ของวิธีการทำงาน contenteditable ของการทำงานเนื่องจากพวกเขาจะจับเนื้อหา DOM จริงเท่านั้น เนื่องจาก use-editable ไม่ได้ตั้งใจที่จะเป็นส่วนประกอบทั้งหมดที่จัดการวงจรการเรนเดอร์จึงไม่จำเป็นต้องรักษาสถานะพิเศษใด ๆ แต่จะผ่านข้อความของ DOM กลับไปที่การโทร onChange
การใช้การเรียกกลับแบบ onChange คุณจะได้รับวัตถุ Position ที่อธิบายตำแหน่งเคอร์เซอร์หมายเลขบรรทัดปัจจุบันและเนื้อหาของบรรทัดขึ้นไปจนถึงเคอร์เซอร์ซึ่งมีประโยชน์สำหรับการตรวจสอบอัตโนมัติซึ่งสามารถนำไปใช้กับฟังก์ชั่น update ที่ useEditable เพื่ออัปเดตตำแหน่งเคอร์เซอร์
อาร์กิวเมนต์แรก คือ elementRef และยอมรับวัตถุ REF ของประเภท RefObject<HTMLElement> ซึ่งชี้ไปที่องค์ประกอบที่ควรแก้ไขได้ การอ้างอิงนี้ได้รับอนุญาตให้เป็น null หรือเปลี่ยนแปลงในระหว่างการรันไทม์ของเบ็ด ตราบใดที่การเปลี่ยนแปลงของการอ้างอิงถูกทริกเกอร์โดย React ทุกอย่างควรทำตามที่คาดไว้
อาร์กิวเมนต์ที่สอง คือ onChange และยอมรับการโทรกลับประเภท (text: string, pos: Position) => void ที่เรียกว่าเมื่อใดก็ตามที่เนื้อหาของการเปลี่ยนแปลง contenteditable สิ่งนี้จะต้องมีการตั้งค่าเพื่อให้มันจะกระตุ้นเนื้อหาขององค์ประกอบอีกครั้ง
text ที่ onChange ได้รับเป็นเพียงการแสดงข้อความของเนื้อหาขององค์ประกอบในขณะที่ Position ที่ได้รับประกอบด้วยตำแหน่งปัจจุบันของเคอร์เซอร์หมายเลขบรรทัด (zero-amexed) และเนื้อหาของบรรทัดปัจจุบันขึ้นไปจนถึงเคอร์เซอร์ซึ่งเป็นประโยชน์สำหรับ autosugstions
อาร์กิวเมนต์ที่สาม เป็นวัตถุ options ทางเลือก สิ่งนี้ยอมรับสองตัวเลือกในการเปลี่ยนพฤติกรรมการแก้ไขของ hook:
disabled ปิดใช้งานการแก้ไขบนการแก้ไขโดยการลบแอตทริบิวต์ contentEditable ออกจากมันอีกครั้งindentation อาจเป็นช่องว่างที่แสดงสำหรับการเยื้อง นอกจากนี้ยังช่วยให้พฤติกรรมคีย์แท็ Tab ที่ได้รับการปรับปรุงซึ่งจะเยื้องสายปัจจุบันหรืออุทิศบรรทัดปัจจุบันเมื่อมีการเปลี่ยนแปลง (โปรดทราบว่าสิ่งนี้จะทำให้ตัวแก้ไขทำหน้าที่เป็นกับดักโฟกัส!) เมื่อ options.indentation การกำหนดค่าใช้จ่ายแล้ว useEditable จะป้องกันการแทรกอักขระแท็บและจะแทรกจำนวนช่องว่างที่ระบุแทนซึ่งทำให้การจัดการคอลัมน์ง่ายขึ้นมาก
นอกจากนี้ตะขอ useEditable จะส่งคืนที่จับ Edit ด้วยวิธีการหลายวิธีดังที่บันทึกไว้ด้านล่าง
Edit.update(content: string): void
แทนที่เนื้อหาทั้งหมดของการแก้ไขในขณะที่ปรับตำแหน่ง Caret สิ่งนี้จะเปลี่ยน Caret โดยความยาวที่แตกต่างระหว่างเนื้อหาปัจจุบันและเนื้อหาที่ผ่าน
Edit.insert(append: string, offset?: number): void
แทรกข้อความใหม่ที่ตำแหน่ง Caret ในขณะที่ลบข้อความในช่วงของออฟเซ็ต (ซึ่งยอมรับการชดเชยเชิงลบ) ตัวอย่างเช่นเมื่อตั้ง offset เป็น -1 จากนั้นอักขระตัวเดียวจะถูกลบไปทางซ้ายของ Caret ก่อนที่จะแทรกข้อความใหม่ใด ๆ เมื่อมีการตั้งค่าเป็น 2 ตัวอักษรสองตัวทางด้านขวาของ carets จะถูกลบ ข้อความ append อาจถูกตั้งค่าเป็นสตริงว่างเพื่อใช้การลบเฉพาะโดยไม่ต้องแทรกข้อความใด ๆ เมื่อมีการเลือกข้อความใด ๆ มันจะถูกลบออกก่อนและ offset จะถูกละเว้น
Edit.move(pos: number | { row: number; column: number }): void
สิ่งนี้จะย้าย Caret ไปยังตำแหน่งที่ระบุ ตำแหน่งอาจเป็นดัชนีอักขระ ( number ) หรือพิกัดที่ระบุ row และ column แยกกัน
Edit.getState(): { text: string; position: Position }
วิธีนี้ช่วยให้ได้รับสถานะปัจจุบันของการแก้ไขซึ่งเหมือนกับสิ่งที่ onChange ได้รับ สิ่งนี้มีประโยชน์เมื่อเพิ่มการดำเนินการแก้ไขที่กำหนดเองในตัวจัดการคีย์ลงหรือเมื่อการเลียนแบบ onChange เป็นอย่างอื่นในขณะที่เลือกแก้ไขได้
react-live ซึ่งฉันเคยทำงานมีหนึ่งในบรรณาธิการเล็ก ๆ contenteditable (แต่ด้วยการอัปเดต HTML ดิบ)react-simple-code-editor เป็นไลบรารี (?) แรกที่ใช้การแยกการใช้งานแบบแยกและการแสดงผลพื้นผิวซึ่งนำเสนอสิ่งที่ API แก้ไขที่ดีควรมีลักษณะอย่างไรcodejar มีเทคนิคที่ดีที่สุดในการจัดการการเลือกแม้ว่าจะไม่มีการแก้ปัญหา Firefox นอกจากนี้ยังใช้การเน้น / การอัปเดต HTML ดิบcodemirror.next เป็นแหล่งที่มีค่าเพื่อดูเทคนิคที่แตกต่างกันเมื่อจัดการอินพุตข้อความและเทคนิคการอัปเดต DOM เสถียร: น่ากลัวไม่ได้วางแผนที่จะพัฒนาคุณสมบัติใหม่ ๆ สำหรับโครงการนี้ เรายังคงตอบสนองต่อรายงานข้อผิดพลาดและข้อกังวลด้านความปลอดภัย เรายังคงต้อนรับ PRS สำหรับโครงการนี้ แต่ PRS ที่มีคุณสมบัติใหม่ควรมีขนาดเล็กและง่ายต่อการรวมเข้าด้วยกันและไม่ควรรวมถึงการเปลี่ยนแปลง