React实时预览react-live源码分析
本文小编为大家详细介绍“React实时预览react-live源码分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“React实时预览react-live源码分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
引言
react-live
是一个 react
的实时编辑器,可直接编辑 react
代码,并实时预览。
本文针对的源码版本
src ├── components │ ├── Editor │ │ └── index.js │ └── Live │ ├── LiveContext.js │ ├── LiveEditor.js │ ├── LiveError.js │ ├── LivePreview.js │ ├── LiveProvider.js │ └── LiveProvider.test.js ├── constants │ └── theme.js ├── hoc │ └── withLive.js ├── index.js └── utils ├── test │ ├── errorBoundary.test.js │ ├── renderer.js │ └── transpile.test.js └── transpile ├── errorBoundary.js ├── evalCode.js ├── index.js └── transform.js
源码解读
输入内容
先看下导出内容,包括:
Editor
:编辑器LiveProvider
:实时编辑环境的Provider
,Context.Provider
LiveEditor
:实时编辑上下文的编辑器LiveError
:实时编辑上下文的报错LivePreview
:实时编辑上下文的预览LiveContext
:实时编辑的Context
withLive
:实时编辑上下文的HOC
文件结构和组件拆分一目了然。
Provider
先看下 Provider
,它提供了以下内容:
element
:实时编辑输出的元素error
:当前的报错信息code
:当前编辑的代码language
:代码语言theme
:代码编辑器主题disabled
:是否禁用onError
:报错的回调onChange
:代码编辑时的回调
Provider
用来收集代码变更,然后通过 transpileAsync
将代码编译生成组件实例:
function transpileAsync(newCode) { const errorCallback = error => { setState({ error: error.toString(), element: undefined }); }; try { const transformResult = transformCode ? transformCode(newCode) : newCode; return Promise.resolve(transformResult) .then(transformedCode => { const renderElement = element => setState({ error: undefined, element }); // Transpilation arguments const input = { code: transformedCode, scope }; if (noInline) { setState({ error: undefined, element: null }); // Reset output for async (no inline) evaluation renderElementAsync(input, renderElement, errorCallback); } else { renderElement(generateElement(input, errorCallback)); } }) .catch(errorCallback); } catch (e) { errorCallback(e); return Promise.resolve(); } }
renderElementAsync
可以先无视,主要是用于 noInline
模式下调用 render
进行渲染,逻辑与非 noInline
模式下类似。
generateElement
实时预览的核心部分就在这里了,它会将代码先进行编译,然后执行代码,取得返回值。
const generateElement = ({ code = '', scope = {} }, errorCallback) => { // NOTE: Remove trailing semicolon to get an actual expression. const codeTrimmed = code.trim().replace(/;$/, ''); // NOTE: Workaround for classes and arrow functions. const transformed = transform(`return (${codeTrimmed})`).trim(); return errorBoundary(evalCode(transformed, { React, ...scope }), errorCallback); };
代码如上,它会先去掉头尾空白,然后去掉结尾的分号,这一步是为了下一步的 return
拼接能够正常返回。通过 return
拼接让 react-live
能够支持下述语法直接渲染:
直接写一个匿名函数:
() => <h4>So functional. Much wow!</h4>;
直接写 jsx
:
<h4>Hello World!</h4>
单 class
组件:
class Comp extends React.Component { render() { return <center>component</center>; } }
不过也导致了一定的学习成本,如果写多个函数,多个组件,嵌套等情况下会让人觉得语法很奇怪。
transform
就是将代码通过 sucrase
进行转译,处理 jsx
、class
这些语法,可以理解为通过 babel
转译。
早期的 react-live
通过 buble
进行转译,能够支持 jsx
注释,现在由于 sucrase
不支持 jsx
注释,所以新版无法使用 jsx
注释来控制 jsx
渲染引擎。
/** @jsx mdx */ // 新版上述注释会失效
随后将转译的代码通过 evalCode
转换为 React element
,此处会将 scope
和 React
传入 evalCode
中。
const evalCode = (code, scope) => { const scopeKeys = Object.keys(scope); const scopeValues = scopeKeys.map(key => scope[key]); return new Function(...scopeKeys, code)(...scopeValues); };
evalCode
中使用 new Function
来构造函数,scope
就是在这里作为参数进行注入。如果对 new Function
不理解的可以看我之前一篇关于 JS
沙箱的文章。
errorBoundary
则是一个简单的 HOC
,用来捕获生成的组件运行时的错误信息,通过 errorCallback
抛出。
const errorBoundary = (Element, errorCallback) => { return class ErrorBoundary extends Component { componentDidCatch(error) { errorCallback(error); } render() { return typeof Element === 'function' ? <Element /> : React.isValidElement(Element) ? Element : null; } }; };
上面就是 react-live
能够实时预览的核心代码了。下面再看下其它几个组件,都比较简单。
其他组件
LivePreview
会接受 Provider
中的 Element
,将其渲染。
LiveError
接受 Provider
中的 error
进行渲染。
LiveEditor
则是接收 Provider
的 code
、language
、theme
、disabled
、onChange
,提供编辑功能。
它的编辑器则是通过 useEditable
编辑,Prism
进行代码高亮。
读到这里,这篇“React实时预览react-live源码分析”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注蜗牛博客行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:niceseo99@gmail.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
评论