Guides pas à pas
Définir des éléments personnalisés
4 min
dans notre exemple précédent, nous avons commencé par un paragraphe, mais nous n'avons jamais vraiment dit à slate quoi que ce soit sur le paragraphe type de bloc nous avons simplement laissé slate utiliser son rendu par défaut interne, qui utilise un vieux \<div> mais ce n'est pas tout ce que vous pouvez faire slate vous permet de définir n'importe quel type de blocs personnalisés que vous souhaitez, comme des citations, des blocs de code, des éléments de liste, etc nous allons vous montrer comment commençons par notre application précédente const app = () => { const editor = usememo(() => withreact(createeditor()), \[]) const \[value, setvalue] = usestate(\[ { type 'paragraph', children \[{ text 'a line of text in a paragraph ' }], }, ]) return ( \<slate editor={editor} value={value} onchange={value => setvalue(value)}> \<editable onkeydown={event => { if (event key === '&') { event preventdefault() editor inserttext('and') } }} /> \</slate> ) } maintenant, ajoutons des "blocs de code" à notre éditeur le problème est que les blocs de code ne seront pas simplement rendus comme un paragraphe ordinaire, ils devront être rendus différemment pour que cela se produise, nous devons définir un "rendu" pour les éléments de code les rendus d'éléments sont juste des composants react simples, comme ceci // define a react component renderer for our code blocks const codeelement = props => { return ( \<pre { props attributes}> \<code>{props children}\</code> \</pre> ) } assez facile vous voyez la props attributes référence ? slate passe les attributs qui doivent être rendus sur l'élément le plus haut de vos blocs, afin que vous n'ayez pas à les construire vous même vous devez mélanger les attributs dans votre composant et voyez cette props children référence ? slate rendra automatiquement tous les enfants d'un bloc pour vous, puis les passera comme n'importe quel autre composant react, via props children de cette façon, vous n'avez pas à vous embêter avec le rendu des nœuds de texte appropriés ou quoi que ce soit de ce genre vous devez rendre les enfants comme la feuille la plus basse dans votre composant et voici un composant pour les éléments "par défaut" const defaultelement = props => { return \<p { props attributes}>{props children}\</p> } maintenant, ajoutons ce rendu à notre éditeur const app = () => { const editor = usememo(() => withreact(createeditor()), \[]) const \[value, setvalue] = usestate(\[ { type 'paragraph', children \[{ text 'a line of text in a paragraph ' }], }, ]) // define a rendering function based on the element passed to `props` we use // `usecallback` here to memoize the function for subsequent renders const renderelement = usecallback(props => { switch (props element type) { case 'code' return \<codeelement { props} /> default return \<defaultelement { props} /> } }, \[]) return ( \<slate editor={editor} value={value} onchange={value => setvalue(value)}> \<editable // pass in the `renderelement` function renderelement={renderelement} onkeydown={event => { if (event key === '&') { event preventdefault() editor inserttext('and') } }} /> \</slate> ) } const codeelement = props => { return ( \<pre { props attributes}> \<code>{props children}\</code> \</pre> ) } const defaultelement = props => { return \<p { props attributes}>{props children}\</p> } d'accord, mais maintenant nous aurons besoin d'un moyen pour que l'utilisateur puisse réellement transformer un bloc en bloc de code alors changeons notre onkeydown fonction pour ajouter un raccourci ``ctrl ``` qui fait exactement cela // import the `editor` and `transforms` helpers from slate import { editor, transforms } from 'slate' const app = () => { const editor = usememo(() => withreact(createeditor()), \[]) const \[value, setvalue] = usestate(\[ { type 'paragraph', children \[{ text 'a line of text in a paragraph ' }], }, ]) const renderelement = usecallback(props => { switch (props element type) { case 'code' return \<codeelement { props} /> default return \<defaultelement { props} /> } }, \[]) return ( \<slate editor={editor} value={value} onchange={value => setvalue(value)}> \<editable renderelement={renderelement} onkeydown={event => { if (event key === '`' && event ctrlkey) { // prevent the "`" from being inserted by default event preventdefault() // otherwise, set the currently selected blocks type to "code" transforms setnodes( editor, { type 'code' }, { match n => editor isblock(editor, n) } ) } }} /> \</slate> ) } const codeelement = props => { return ( \<pre { props attributes}> \<code>{props children}\</code> \</pre> ) } const defaultelement = props => { return \<p { props attributes}>{props children}\</p> } maintenant, si vous appuyez sur ``ctrl ``` le bloc dans lequel se trouve votre curseur devrait se transformer en un bloc de code ! magie ! mais nous avons oublié une chose lorsque vous appuyez à nouveau sur ``ctrl ``` , cela devrait changer le bloc de code en un paragraphe pour ce faire, nous devrons ajouter un peu de logique pour changer le type que nous définissons en fonction de savoir si l'un des blocs actuellement sélectionnés est déjà un bloc de code const app = () => { const editor = usememo(() => withreact(createeditor()), \[]) const \[value, setvalue] = usestate(\[ { type 'paragraph', children \[{ text 'a line of text in a paragraph ' }], }, ]) const renderelement = usecallback(props => { switch (props element type) { case 'code' return \<codeelement { props} /> default return \<defaultelement { props} /> } }, \[]) return ( \<slate editor={editor} value={value} onchange={value => setvalue(value)}> \<editable renderelement={renderelement} onkeydown={event => { if (event key === '`' && event ctrlkey) { event preventdefault() // determine whether any of the currently selected blocks are code blocks const \[match] = editor nodes(editor, { match n => n type === 'code', }) // toggle the block type depending on whether there's already a match transforms setnodes( editor, { type match ? 'paragraph' 'code' }, { match n => editor isblock(editor, n) } ) } }} /> \</slate> ) } et voilà ! si vous appuyez sur ``ctrl ``` tout en étant dans un bloc de code, cela devrait redevenir un paragraphe !
