스키마 정의
커스텀 블록 노드 타입의 스키마 정의:
{
customBlock: {
content: 'block*',
group: 'block',
attrs: {
type: { default: '' },
data: { default: '{}' }
},
}
}모델 표현
모델 표현 예제:
{
type: 'customBlock',
attrs: {
type: 'my-custom-block',
data: JSON.stringify({ custom: 'data' })
},
children: []
}HTML 직렬화
모델을 HTML로 변환:
function serializeCustomBlock(node) {
return '<div data-type="custom-block" data-block-type="' + node.attrs.type +
'" data-block-data="' + escapeHtml(node.attrs.data) + '">' +
serializeChildren(node.children) + '</div>';
}HTML 역직렬화
HTML을 모델로 파싱:
function parseCustomBlock(domNode) {
return {
type: 'customBlock',
attrs: {
type: domNode.getAttribute('data-block-type') || '',
data: domNode.getAttribute('data-block-data') || '{}'
},
children: Array.from(domNode.childNodes)
.map(node => parseNode(node))
.filter(Boolean)
};
}뷰 연동
뷰 연동 노트: 이 노드 타입을 뷰 레이어에서 구현할 때 contenteditable 동작, 선택 처리, 이벤트 관리에 특히 주의하세요.
뷰 연동 코드:
// 커스텀 블록 렌더링
const customBlock = document.createElement('div');
customBlock.setAttribute('data-type', 'custom-block');
customBlock.setAttribute('data-block-type', node.attrs.type);
customBlock.setAttribute('data-block-data', node.attrs.data);
customBlock.contentEditable = 'true';
node.children.forEach(child => {
customBlock.appendChild(renderNode(child));
});일반적인 문제
일반적인 함정: 이 노드 타입을 구현할 때 자주 발생하는 문제들입니다. 구현 전에 주의 깊게 검토하세요.
일반적인 문제 및 해결 방법:
// 문제: 커스텀 블록 타입 등록
// 해결: 커스텀 블록 렌더러 등록
const customBlockRenderers = {
'my-custom-block': (node, data) => {
// 커스텀 렌더링 로직
}
};
// 문제: 커스텀 블록 데이터 검증
// 해결: 커스텀 블록 데이터 검증
function validateCustomBlockData(data, type) {
// 블록 타입에 따라 검증
return true;
}구현
완전한 구현 예제:
class CustomBlockNode {
constructor(attrs, children) {
this.type = 'customBlock';
this.attrs = {
type: attrs?.type || '',
data: attrs?.data || '{}'
};
this.children = children || [];
}
toDOM() {
const customBlock = document.createElement('div');
customBlock.setAttribute('data-type', 'custom-block');
customBlock.setAttribute('data-block-type', this.attrs.type);
customBlock.setAttribute('data-block-data', this.attrs.data);
this.children.forEach(child => {
customBlock.appendChild(child.toDOM());
});
return customBlock;
}
static fromDOM(domNode) {
return new CustomBlockNode(
{
type: domNode.getAttribute('data-block-type') || '',
data: domNode.getAttribute('data-block-data') || '{}'
},
Array.from(domNode.childNodes)
.map(node => parseNode(node))
.filter(Boolean)
);
}
}