{"id":124339,"date":"2020-06-23T21:24:20","date_gmt":"2020-06-23T13:24:20","guid":{"rendered":"http:\/\/4563.org\/?p=124339"},"modified":"2020-06-23T21:24:20","modified_gmt":"2020-06-23T13:24:20","slug":"%e5%bc%80%e6%ba%90%e4%b8%80%e4%b8%aa-react-%e6%8a%80%e6%9c%af%e6%a0%88%e7%9a%84%e9%ab%98%e6%89%a9%e5%b1%95%e6%80%a7%e5%af%8c%e6%96%87%e6%9c%ac%e7%bc%96%e8%be%91%e5%99%a8","status":"publish","type":"post","link":"http:\/\/4563.org\/?p=124339","title":{"rendered":"\u5f00\u6e90\u4e00\u4e2a React \u6280\u672f\u6808\u7684\u9ad8\u6269\u5c55\u6027\u5bcc\u6587\u672c\u7f16\u8f91\u5668"},"content":{"rendered":"<div>\n<div>\n<div>\n<h1>                  \u5f00\u6e90\u4e00\u4e2a React \u6280\u672f\u6808\u7684\u9ad8\u6269\u5c55\u6027\u5bcc\u6587\u672c\u7f16\u8f91\u5668               <\/h1>\n<p> <\/p>\n<div>\n<div> <span>\u8cc7\u6df1\u5927\u4f6c : camol <\/span>  <span><i><\/i> 3<\/span> <\/div>\n<div> <\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<div isfirst=\"1\"> <\/p>\n<p>\u6700\u8fd1\u6211\u82b1\u4e86\u70b9\u65f6\u95f4\uff0c\u628a\u4e4b\u524d\u4f7f\u7528\u65e7\u7248\u7684 slate \u6846\u67b6\u79ef\u7d2f\u7684\u4e00\u4e9b\u7ecf\u9a8c\u6574\u7406\u4e86\u4e0b\uff0c\u5f00\u6e90\u4e00\u4e2a\u57fa\u4e8e slate \u6846\u67b6\u7684 react \u6280\u672f\u6808\u7684\u9ad8\u6269\u5c55\u6027\u7684\u5bcc\u6587\u672c\u7f16\u8f91\u5668\u3002<\/p>\n<p>\u5b83\u7684\u9ad8\u6269\u5c55\u6027\u4e3b\u8981\u5728\u4e8e\uff1a<\/p>\n<ol>\n<li>\u652f\u6301\u81ea\u5b9a\u4e49\u5de5\u5177\u680f\uff1b<\/li>\n<li>\u652f\u6301\u81ea\u5b9a\u4e49\u8282\u70b9\u6e32\u67d3 \uff1b<\/li>\n<\/ol>\n<p>\u7b80\u8981 demo \u5982\u4e0b<\/p>\n<pre><code>import * as React from \"react\"; import ReactDom from \"react-dom\"; import EasyEditor from \"@camol\/easy-editor\";  class Editor extends React.Component {   html = \"\";    handleChange = (v: any) =&gt; {     console.log(\"change=&gt;&gt;&gt;\", v);     if (this.editorRef.current) {       \/\/ value to html       console.log(this.editorRef.current.convertor.serialize(v.change.value));     }   };    render() {     return &lt;EasyEditor value={\"&lt;p&gt;123&lt;\/p&gt;\"} onChange={this.handleChange} \/&gt;;   } }  ReactDom.render(&lt;Editor \/&gt;, document.getElementById(\"root\"));  <\/code><\/pre>\n<p><code>value<\/code> \u652f\u6301 slate \u7684 <code>Value<\/code> \u5b9e\u4f8b\uff0c\u4e5f\u652f\u6301 html \u3002\u6240\u4ee5\uff0c\u4f60\u53ef\u4ee5\u8c03\u7528 value.toJSON() \u53d6\u5f97 json \u683c\u5f0f\u7684\u6570\u636e \u6216\u8005\u8f6c\u6210 html \u5b58\u5165\u6570\u636e\u5e93\uff0c\u56de\u663e\u65f6\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528\u3002<\/p>\n<h2>\u652f\u6301\u81ea\u5b9a\u4e49\u5de5\u5177\u680f<\/h2>\n<p>\u76ee\u524d\uff0c\u7f16\u8f91\u5668\u5df2\u7ecf\u5185\u7f6e\u4e86\u4e00\u4e9b\u5de5\u5177\uff0c\u5982\u6587\u5b57\u52a0\u7c97\u3001\u659c\u4f53\u3001\u4e0b\u5212\u7ebf\u3001\u6587\u5b57\u5c45\u4e2d\u7b49\u529f\u80fd\u3002\u652f\u6301\u56fe\u7247\u548c\u89c6\u9891\u7684\u63d2\u5165\uff0c\u8d44\u6e90\u5730\u5740\u53ef\u4ee5\u901a\u8fc7 <code>beforeUpload<\/code> \u81ea\u5b9a\u4e49\u4e0a\u4f20\u903b\u8f91\u3002\u4ece\u526a\u8d34\u677f\u5185\u590d\u5236\u7c98\u8d34\u56fe\u7247\uff08\u5305\u62ec word \u5185\u590d\u5236\uff09\u7b49\u4e0a\u4f20\u6587\u4ef6\u90e8\u5206\u90fd\u4f1a\u5c1d\u8bd5\u8c03\u7528\u8be5\u51fd\u6570\u4ee5\u83b7\u53d6\u4e0a\u4f20\u540e\u7684\u8d44\u6e90\u5730\u5740\u3002\u4e0d\u4f7f\u7528\u81ea\u5b9a\u4e49\u4e0a\u4f20\u65f6\uff0c\u56fe\u7247\u5730\u5740\u9ed8\u8ba4\u4f7f\u7528 base64 \u683c\u5f0f\u3002<\/p>\n<p>\u60ac\u6d6e\u5de5\u5177\u680f\uff0c\u8003\u8651\u5230\u9009\u4e2d\u4e0d\u540c\u8282\u70b9\u65f6\u7684\u6e32\u67d3\u4e0d\u540c\uff0c\u8fd8\u6ca1\u8003\u8651\u597d\u5982\u4f55\u8bbe\u8ba1\uff0c\u6682\u65f6\u6ce8\u91ca\u6389\u4e86\u8fd9\u90e8\u5206\u529f\u80fd\uff0c\u540e\u9762\u4f1a\u5b8c\u5584\u3002<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/4563.org\/wp-content\/uploads\/2020\/06\/20200627_5ef7a97c2bdda.gif\" alt=\"\u5f00\u6e90\u4e00\u4e2a React \u6280\u672f\u6808\u7684\u9ad8\u6269\u5c55\u6027\u5bcc\u6587\u672c\u7f16\u8f91\u5668\" \/><\/p>\n<pre><code>\/\/ \u81ea\u5b9a\u4e49 \u63d2\u5165\u89c6\u9891\u7684\u64cd\u4f5c\u6309\u94ae class AudioControl extends React.Component {   inputRef = React.createRef();    handleClick = () =&gt; {     if (inputRef.current) {       inputRef.current.click();     }   };    handleChange = (e: React.ChangeEvent&lt;HTMLInputElement&gt;) =&gt; {     const file = e.target.files[0];     e.target.value = \"\";     if (file) {       if (this.props.beforeUpload) {         let url = await this.props.beforeUpload(file);         if (url) {           let change = this.props.change.focus().insertInline({             object: \"inline\",             type: \"audio\",             isVoid: true,             data: {               src: url,             },           });           this.props.update(change);         }       }     }   };    render() {     return (       &lt;span onMouseDown={this.handleClick}&gt;         &lt;span className=\"tool-insert-video\" \/&gt;         &lt;input           type=\"file\"           style={{ width: 0, height: 0, opacity: 0 }}           ref={this.inputRef}           onChange={this.handleChange}         \/&gt;       &lt;\/span&gt;     );   } } <\/code><\/pre>\n<pre><code>&lt;EasyEditor     value={\"&lt;p&gt;123&lt;\/p&gt;\"}     onChange={this.handleChange}     controls={[       [\"bold\", \"u\", \"image\"],       [         {           type: \"audio\",           component: (change, update, beforeUpload) =&gt; {             return (               &lt;AudioControl                 change={change}                 update={update}                 beforeUpload={beforeUpload}               \/&gt;             );           },         },       ],     ]}   \/&gt;  <\/code><\/pre>\n<h2>\u652f\u6301\u81ea\u5b9a\u4e49\u8282\u70b9\u6e32\u67d3<\/h2>\n<p>\u4f7f\u7528\u81ea\u5b9a\u4e49\u8282\u70b9\u6e32\u67d3\uff0c\u53ef\u4ee5\u5b9e\u73b0\u4e00\u4e9b\u9ad8\u7ea7\u529f\u80fd\uff0c\u5982\u56fe\u7247\u62d6\u62fd\u8c03\u6574\u5927\u5c0f\uff0c\u56fe\u7247\u60ac\u6d6e\u3001\u5de6\u73af\u7ed5\u3001\u53f3\u73af\u7ed5\u7b49\u529f\u80fd\uff0c\u6216\u8005\u8868\u683c\u7684\u62d6\u62fd\u8c03\u6574\u7b49\uff0c\u53c8\u6216\u8005\u662f\u7c7b\u4f3c\u77f3\u58a8\u6587\u6863\u7b49\u6dfb\u52a0\u6587\u4ef6\u9644\u4ef6\uff0c\u5c55\u793a\u5728\u6587\u6863\u4e2d\u7684\u529f\u80fd\u3002\u524d\u9762\u90e8\u5206\u529f\u80fd\u5df2\u7ecf\u5728\u7f16\u8f91\u5668\u5185\u5b9e\u73b0\u4e86\u3002<\/p>\n<p>\u8fd9\u91cc\u6211\u7b80\u8981\u5c55\u793a\u4e0b\u5982\u4f55\u81ea\u5b9a\u4e49\u6e32\u67d3 audio \u6807\u7b7e\uff1a<\/p>\n<pre><code>import * as React from \"react\"; import { DefaultTreeElement } from \"parse5\";  const plugin = {   type: \"node\", \/\/ node, mark   object: \"inline\", \/\/ block, inline   nodeType: \"super-audio\", \/\/ \u81ea\u5b9a\u4e49\u8282\u70b9\u7c7b\u578b   \/\/ \u81ea\u52a8\u89e3\u6790 html \u4e2d audio \u6807\u7b7e\uff0c\u751f\u6210 super-audio \u8282\u70b9   importer(el: DefaultTreeElement, next: Function): any {      if (el.tagName.toLowerCase() === \"audio\") {       return {         object: \"inline\", \/\/ block \u3001inline,         type: \"super-audio\",         isVoid: true,         data: {           src: el?.attrs?.find((n) =&gt; n.name === \"src\")?.value,         },         nodes: next(el.childNodes),       };     }   },   \/\/ \u8c03\u7528 editor.convertor.serialize(value) \u4f1a\u8c03\u7528\u8be5\u65b9\u6cd5\u5c06 super-audio \u8282\u70b9 \u8f6c\u6210 \u5bf9\u5e94\u7684 html \u5b58\u5165\u6570\u636e\u5e93   exporter(node: any, children: any): any {      let { className, src } = node.data.toJS();     return &lt;audio src={src} className={className}&gt;&lt;\/audio&gt;;   },   \/\/ \u81ea\u5b9a\u4e49\u6e32\u67d3\u65b9\u5f0f   render(     editor: any,     props: { attributes: any; children: any; node: any; isSelected: any }   ): any {     \/\/ @ts-ignore     const { attributes, children, node, isSelected } = props;     const src = node.data.get(\"src\");     return (       &lt;span {...attributes}&gt;         &lt;audio src={src} controls&gt;           {children}         &lt;\/audio&gt;       &lt;\/span&gt;     );   }, };  export default plugin; <\/code><\/pre>\n<pre><code>&lt;EasyEditor     value=\"&lt;audio src='xxxxx.mp3'&gt;&lt;\/audio&gt;&lt;p&gt; &lt;\/p&gt;\"     ...     plugins={[audioPlugin]} \/&gt; <\/code><\/pre>\n<p>\u76ee\u524d\u7f16\u8f91\u5668\u4e2d\u7684\u89c6\u9891\u64ad\u653e\u63d2\u4ef6\u5c31\u662f\u4f7f\u7528\u8be5\u7279\u6027\u5b9e\u73b0\u7684\uff0c\u96c6\u6210\u4e86 plyr-react\uff0c\u652f\u6301 mp4 \u3001webm \uff08\u5176\u4ed6\u683c\u5f0f\u540e\u9762\u4f1a\u652f\u6301\uff09\u3002 <img decoding=\"async\" src=\"http:\/\/4563.org\/wp-content\/uploads\/2020\/06\/20200627_5ef7a99021e1e.png\" alt=\"\u5f00\u6e90\u4e00\u4e2a React \u6280\u672f\u6808\u7684\u9ad8\u6269\u5c55\u6027\u5bcc\u6587\u672c\u7f16\u8f91\u5668\" \/><\/p>\n<h2>\u6c42\u652f\u6301<\/h2>\n<p>\u867d\u7136\u53ef\u80fd\u8fd8\u6709\u4e9b\u95ee\u9898\uff0c\u4f46\u6211\u540e\u9762\u4f1a\u957f\u671f\u7ef4\u62a4\u7684\uff0c\u5e0c\u671b\u5bf9\u9700\u8981\u7684\u540c\u5b66\u4eec\u6709\u5e2e\u52a9 \uff1a\uff09\u3002<\/p>\n<p>\u6700\u540e\u8d34\u4e00\u4e0b\u8be5\u9879\u76ee\u7684 github \u5730\u5740\uff0c\u6c42\u652f\u6301\uff0c\u6c42 star \uff01<\/p>\n<p>https:\/\/github.com\/kanweiwei\/easy-editor<\/p>\n<\/p><\/div>\n<div> <b>\u5927\u4f6c\u6709\u8a71\u8aaa<\/b> (<span>0<\/span>)        <\/div>\n<div> <\/div>\n<\/p><\/div>\n<\/p><\/div>\n<ul>\n<li>\n","protected":false},"excerpt":{"rendered":"<p>\u5f00\u6e90\u4e00\u4e2a React \u6280\u672f\u6808\u7684\u9ad8\u6269&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[],"tags":[],"_links":{"self":[{"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/posts\/124339"}],"collection":[{"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/4563.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=124339"}],"version-history":[{"count":0,"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/posts\/124339\/revisions"}],"wp:attachment":[{"href":"http:\/\/4563.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=124339"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/4563.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=124339"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/4563.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=124339"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}